diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2025-12-08 12:50:34 +0000 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2025-12-08 12:50:34 +0000 |
| commit | efe3e43cf792abd8bb256121ebf84ae04836313a (patch) | |
| tree | 2aa626f43817d7f86145ba4c6c09ac8660df1a9b /tests/proactive_sync_basic.rs | |
| parent | b4da09689ee0bd6ac327a6ed7ffb01e2175e2596 (diff) | |
tests: discover and sync from relay in annocunement published directly
Diffstat (limited to 'tests/proactive_sync_basic.rs')
| -rw-r--r-- | tests/proactive_sync_basic.rs | 171 |
1 files changed, 157 insertions, 14 deletions
diff --git a/tests/proactive_sync_basic.rs b/tests/proactive_sync_basic.rs index b789cb6..d96d576 100644 --- a/tests/proactive_sync_basic.rs +++ b/tests/proactive_sync_basic.rs | |||
| @@ -74,9 +74,7 @@ async fn check_event_syncs( | |||
| 74 | .await | 74 | .await |
| 75 | .expect("Failed to connect to target relay"); | 75 | .expect("Failed to connect to target relay"); |
| 76 | 76 | ||
| 77 | let filter = Filter::new() | 77 | let filter = Filter::new().kind(event.kind).author(keys.public_key()); |
| 78 | .kind(event.kind) | ||
| 79 | .author(keys.public_key()); | ||
| 80 | 78 | ||
| 81 | let events_on_target = client_target | 79 | let events_on_target = client_target |
| 82 | .fetch_events(filter, Duration::from_secs(3)) | 80 | .fetch_events(filter, Duration::from_secs(3)) |
| @@ -185,7 +183,7 @@ async fn test_sync_relay_connects_to_source() { | |||
| 185 | let relay_a = TestRelay::start().await; | 183 | let relay_a = TestRelay::start().await; |
| 186 | 184 | ||
| 187 | // Start syncing relay (relay_b) configured to sync from relay_a | 185 | // Start syncing relay (relay_b) configured to sync from relay_a |
| 188 | let relay_b = TestRelay::start_with_sync(relay_a.url()).await; | 186 | let relay_b = TestRelay::start_with_sync(Some(relay_a.url().into())).await; |
| 189 | 187 | ||
| 190 | // Give some time for connection to establish | 188 | // Give some time for connection to establish |
| 191 | tokio::time::sleep(Duration::from_millis(500)).await; | 189 | tokio::time::sleep(Duration::from_millis(500)).await; |
| @@ -197,9 +195,9 @@ async fn test_sync_relay_connects_to_source() { | |||
| 197 | relay_a.stop().await; | 195 | relay_a.stop().await; |
| 198 | } | 196 | } |
| 199 | 197 | ||
| 200 | /// Test that valid events sync from source to syncing relay | 198 | /// Test that valid events sync from source to bootstrap relay |
| 201 | #[tokio::test] | 199 | #[tokio::test] |
| 202 | async fn test_valid_event_syncs_to_relay() { | 200 | async fn announcement_listing_relay_syncs_from_bootstrap_relay() { |
| 203 | // Start source relay (relay_a) | 201 | // Start source relay (relay_a) |
| 204 | let relay_a = TestRelay::start().await; | 202 | let relay_a = TestRelay::start().await; |
| 205 | println!( | 203 | println!( |
| @@ -209,7 +207,7 @@ async fn test_valid_event_syncs_to_relay() { | |||
| 209 | ); | 207 | ); |
| 210 | 208 | ||
| 211 | // Start syncing relay (relay_b) configured to sync from relay_a | 209 | // Start syncing relay (relay_b) configured to sync from relay_a |
| 212 | let relay_b = TestRelay::start_with_sync(relay_a.url()).await; | 210 | let relay_b = TestRelay::start_with_sync(Some(relay_a.url().into())).await; |
| 213 | println!( | 211 | println!( |
| 214 | "relay_b started at {} (domain: {})", | 212 | "relay_b started at {} (domain: {})", |
| 215 | relay_b.url(), | 213 | relay_b.url(), |
| @@ -226,11 +224,8 @@ async fn test_valid_event_syncs_to_relay() { | |||
| 226 | // Create a repository announcement that lists BOTH relays | 224 | // Create a repository announcement that lists BOTH relays |
| 227 | // This is required for sync - the event must reference both the source relay | 225 | // This is required for sync - the event must reference both the source relay |
| 228 | // and the syncing relay for the write policy to accept it on both sides | 226 | // and the syncing relay for the write policy to accept it on both sides |
| 229 | let event = create_repo_announcement( | 227 | let event = |
| 230 | &keys, | 228 | create_repo_announcement(&keys, &[&relay_a.domain(), &relay_b.domain()], "test-repo"); |
| 231 | &[&relay_a.domain(), &relay_b.domain()], | ||
| 232 | "test-repo", | ||
| 233 | ); | ||
| 234 | let event_id = event.id; | 229 | let event_id = event.id; |
| 235 | 230 | ||
| 236 | // Print event details for debugging | 231 | // Print event details for debugging |
| @@ -263,7 +258,7 @@ async fn test_valid_event_syncs_to_relay() { | |||
| 263 | /// This verifies that relay_b's write policy correctly rejects events during sync | 258 | /// This verifies that relay_b's write policy correctly rejects events during sync |
| 264 | /// if they don't list relay_b as one of their relays. | 259 | /// if they don't list relay_b as one of their relays. |
| 265 | #[tokio::test] | 260 | #[tokio::test] |
| 266 | async fn test_event_not_listing_target_relay_is_not_synced() { | 261 | async fn test_announcement_not_listing_relay_is_not_synced_from_boostrap_relay() { |
| 267 | // Start source relay (relay_a) | 262 | // Start source relay (relay_a) |
| 268 | let relay_a = TestRelay::start().await; | 263 | let relay_a = TestRelay::start().await; |
| 269 | println!( | 264 | println!( |
| @@ -273,7 +268,7 @@ async fn test_event_not_listing_target_relay_is_not_synced() { | |||
| 273 | ); | 268 | ); |
| 274 | 269 | ||
| 275 | // Start syncing relay (relay_b) configured to sync from relay_a | 270 | // Start syncing relay (relay_b) configured to sync from relay_a |
| 276 | let relay_b = TestRelay::start_with_sync(relay_a.url()).await; | 271 | let relay_b = TestRelay::start_with_sync(Some(relay_a.url().into())).await; |
| 277 | println!( | 272 | println!( |
| 278 | "relay_b started at {} (domain: {})", | 273 | "relay_b started at {} (domain: {})", |
| 279 | relay_b.url(), | 274 | relay_b.url(), |
| @@ -321,3 +316,151 @@ async fn test_event_not_listing_target_relay_is_not_synced() { | |||
| 321 | event_id | 316 | event_id |
| 322 | ); | 317 | ); |
| 323 | } | 318 | } |
| 319 | |||
| 320 | fn create_kind_event_referencing_repo(keys: &Keys, repo_coord: &str) -> Event { | ||
| 321 | // TODO this breaks with kind 1 | ||
| 322 | EventBuilder::new(Kind::Custom(1617), "Test patch proposal") | ||
| 323 | .tags(vec![Tag::custom( | ||
| 324 | TagKind::custom("a"), | ||
| 325 | vec![repo_coord.to_string()], | ||
| 326 | )]) | ||
| 327 | .sign_with_keys(keys) | ||
| 328 | .expect("Failed to sign event") | ||
| 329 | } | ||
| 330 | |||
| 331 | /// Test that when a relay is discovered (via an announcement event), events are synced from it | ||
| 332 | /// | ||
| 333 | /// This test verifies dynamic relay discovery from direct submissions: | ||
| 334 | /// 1. relay_a has an announcement and a patch event | ||
| 335 | /// 2. relay_b (sync enabled, NO bootstrap) receives the announcement directly | ||
| 336 | /// 3. relay_b discovers relay_a from the announcement and connects to sync | ||
| 337 | /// 4. relay_b syncs the patch event from relay_a | ||
| 338 | /// | ||
| 339 | /// This tests the scenario where relays discover each other through announcements | ||
| 340 | /// submitted by users, not through an existing sync connection. | ||
| 341 | #[tokio::test] | ||
| 342 | async fn repo_events_synced_from_discovered_relay_after_announcement_received() { | ||
| 343 | // relay_a: source relay with the patch event | ||
| 344 | let relay_a = TestRelay::start().await; | ||
| 345 | println!( | ||
| 346 | "relay_a started at {} (domain: {})", | ||
| 347 | relay_a.url(), | ||
| 348 | relay_a.domain() | ||
| 349 | ); | ||
| 350 | |||
| 351 | // relay_b: sync enabled but NO bootstrap relay - will discover relay_a | ||
| 352 | let relay_b = TestRelay::start_with_sync(None).await; | ||
| 353 | println!( | ||
| 354 | "relay_b started at {} (domain: {})", | ||
| 355 | relay_b.url(), | ||
| 356 | relay_b.domain() | ||
| 357 | ); | ||
| 358 | |||
| 359 | // Create test keys | ||
| 360 | let keys = Keys::generate(); | ||
| 361 | |||
| 362 | // Create a repository announcement that lists BOTH relays | ||
| 363 | let announcement = create_repo_announcement( | ||
| 364 | &keys, | ||
| 365 | &[&relay_a.domain(), &relay_b.domain()], | ||
| 366 | "test-repo-discovery", | ||
| 367 | ); | ||
| 368 | let announcement_id = announcement.id; | ||
| 369 | |||
| 370 | println!( | ||
| 371 | "Created announcement {} (kind {})", | ||
| 372 | announcement_id, | ||
| 373 | announcement.kind.as_u16() | ||
| 374 | ); | ||
| 375 | for tag in announcement.tags.iter() { | ||
| 376 | println!(" Tag: {:?}", tag.as_slice()); | ||
| 377 | } | ||
| 378 | |||
| 379 | // Build the repo coordinate for the 'a' tag in the patch | ||
| 380 | let repo_coord = format!( | ||
| 381 | "{}:{}:{}", | ||
| 382 | KIND_REPOSITORY_STATE, | ||
| 383 | keys.public_key().to_hex(), | ||
| 384 | "test-repo-discovery" | ||
| 385 | ); | ||
| 386 | |||
| 387 | // Create a patch event that references the announcement | ||
| 388 | let patch = create_kind_event_referencing_repo(&keys, &repo_coord); | ||
| 389 | let patch_id = patch.id; | ||
| 390 | |||
| 391 | println!("Created patch {} (kind {})", patch_id, patch.kind.as_u16()); | ||
| 392 | for tag in patch.tags.iter() { | ||
| 393 | println!(" Tag: {:?}", tag.as_slice()); | ||
| 394 | } | ||
| 395 | |||
| 396 | // Step 1: Send announcement to relay_a | ||
| 397 | let client_a = create_connected_client(relay_a.url(), keys.clone()) | ||
| 398 | .await | ||
| 399 | .expect("Failed to connect to relay_a"); | ||
| 400 | send_event_reliably(&client_a, &announcement) | ||
| 401 | .await | ||
| 402 | .expect("Failed to send announcement to relay_a"); | ||
| 403 | println!("Announcement sent to relay_a"); | ||
| 404 | |||
| 405 | // Step 2: Send patch to relay_a ONLY | ||
| 406 | send_event_reliably(&client_a, &patch) | ||
| 407 | .await | ||
| 408 | .expect("Failed to send patch to relay_a"); | ||
| 409 | println!("Patch sent to relay_a"); | ||
| 410 | client_a.disconnect().await; | ||
| 411 | |||
| 412 | // Step 3: Send announcement to relay_b directly (this should trigger discovery of relay_a) | ||
| 413 | let client_b = create_connected_client(relay_b.url(), keys.clone()) | ||
| 414 | .await | ||
| 415 | .expect("Failed to connect to relay_b"); | ||
| 416 | send_event_reliably(&client_b, &announcement) | ||
| 417 | .await | ||
| 418 | .expect("Failed to send announcement to relay_b"); | ||
| 419 | println!("Announcement sent to relay_b (should trigger discovery of relay_a)"); | ||
| 420 | client_b.disconnect().await; | ||
| 421 | |||
| 422 | // Step 4: Wait for relay_b to discover relay_a and sync the patch | ||
| 423 | println!("Waiting 3s for relay_b to discover relay_a and sync patch..."); | ||
| 424 | tokio::time::sleep(Duration::from_secs(3)).await; | ||
| 425 | |||
| 426 | // Step 5: Verify patch was synced to relay_b | ||
| 427 | let client_b_check = create_connected_client(relay_b.url(), Keys::generate()) | ||
| 428 | .await | ||
| 429 | .expect("Failed to connect to relay_b for verification"); | ||
| 430 | |||
| 431 | let filter = Filter::new() | ||
| 432 | .kind(Kind::Custom(1617)) | ||
| 433 | .author(keys.public_key()); | ||
| 434 | |||
| 435 | let events_on_b = client_b_check | ||
| 436 | .fetch_events(filter, Duration::from_secs(3)) | ||
| 437 | .await | ||
| 438 | .expect("Failed to fetch from relay_b"); | ||
| 439 | |||
| 440 | let patch_synced = events_on_b.iter().any(|e| e.id == patch_id); | ||
| 441 | |||
| 442 | if patch_synced { | ||
| 443 | println!( | ||
| 444 | "Patch {} found on relay_b (synced from discovered relay_a)", | ||
| 445 | patch_id | ||
| 446 | ); | ||
| 447 | } else { | ||
| 448 | println!("Patch {} NOT found on relay_b", patch_id); | ||
| 449 | println!( | ||
| 450 | "Events on relay_b: {:?}", | ||
| 451 | events_on_b.iter().map(|e| e.id).collect::<Vec<_>>() | ||
| 452 | ); | ||
| 453 | } | ||
| 454 | |||
| 455 | client_b_check.disconnect().await; | ||
| 456 | |||
| 457 | // Clean up | ||
| 458 | relay_b.stop().await; | ||
| 459 | relay_a.stop().await; | ||
| 460 | |||
| 461 | assert!( | ||
| 462 | patch_synced, | ||
| 463 | "Patch {} should have been synced to relay_b from discovered relay_a", | ||
| 464 | patch_id | ||
| 465 | ); | ||
| 466 | } | ||