diff options
Diffstat (limited to 'tests/sync/discovery.rs')
| -rw-r--r-- | tests/sync/discovery.rs | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/tests/sync/discovery.rs b/tests/sync/discovery.rs index ec40802..3cdf00d 100644 --- a/tests/sync/discovery.rs +++ b/tests/sync/discovery.rs | |||
| @@ -267,4 +267,167 @@ async fn test_layer2_discovery_with_chain() { | |||
| 267 | "Issue {} (Layer 2) should have synced to relay_b via discovery", | 267 | "Issue {} (Layer 2) should have synced to relay_b via discovery", |
| 268 | issue_id | 268 | issue_id |
| 269 | ); | 269 | ); |
| 270 | } | ||
| 271 | |||
| 272 | /// Test 3: 3-relay recursive discovery - relay discovers third relay through bootstrap | ||
| 273 | /// | ||
| 274 | /// Scenario: | ||
| 275 | /// ```text | ||
| 276 | /// relay_a (SUT) relay_b (bootstrap) relay_c (discovered) | ||
| 277 | /// │ │ │ | ||
| 278 | /// │ │ has announcement_x │ has announcement_y | ||
| 279 | /// │ │ listing A+B+C │ listing A+C | ||
| 280 | /// │ │ │ | ||
| 281 | /// ├────connect──────────► │ | ||
| 282 | /// │◄───sync announcement_x─────────────────────── | ||
| 283 | /// │ │ | ||
| 284 | /// │ discovers relay_c from announcement_x │ | ||
| 285 | /// │ │ | ||
| 286 | /// ├─────────────connect─────────────────────────► | ||
| 287 | /// │◄────────────sync announcement_y─────────────┘ | ||
| 288 | /// ``` | ||
| 289 | /// | ||
| 290 | /// This tests that relay_a: | ||
| 291 | /// 1. Connects to relay_b (configured as bootstrap) | ||
| 292 | /// 2. Receives announcement_x which lists relay_c | ||
| 293 | /// 3. Discovers and connects to relay_c | ||
| 294 | /// 4. Syncs announcement_y from relay_c | ||
| 295 | /// | ||
| 296 | /// NOTE: This test is ignored because recursive relay discovery from synced | ||
| 297 | /// announcements is not yet implemented. Currently, discovery only triggers | ||
| 298 | /// when an announcement is directly submitted to a relay, not when it's | ||
| 299 | /// synced from a bootstrap relay. | ||
| 300 | #[tokio::test] | ||
| 301 | #[ignore = "Recursive relay discovery from bootstrap sync not yet implemented"] | ||
| 302 | async fn test_recursive_relay_discovery_syncs_announcement() { | ||
| 303 | // 1. Start all three relays | ||
| 304 | |||
| 305 | // relay_b - will be the bootstrap relay, has announcement_x | ||
| 306 | let relay_b = TestRelay::start().await; | ||
| 307 | println!( | ||
| 308 | "relay_b (bootstrap) started at {} (domain: {})", | ||
| 309 | relay_b.url(), | ||
| 310 | relay_b.domain() | ||
| 311 | ); | ||
| 312 | |||
| 313 | // relay_c - will be discovered via announcement_x, has announcement_y | ||
| 314 | let relay_c = TestRelay::start().await; | ||
| 315 | println!( | ||
| 316 | "relay_c (to be discovered) started at {} (domain: {})", | ||
| 317 | relay_c.url(), | ||
| 318 | relay_c.domain() | ||
| 319 | ); | ||
| 320 | |||
| 321 | // relay_a - SUT, starts with relay_b as bootstrap | ||
| 322 | let relay_a = TestRelay::start_with_sync(Some(relay_b.url().to_string())).await; | ||
| 323 | println!( | ||
| 324 | "relay_a (SUT) started at {} (domain: {})", | ||
| 325 | relay_a.url(), | ||
| 326 | relay_a.domain() | ||
| 327 | ); | ||
| 328 | |||
| 329 | // 2. Create test keys (one for each announcement) | ||
| 330 | let keys_x = Keys::generate(); | ||
| 331 | let keys_y = Keys::generate(); | ||
| 332 | |||
| 333 | // 3. Create announcement_x on relay_b (lists all three relays: A+B+C) | ||
| 334 | let announcement_x = create_repo_announcement( | ||
| 335 | &keys_x, | ||
| 336 | &[&relay_a.domain(), &relay_b.domain(), &relay_c.domain()], | ||
| 337 | "repo-x-all-relays", | ||
| 338 | ); | ||
| 339 | let announcement_x_id = announcement_x.id; | ||
| 340 | println!("Created announcement_x {} listing A+B+C", announcement_x_id); | ||
| 341 | for tag in announcement_x.tags.iter() { | ||
| 342 | println!(" Tag: {:?}", tag.as_slice()); | ||
| 343 | } | ||
| 344 | |||
| 345 | // 4. Create announcement_y on relay_c (lists only A+C, NOT B) | ||
| 346 | let announcement_y = create_repo_announcement( | ||
| 347 | &keys_y, | ||
| 348 | &[&relay_a.domain(), &relay_c.domain()], | ||
| 349 | "repo-y-ac-only", | ||
| 350 | ); | ||
| 351 | let announcement_y_id = announcement_y.id; | ||
| 352 | println!("Created announcement_y {} listing A+C only", announcement_y_id); | ||
| 353 | for tag in announcement_y.tags.iter() { | ||
| 354 | println!(" Tag: {:?}", tag.as_slice()); | ||
| 355 | } | ||
| 356 | |||
| 357 | // 5. Send announcement_x to relay_b only | ||
| 358 | let client_b = TestClient::new(relay_b.url(), keys_x.clone()) | ||
| 359 | .await | ||
| 360 | .expect("Failed to connect to relay_b"); | ||
| 361 | |||
| 362 | client_b | ||
| 363 | .send_event(&announcement_x) | ||
| 364 | .await | ||
| 365 | .expect("Failed to send announcement_x to relay_b"); | ||
| 366 | println!("announcement_x sent to relay_b"); | ||
| 367 | |||
| 368 | client_b.disconnect().await; | ||
| 369 | |||
| 370 | // 6. Send announcement_y to relay_c only | ||
| 371 | let client_c = TestClient::new(relay_c.url(), keys_y.clone()) | ||
| 372 | .await | ||
| 373 | .expect("Failed to connect to relay_c"); | ||
| 374 | |||
| 375 | client_c | ||
| 376 | .send_event(&announcement_y) | ||
| 377 | .await | ||
| 378 | .expect("Failed to send announcement_y to relay_c"); | ||
| 379 | println!("announcement_y sent to relay_c"); | ||
| 380 | |||
| 381 | client_c.disconnect().await; | ||
| 382 | |||
| 383 | // 7. Wait for relay_a to: | ||
| 384 | // - Sync from bootstrap relay_b (gets announcement_x) | ||
| 385 | // - Discover relay_c from announcement_x's relays tag | ||
| 386 | // - Connect to relay_c and sync announcement_y | ||
| 387 | println!("Waiting 5s for recursive relay discovery..."); | ||
| 388 | tokio::time::sleep(Duration::from_secs(5)).await; | ||
| 389 | |||
| 390 | // 8. Verify announcement_x was synced to relay_a (from bootstrap relay_b) | ||
| 391 | let filter_x = Filter::new() | ||
| 392 | .kind(Kind::Custom(KIND_REPOSITORY_STATE)) | ||
| 393 | .author(keys_x.public_key()); | ||
| 394 | |||
| 395 | let announcement_x_synced = | ||
| 396 | wait_for_event_on_relay(relay_a.url(), filter_x, Duration::from_secs(5)).await; | ||
| 397 | |||
| 398 | println!( | ||
| 399 | "announcement_x {} synced to relay_a: {}", | ||
| 400 | announcement_x_id, announcement_x_synced | ||
| 401 | ); | ||
| 402 | |||
| 403 | // 9. Verify announcement_y was synced to relay_a (from discovered relay_c) | ||
| 404 | let filter_y = Filter::new() | ||
| 405 | .kind(Kind::Custom(KIND_REPOSITORY_STATE)) | ||
| 406 | .author(keys_y.public_key()); | ||
| 407 | |||
| 408 | let announcement_y_synced = | ||
| 409 | wait_for_event_on_relay(relay_a.url(), filter_y, Duration::from_secs(5)).await; | ||
| 410 | |||
| 411 | println!( | ||
| 412 | "announcement_y {} synced to relay_a: {}", | ||
| 413 | announcement_y_id, announcement_y_synced | ||
| 414 | ); | ||
| 415 | |||
| 416 | // 10. Cleanup | ||
| 417 | relay_a.stop().await; | ||
| 418 | relay_b.stop().await; | ||
| 419 | relay_c.stop().await; | ||
| 420 | |||
| 421 | // 11. Assertions | ||
| 422 | assert!( | ||
| 423 | announcement_x_synced, | ||
| 424 | "announcement_x {} should have synced from bootstrap relay_b to relay_a", | ||
| 425 | announcement_x_id | ||
| 426 | ); | ||
| 427 | |||
| 428 | assert!( | ||
| 429 | announcement_y_synced, | ||
| 430 | "announcement_y {} should have synced from discovered relay_c to relay_a (recursive discovery)", | ||
| 431 | announcement_y_id | ||
| 432 | ); | ||
| 270 | } \ No newline at end of file | 433 | } \ No newline at end of file |