diff options
| -rw-r--r-- | tests/common/sync_helpers.rs | 101 |
1 files changed, 90 insertions, 11 deletions
diff --git a/tests/common/sync_helpers.rs b/tests/common/sync_helpers.rs index 5fc2ad7..daa684b 100644 --- a/tests/common/sync_helpers.rs +++ b/tests/common/sync_helpers.rs | |||
| @@ -1071,12 +1071,16 @@ pub struct SyncTestResult { | |||
| 1071 | pub syncing_relay: TestRelay, | 1071 | pub syncing_relay: TestRelay, |
| 1072 | pub maintainer_keys: Keys, | 1072 | pub maintainer_keys: Keys, |
| 1073 | pub repo_coord: String, | 1073 | pub repo_coord: String, |
| 1074 | // Keep SmartGitServer alive for the test duration | ||
| 1075 | _git_server: Option<super::git_server::SmartGitServer>, | ||
| 1076 | // Keep temp dir alive for the test duration | ||
| 1077 | _git_temp_dir: Option<tempfile::TempDir>, | ||
| 1074 | } | 1078 | } |
| 1075 | 1079 | ||
| 1076 | /// Helper to send an event to a relay | 1080 | /// Helper to send an event to a relay |
| 1077 | /// | 1081 | /// |
| 1078 | /// Creates a temporary client, sends the event, and disconnects. | 1082 | /// Creates a temporary client, sends the event, and disconnects. |
| 1079 | async fn send_to_relay(relay: &TestRelay, event: &Event) -> Result<(), String> { | 1083 | pub async fn send_to_relay(relay: &TestRelay, event: &Event) -> Result<(), String> { |
| 1080 | let temp_keys = Keys::generate(); | 1084 | let temp_keys = Keys::generate(); |
| 1081 | let client = TestClient::new(relay.url(), temp_keys).await?; | 1085 | let client = TestClient::new(relay.url(), temp_keys).await?; |
| 1082 | client.send_event(event).await?; | 1086 | client.send_event(event).await?; |
| @@ -1084,6 +1088,17 @@ async fn send_to_relay(relay: &TestRelay, event: &Event) -> Result<(), String> { | |||
| 1084 | Ok(()) | 1088 | Ok(()) |
| 1085 | } | 1089 | } |
| 1086 | 1090 | ||
| 1091 | /// Helper to send an event to a relay by URL | ||
| 1092 | /// | ||
| 1093 | /// Creates a temporary client, sends the event, and disconnects. | ||
| 1094 | pub async fn send_to_relay_url(relay_url: &str, event: &Event) -> Result<(), String> { | ||
| 1095 | let temp_keys = Keys::generate(); | ||
| 1096 | let client = TestClient::new(relay_url, temp_keys).await?; | ||
| 1097 | client.send_event(event).await?; | ||
| 1098 | client.disconnect().await; | ||
| 1099 | Ok(()) | ||
| 1100 | } | ||
| 1101 | |||
| 1087 | /// Unified sync test helper that automatically determines sync mode. | 1102 | /// Unified sync test helper that automatically determines sync mode. |
| 1088 | /// | 1103 | /// |
| 1089 | /// This function sets up a complete sync test environment by determining whether | 1104 | /// This function sets up a complete sync test environment by determining whether |
| @@ -1119,6 +1134,10 @@ async fn send_to_relay(relay: &TestRelay, event: &Event) -> Result<(), String> { | |||
| 1119 | /// // Assert comment synced to result.syncing_relay | 1134 | /// // Assert comment synced to result.syncing_relay |
| 1120 | /// ``` | 1135 | /// ``` |
| 1121 | pub async fn run_sync_test(historic_events: &[Event], live_events: &[Event]) -> SyncTestResult { | 1136 | pub async fn run_sync_test(historic_events: &[Event], live_events: &[Event]) -> SyncTestResult { |
| 1137 | use super::purgatory_helpers::{ | ||
| 1138 | create_state_event, create_test_repo_with_commit, push_to_relay, CommitVariant, | ||
| 1139 | }; | ||
| 1140 | |||
| 1122 | // Validate usage - cannot provide events in both slices | 1141 | // Validate usage - cannot provide events in both slices |
| 1123 | let historic_mode = !historic_events.is_empty(); | 1142 | let historic_mode = !historic_events.is_empty(); |
| 1124 | let live_mode = !live_events.is_empty(); | 1143 | let live_mode = !live_events.is_empty(); |
| @@ -1137,39 +1156,97 @@ pub async fn run_sync_test(historic_events: &[Event], live_events: &[Event]) -> | |||
| 1137 | // 2. Start source relay | 1156 | // 2. Start source relay |
| 1138 | let source = TestRelay::start().await; | 1157 | let source = TestRelay::start().await; |
| 1139 | 1158 | ||
| 1140 | // 3. Create keys and announcement listing both relays | 1159 | // 3. Create local git repo with a commit |
| 1160 | let git_temp_dir = tempfile::tempdir().expect("Failed to create temp dir for git repo"); | ||
| 1161 | let commit_hash = | ||
| 1162 | create_test_repo_with_commit(git_temp_dir.path(), CommitVariant::StateTest) | ||
| 1163 | .expect("Failed to create test git repo"); | ||
| 1164 | |||
| 1165 | // 4. Create keys and build URLs | ||
| 1141 | let keys = Keys::generate(); | 1166 | let keys = Keys::generate(); |
| 1142 | let announcement = | 1167 | let npub = keys |
| 1143 | create_repo_announcement(&keys, &[&source.domain(), &syncing_domain], "test-repo"); | 1168 | .public_key() |
| 1169 | .to_bech32() | ||
| 1170 | .expect("Failed to convert public key to npub"); | ||
| 1171 | |||
| 1172 | // Clone URLs: source relay HTTP endpoint is where git data lives | ||
| 1173 | // The syncing relay's purgatory will fetch from source's clone URL | ||
| 1174 | let clone_url_source = format!("http://{}/{}/{}.git", source.domain(), npub, "test-repo"); | ||
| 1175 | let clone_url_syncing = format!( | ||
| 1176 | "http://{}/{}/{}.git", | ||
| 1177 | syncing_domain, npub, "test-repo" | ||
| 1178 | ); | ||
| 1179 | |||
| 1180 | let clone_urls = vec![clone_url_source.clone(), clone_url_syncing.clone()]; | ||
| 1181 | let relay_urls = vec![ | ||
| 1182 | format!("ws://{}", source.domain()), | ||
| 1183 | format!("ws://{}", syncing_domain), | ||
| 1184 | ]; | ||
| 1144 | 1185 | ||
| 1145 | // 4. Send announcement + historic events to source BEFORE syncing relay starts | 1186 | let announcement = EventBuilder::new(Kind::GitRepoAnnouncement, "Repository state") |
| 1187 | .tags(vec![ | ||
| 1188 | Tag::identifier("test-repo"), | ||
| 1189 | Tag::custom(TagKind::custom("clone"), clone_urls.clone()), | ||
| 1190 | Tag::custom(TagKind::custom("relays"), relay_urls.clone()), | ||
| 1191 | ]) | ||
| 1192 | .sign_with_keys(&keys) | ||
| 1193 | .expect("Failed to sign repo announcement"); | ||
| 1194 | |||
| 1195 | // 5. Create state event referencing the commit | ||
| 1196 | let state_event = create_state_event( | ||
| 1197 | &keys, | ||
| 1198 | "test-repo", | ||
| 1199 | &[("main", &commit_hash)], | ||
| 1200 | &[], | ||
| 1201 | &clone_urls.iter().map(|s| s.as_str()).collect::<Vec<_>>(), | ||
| 1202 | &relay_urls.iter().map(|s| s.as_str()).collect::<Vec<_>>(), | ||
| 1203 | ) | ||
| 1204 | .expect("Failed to create state event"); | ||
| 1205 | |||
| 1206 | // 6. Send announcement + state event to source (both go to purgatory) | ||
| 1146 | send_to_relay(&source, &announcement) | 1207 | send_to_relay(&source, &announcement) |
| 1147 | .await | 1208 | .await |
| 1148 | .expect("Failed to send announcement"); | 1209 | .expect("Failed to send announcement"); |
| 1210 | send_to_relay(&source, &state_event) | ||
| 1211 | .await | ||
| 1212 | .expect("Failed to send state event"); | ||
| 1213 | |||
| 1214 | // 7. Git push to source relay → releases both announcement and state event from purgatory | ||
| 1215 | push_to_relay(git_temp_dir.path(), &source.domain(), &npub, "test-repo") | ||
| 1216 | .expect("Failed to push git data to source relay"); | ||
| 1217 | |||
| 1218 | // 8. Wait for source relay to process the push and release events from purgatory | ||
| 1219 | tokio::time::sleep(Duration::from_secs(2)).await; | ||
| 1220 | |||
| 1221 | // 9. Send historic events to source BEFORE syncing relay starts | ||
| 1149 | for event in historic_events { | 1222 | for event in historic_events { |
| 1150 | send_to_relay(&source, event) | 1223 | send_to_relay(&source, event) |
| 1151 | .await | 1224 | .await |
| 1152 | .expect("Failed to send historic event"); | 1225 | .expect("Failed to send historic event"); |
| 1153 | } | 1226 | } |
| 1154 | 1227 | ||
| 1155 | // 5. Start syncing relay (connects to source) | 1228 | // 10. Start syncing relay (connects to source) |
| 1156 | let syncing = | 1229 | let syncing = |
| 1157 | TestRelay::start_on_port_with_options(syncing_port, Some(source.url().into()), false).await; | 1230 | TestRelay::start_on_port_with_options(syncing_port, Some(source.url().into()), false).await; |
| 1158 | 1231 | ||
| 1159 | // 6. Wait for sync connection to establish | 1232 | // 11. Wait for sync connection to establish |
| 1160 | let _ = wait_for_sync_connection(syncing.url(), 1, Duration::from_secs(5)).await; | 1233 | let _ = wait_for_sync_connection(syncing.url(), 1, Duration::from_secs(5)).await; |
| 1161 | 1234 | ||
| 1162 | // 7. Send live events AFTER connection established | 1235 | // 12. Send live events AFTER connection established |
| 1163 | for event in live_events { | 1236 | for event in live_events { |
| 1164 | send_to_relay(&source, event) | 1237 | send_to_relay(&source, event) |
| 1165 | .await | 1238 | .await |
| 1166 | .expect("Failed to send live event"); | 1239 | .expect("Failed to send live event"); |
| 1167 | } | 1240 | } |
| 1168 | 1241 | ||
| 1169 | // 8. Allow sync to complete | 1242 | // 13. Allow sync + purgatory promotion to complete on the syncing relay. |
| 1170 | tokio::time::sleep(Duration::from_millis(100)).await; | 1243 | // The syncing relay receives the announcement (goes to purgatory) and state event. |
| 1244 | // The purgatory sync loop (1s interval) fetches git data from source's clone URL | ||
| 1245 | // (http://source-domain/npub/test-repo.git) and releases the announcement. | ||
| 1246 | // We wait up to 8s to allow time for this. | ||
| 1247 | tokio::time::sleep(Duration::from_secs(8)).await; | ||
| 1171 | 1248 | ||
| 1172 | // 9. Compute repo coordinate before moving keys | 1249 | // 14. Compute repo coordinate before moving keys |
| 1173 | let coordinate = repo_coord(&keys, "test-repo"); | 1250 | let coordinate = repo_coord(&keys, "test-repo"); |
| 1174 | 1251 | ||
| 1175 | SyncTestResult { | 1252 | SyncTestResult { |
| @@ -1177,6 +1254,8 @@ pub async fn run_sync_test(historic_events: &[Event], live_events: &[Event]) -> | |||
| 1177 | syncing_relay: syncing, | 1254 | syncing_relay: syncing, |
| 1178 | maintainer_keys: keys, | 1255 | maintainer_keys: keys, |
| 1179 | repo_coord: coordinate, | 1256 | repo_coord: coordinate, |
| 1257 | _git_server: None, | ||
| 1258 | _git_temp_dir: Some(git_temp_dir), | ||
| 1180 | } | 1259 | } |
| 1181 | } | 1260 | } |
| 1182 | 1261 | ||