upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/tests/proactive_sync_basic.rs
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2025-12-08 12:50:34 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2025-12-08 12:50:34 +0000
commitefe3e43cf792abd8bb256121ebf84ae04836313a (patch)
tree2aa626f43817d7f86145ba4c6c09ac8660df1a9b /tests/proactive_sync_basic.rs
parentb4da09689ee0bd6ac327a6ed7ffb01e2175e2596 (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.rs171
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]
202async fn test_valid_event_syncs_to_relay() { 200async 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]
266async fn test_event_not_listing_target_relay_is_not_synced() { 261async 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
320fn 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]
342async 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}