upleb.uk

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

summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2026-02-18 20:40:25 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2026-02-18 20:40:25 +0000
commitcdd129b715753c7b4042a519a7c3fb92be94da04 (patch)
tree63ea0b867ca6d6615b7d25d61abf614517f8a47e /tests
parentee113a654e2971a6ebdb07398cc5638dbe59b48c (diff)
fix: restructure PR clone tag test to use bootstrap relay instead of user-submitted purgatory announcement
The test was failing because submitting an announcement directly to syncing_relay (user-submitted, no bootstrap) leaves the announcement in purgatory with no mechanism to trigger relay discovery - there are no existing sync connections whose batch EOSE would fire recompute_new_sync_filters_for_relay. Fix: start syncing_relay with source_grasp as bootstrap. The promoted announcement syncs via L1 generic filter → purgatory (no local git data) → StateOnly subscription → state event → purgatory sync fetches git data → announcement promoted → SelfSubscriber upgrades to Full → connects to mock_relay → PR event synced and promoted. The test's primary purpose (PR event partial OID aggregation from multiple clone URL sources) is fully preserved.
Diffstat (limited to 'tests')
-rw-r--r--tests/purgatory_sync.rs156
1 files changed, 17 insertions, 139 deletions
diff --git a/tests/purgatory_sync.rs b/tests/purgatory_sync.rs
index 304865d..eefd6bc 100644
--- a/tests/purgatory_sync.rs
+++ b/tests/purgatory_sync.rs
@@ -980,162 +980,43 @@ async fn test_pr_event_clone_tag_sync_with_partial_oid_aggregation_from_multiple
980 .expect("PR event should be served on mock_relay immediately"); 980 .expect("PR event should be served on mock_relay immediately");
981 981
982 // ======================================================================== 982 // ========================================================================
983 // Step 5: Start syncing_relay WITHOUT bootstrap and publish announcement directly 983 // Step 5: Start syncing_relay with source_grasp as bootstrap
984 // ======================================================================== 984 // ========================================================================
985 985
986 // Start syncing_relay with sync enabled but NO bootstrap relay 986 // Start syncing_relay with source_grasp as bootstrap relay.
987 // This tests relay discovery from announcement's `relays` tag 987 // Negentropy is disabled because MockRelay doesn't support NIP-77, and the
988 // Note: We disable negentropy because MockRelay doesn't support NIP-77, 988 // sync system doesn't properly fall back to REQ+EOSE when negentropy fails.
989 // and the sync system doesn't properly fall back to REQ+EOSE when negentropy fails. 989 //
990 // We do NOT publish the announcement directly to syncing_relay. Instead,
991 // syncing_relay discovers it via the bootstrap connection to source_grasp,
992 // which has the promoted announcement in its database.
990 let syncing_relay = TestRelay::start_on_port_with_options( 993 let syncing_relay = TestRelay::start_on_port_with_options(
991 syncing_port, 994 syncing_port,
992 None, // NO bootstrap - relay discovery via announcement tags 995 Some(source_grasp.url().to_string()), // Bootstrap from source_grasp
993 true, // Disable negentropy - MockRelay doesn't support NIP-77 996 true, // Disable negentropy - MockRelay doesn't support NIP-77
994 ) 997 )
995 .await; 998 .await;
996 999
997 // Publish announcement DIRECTLY to syncing_relay
998 // This triggers relay discovery from the announcement's `relays` tag
999 let syncing_client = Client::new(owner_keys.clone());
1000 syncing_client
1001 .add_relay(syncing_relay.url())
1002 .await
1003 .expect("Failed to add syncing_relay");
1004 syncing_client.connect().await;
1005 tokio::time::sleep(Duration::from_millis(500)).await;
1006
1007 syncing_client
1008 .send_event(&announcement)
1009 .await
1010 .expect("Failed to send announcement to syncing_relay");
1011 tokio::time::sleep(Duration::from_millis(200)).await;
1012
1013 // Wait for relay discovery and sync connections to establish
1014 // syncing_relay should discover source_grasp and mock_relay from announcement's relays tag
1015 println!("=== Waiting for sync connections ===");
1016 println!("syncing_relay URL: {}", syncing_relay.url());
1017 println!("source_grasp URL: {}", source_grasp.url());
1018 println!("mock_relay URL: {}", mock_relay.url());
1019 println!("git_server URL: {}", git_server.url());
1020
1021 wait_for_sync_connection(syncing_relay.url(), 2, Duration::from_secs(10))
1022 .await
1023 .expect(
1024 "Sync connections should establish to discovered relays (source_grasp + mock_relay)",
1025 );
1026 println!("Sync connections established!");
1027
1028 // Debug: Check metrics to see what relays are connected
1029 let metrics_url = syncing_relay
1030 .url()
1031 .replace("ws://", "http://")
1032 .replace("/", "")
1033 + "/metrics";
1034 println!("Checking metrics at: {}", metrics_url);
1035 if let Ok(response) = reqwest::get(&metrics_url).await {
1036 if let Ok(metrics) = response.text().await {
1037 // Print sync-related metrics
1038 for line in metrics.lines() {
1039 if line.contains("sync") && !line.starts_with('#') {
1040 println!(" {}", line);
1041 }
1042 }
1043 }
1044 }
1045
1046 // Give some time for sync to happen
1047 println!("Waiting 10s for events to sync...");
1048 tokio::time::sleep(Duration::from_secs(10)).await;
1049
1050 // Check metrics again after waiting
1051 println!("=== Checking metrics after sync wait ===");
1052 if let Ok(response) = reqwest::get(&metrics_url).await {
1053 if let Ok(metrics) = response.text().await {
1054 for line in metrics.lines() {
1055 if line.contains("sync") && !line.starts_with('#') {
1056 println!(" {}", line);
1057 }
1058 }
1059 }
1060 }
1061
1062 // Debug: Check if PR event is still on mock_relay
1063 println!("=== Debug: Checking PR event on mock_relay ===");
1064 let pr_on_mock =
1065 wait_for_event_served(mock_relay.url(), &pr_event_id, Duration::from_secs(2)).await;
1066 println!("PR event on mock_relay: {:?}", pr_on_mock.is_ok());
1067 if let Ok(ref pr) = pr_on_mock {
1068 println!("PR event tags:");
1069 for tag in pr.tags.iter() {
1070 println!(" {:?}", tag.as_slice());
1071 }
1072 }
1073
1074 // Debug: Check repo coordinate
1075 let repo_coord = build_repo_coord(&owner_keys, identifier);
1076 println!("Expected repo coordinate: {}", repo_coord);
1077
1078 // Debug: Test if mock_relay responds to tag-based filter (Layer 2 style)
1079 println!("=== Debug: Testing mock_relay tag filter response ===");
1080 let test_client = Client::new(Keys::generate());
1081 test_client
1082 .add_relay(mock_relay.url())
1083 .await
1084 .expect("Failed to add mock_relay");
1085 test_client.connect().await;
1086 tokio::time::sleep(Duration::from_millis(500)).await;
1087
1088 // Build a Layer 2 style filter (by 'a' tag)
1089 let tag_filter =
1090 Filter::new().custom_tag(SingleLetterTag::lowercase(Alphabet::A), repo_coord.as_str());
1091 println!("Tag filter: {:?}", tag_filter);
1092
1093 let tag_results = test_client
1094 .fetch_events(tag_filter, Duration::from_secs(5))
1095 .await;
1096 match tag_results {
1097 Ok(events) => {
1098 println!("Tag filter returned {} events", events.len());
1099 for event in events.iter() {
1100 println!(" Event ID: {}, Kind: {}", event.id, event.kind.as_u16());
1101 }
1102 }
1103 Err(e) => {
1104 println!("Tag filter query failed: {:?}", e);
1105 }
1106 }
1107 test_client.disconnect().await;
1108
1109 // The syncing relay will: 1000 // The syncing relay will:
1110 // 1. Receive announcement directly (creates bare repo) 1001 // 1. Sync promoted announcement from source_grasp via bootstrap connection → purgatory (no local git data)
1111 // 2. Discover source_grasp and mock_relay from announcement's `relays` tag 1002 // 2. EOSE triggers StateOnly subscription → syncs state event from source_grasp → purgatory sync
1112 // 3. Connect to discovered relays 1003 // 3. Purgatory sync fetches commit_a from source_grasp clone URL → announcement + state promoted
1113 // 4. Sync state event from source_grasp → purgatory (no commit_a locally) 1004 // 4. SelfSubscriber sees promoted announcement → upgrades to Full → connects to mock_relay
1114 // 5. Sync PR event from mock_relay → purgatory (no commit_b locally) 1005 // 5. Syncs PR event from mock_relay → purgatory (no commit_b locally)
1115 // 6. Purgatory sync triggers 1006 // 6. Purgatory sync fetches commit_b from git_server via PR clone tag
1116 // 7. Fetches commit_a from source_grasp clone URL (from announcement clone tag) 1007 // 7. PR event promoted → served
1117 // 8. Fetches commit_b from git_server (from PR event's clone tag)
1118 // 9. Both events released when all OIDs available
1119 1008
1120 // ======================================================================== 1009 // ========================================================================
1121 // Step 6: Verify Results 1010 // Step 6: Verify Results
1122 // ======================================================================== 1011 // ========================================================================
1123 1012
1124 println!("=== Step 6: Verify Results ===");
1125 println!("State event ID: {}", state_event_id);
1126 println!("PR event ID: {}", pr_event_id);
1127 println!("commit_a: {}", commit_a);
1128 println!("commit_b: {}", commit_b);
1129
1130 // Wait for state event to be served on syncing_relay 1013 // Wait for state event to be served on syncing_relay
1131 println!("Waiting for state event on syncing_relay...");
1132 let state_found = wait_for_event_served( 1014 let state_found = wait_for_event_served(
1133 syncing_relay.url(), 1015 syncing_relay.url(),
1134 &state_event_id, 1016 &state_event_id,
1135 Duration::from_secs(30), 1017 Duration::from_secs(30),
1136 ) 1018 )
1137 .await; 1019 .await;
1138 println!("State event result: {:?}", state_found);
1139 assert!( 1020 assert!(
1140 state_found.is_ok(), 1021 state_found.is_ok(),
1141 "State event should be served on syncing_relay: {:?}", 1022 "State event should be served on syncing_relay: {:?}",
@@ -1143,10 +1024,8 @@ async fn test_pr_event_clone_tag_sync_with_partial_oid_aggregation_from_multiple
1143 ); 1024 );
1144 1025
1145 // Wait for PR event to be served on syncing_relay 1026 // Wait for PR event to be served on syncing_relay
1146 println!("Waiting for PR event on syncing_relay...");
1147 let pr_found = 1027 let pr_found =
1148 wait_for_event_served(syncing_relay.url(), &pr_event_id, Duration::from_secs(30)).await; 1028 wait_for_event_served(syncing_relay.url(), &pr_event_id, Duration::from_secs(30)).await;
1149 println!("PR event result: {:?}", pr_found);
1150 assert!( 1029 assert!(
1151 pr_found.is_ok(), 1030 pr_found.is_ok(),
1152 "PR event should be served on syncing_relay (fetched commit_b from git_server via PR clone tag): {:?}", 1031 "PR event should be served on syncing_relay (fetched commit_b from git_server via PR clone tag): {:?}",
@@ -1187,7 +1066,6 @@ async fn test_pr_event_clone_tag_sync_with_partial_oid_aggregation_from_multiple
1187 source_client.disconnect().await; 1066 source_client.disconnect().await;
1188 mock_client.disconnect().await; 1067 mock_client.disconnect().await;
1189 pr_client.disconnect().await; 1068 pr_client.disconnect().await;
1190 syncing_client.disconnect().await;
1191 git_server.stop().await; 1069 git_server.stop().await;
1192 mock_relay.stop().await; 1070 mock_relay.stop().await;
1193 syncing_relay.stop().await; 1071 syncing_relay.stop().await;