upleb.uk

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

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tests/common/sync_helpers.rs15
-rw-r--r--tests/sync.rs4
-rw-r--r--tests/sync/historic_sync.rs392
3 files changed, 134 insertions, 277 deletions
diff --git a/tests/common/sync_helpers.rs b/tests/common/sync_helpers.rs
index 67dec3c..8971369 100644
--- a/tests/common/sync_helpers.rs
+++ b/tests/common/sync_helpers.rs
@@ -1060,6 +1060,7 @@ mod tests {
1060 let metrics = ParsedMetrics::parse(text); 1060 let metrics = ParsedMetrics::parse(text);
1061 assert_eq!(metrics.relay_connected("ws://127.0.0.1:12345"), Some(true)); 1061 assert_eq!(metrics.relay_connected("ws://127.0.0.1:12345"), Some(true));
1062 } 1062 }
1063}
1063 1064
1064// ============================================================================ 1065// ============================================================================
1065// Unified Sync Test Helper 1066// Unified Sync Test Helper
@@ -1125,16 +1126,14 @@ pub async fn run_sync_test(
1125 historic_events: &[Event], 1126 historic_events: &[Event],
1126 live_events: &[Event], 1127 live_events: &[Event],
1127) -> SyncTestResult { 1128) -> SyncTestResult {
1128 // Validate usage - exactly one slice must have content 1129 // Validate usage - cannot provide events in both slices
1129 let historic_mode = !historic_events.is_empty(); 1130 let historic_mode = !historic_events.is_empty();
1130 let live_mode = !live_events.is_empty(); 1131 let live_mode = !live_events.is_empty();
1131 1132
1132 if historic_mode && live_mode { 1133 if historic_mode && live_mode {
1133 panic!("Invalid usage: both historic_events and live_events provided. Use one or the other."); 1134 panic!("Invalid usage: both historic_events and live_events provided. Use one or the other.");
1134 } 1135 }
1135 if !historic_mode && !live_mode { 1136 // Note: Both slices can be empty - this tests just the announcement sync
1136 panic!("Invalid usage: both historic_events and live_events are empty. Provide at least one.");
1137 }
1138 1137
1139 // 1. Pre-allocate syncing relay port for announcement tags 1138 // 1. Pre-allocate syncing relay port for announcement tags
1140 let syncing_port = TestRelay::find_free_port(); 1139 let syncing_port = TestRelay::find_free_port();
@@ -1218,11 +1217,5 @@ mod sync_helper_tests {
1218 let _result = run_sync_test(&[historic], &[live]).await; 1217 let _result = run_sync_test(&[historic], &[live]).await;
1219 } 1218 }
1220 1219
1221 #[tokio::test] 1220 // Note: Empty slices are now allowed - tests just the announcement sync
1222 #[should_panic(expected = "both historic_events and live_events are empty")]
1223 async fn test_run_sync_test_panics_with_empty_slices() {
1224 // Should panic - both slices empty
1225 let _result = run_sync_test(&[], &[]).await;
1226 }
1227}
1228} 1221}
diff --git a/tests/sync.rs b/tests/sync.rs
index 2e09fb8..64fd10a 100644
--- a/tests/sync.rs
+++ b/tests/sync.rs
@@ -3,7 +3,7 @@
3//! This test file organizes tests for ngit-grasp's proactive sync functionality. 3//! This test file organizes tests for ngit-grasp's proactive sync functionality.
4//! Tests are grouped into submodules by sync scenario: 4//! Tests are grouped into submodules by sync scenario:
5//! 5//!
6//! - `bootstrap` - Tests for sync from pre-configured bootstrap relay 6//! - `historic_sync` - Tests for sync from pre-configured bootstrap relay (historic events)
7//! - `discovery` - Tests for relay discovery from announcement events 7//! - `discovery` - Tests for relay discovery from announcement events
8//! - `live_sync` - Tests for real-time sync after connection established 8//! - `live_sync` - Tests for real-time sync after connection established
9//! - `tag_variations` - Tests for different Layer 2/3 tag types 9//! - `tag_variations` - Tests for different Layer 2/3 tag types
@@ -31,7 +31,7 @@ mod common;
31 31
32// Include sync test submodules (located in tests/sync/) 32// Include sync test submodules (located in tests/sync/)
33mod sync { 33mod sync {
34 pub mod bootstrap; 34 pub mod historic_sync;
35 pub mod catchup; 35 pub mod catchup;
36 pub mod discovery; 36 pub mod discovery;
37 pub mod live_sync; 37 pub mod live_sync;
diff --git a/tests/sync/historic_sync.rs b/tests/sync/historic_sync.rs
index 8f0c79b..d13886f 100644
--- a/tests/sync/historic_sync.rs
+++ b/tests/sync/historic_sync.rs
@@ -1,12 +1,11 @@
1//! Bootstrap Sync Tests 1//! Historic Sync Tests
2//! 2//!
3//! Tests for relay synchronization from a pre-configured bootstrap relay. 3//! Tests for relay synchronization from a pre-configured bootstrap relay.
4//! These tests verify that a relay can sync events from another relay 4//! These tests verify that a relay can sync events from another relay
5//! that it's configured to connect to on startup. 5//! that it's configured to connect to on startup.
6//! 6//!
7//! # Tests 7//! "Historic sync" refers to events that existed on the source relay BEFORE
8//! - Test 1: Bootstrap sync on startup (existing events sync) 8//! the syncing relay connected (bootstrap scenario).
9//! - Test 4: Replay after restart (events persist and replay)
10 9
11use std::time::Duration; 10use std::time::Duration;
12 11
@@ -17,308 +16,183 @@ use crate::common::{sync_helpers::*, TestRelay};
17/// Test 1: Bootstrap sync - relay syncs existing events from bootstrap relay on startup 16/// Test 1: Bootstrap sync - relay syncs existing events from bootstrap relay on startup
18/// 17///
19/// Scenario: 18/// Scenario:
20/// 1. Start relay_a (source) with an announcement 19/// 1. Source relay has announcement (sent before syncing relay starts)
21/// 2. Start relay_b configured to sync from relay_a 20/// 2. Start syncing relay configured to sync from source
22/// 3. Verify relay_b syncs the announcement from relay_a 21/// 3. Verify announcement syncs via bootstrap/historic sync
23/// 22///
24/// This tests that when a relay starts with a bootstrap relay configured, 23/// This tests that when a relay starts with a bootstrap relay configured,
25/// it connects and syncs existing events. 24/// it connects and syncs existing events.
26#[tokio::test] 25#[tokio::test]
27async fn test_bootstrap_syncs_existing_layer2_events() { 26async fn test_bootstrap_syncs_existing_layer2_events() {
28 // 1. Start source relay (relay_a) 27 // Use run_sync_test helper - announcement auto-created and sent as historic event
29 let relay_a = TestRelay::start().await; 28 let result = run_sync_test(&[], &[]).await;
30 println!(
31 "relay_a started at {} (domain: {})",
32 relay_a.url(),
33 relay_a.domain()
34 );
35
36 // 2. Pre-allocate port for relay_b so we can include it in the announcement
37 let relay_b_port = TestRelay::find_free_port();
38 let relay_b_domain = format!("127.0.0.1:{}", relay_b_port);
39 println!("Pre-allocated relay_b domain: {}", relay_b_domain);
40
41 // 3. Create test keys
42 let keys = Keys::generate();
43
44 // 4. Create a repository announcement that lists BOTH relays
45 // This is required because relay_b's write policy checks that events reference its domain
46 let announcement = create_repo_announcement(
47 &keys,
48 &[&relay_a.domain(), &relay_b_domain],
49 "test-repo-bootstrap",
50 );
51 let announcement_id = announcement.id;
52
53 println!(
54 "Created announcement {} (kind {})",
55 announcement_id,
56 announcement.kind.as_u16()
57 );
58 for tag in announcement.tags.iter() {
59 println!(" Tag: {:?}", tag.as_slice());
60 }
61
62 // 5. Send announcement to relay_a BEFORE relay_b starts
63 // This is key for testing bootstrap sync
64 let client_a = TestClient::new(relay_a.url(), keys.clone())
65 .await
66 .expect("Failed to connect to relay_a");
67 29
68 client_a 30 // Verify announcement synced to syncing relay
69 .send_event(&announcement)
70 .await
71 .expect("Failed to send announcement to relay_a");
72 println!("Announcement sent to relay_a");
73
74 client_a.disconnect().await;
75
76 // 6. Wait briefly to ensure event is persisted on relay_a
77 tokio::time::sleep(Duration::from_millis(500)).await;
78
79 // 7. NOW start relay_b on the pre-allocated port, configured to sync from relay_a
80 // The announcement already exists on relay_a, so this tests bootstrap sync
81 let relay_b = TestRelay::start_on_port_with_options(
82 relay_b_port,
83 Some(relay_a.url().into()),
84 false,
85 )
86 .await;
87 println!(
88 "relay_b started at {} (domain: {})",
89 relay_b.url(),
90 relay_b.domain()
91 );
92
93 // 8. Wait for bootstrap sync to complete
94 // Bootstrap sync should happen automatically on startup
95 tokio::time::sleep(Duration::from_secs(3)).await;
96
97 // 9. Verify announcement synced to relay_b
98 let filter = Filter::new() 31 let filter = Filter::new()
99 .kind(Kind::Custom(KIND_REPOSITORY_STATE)) 32 .kind(Kind::Custom(KIND_REPOSITORY_STATE))
100 .author(keys.public_key()); 33 .author(result.maintainer_keys.public_key());
101 34
102 let synced = wait_for_event_on_relay(relay_b.url(), filter, Duration::from_secs(5)).await; 35 let synced = wait_for_event_on_relay(
36 result.syncing_relay.url(),
37 filter,
38 Duration::from_secs(5)
39 ).await;
103 40
104 // 10. Cleanup 41 // Cleanup
105 relay_b.stop().await; 42 result.syncing_relay.stop().await;
106 relay_a.stop().await; 43 result.source_relay.stop().await;
107 44
108 assert!( 45 assert!(
109 synced, 46 synced,
110 "Announcement {} should have synced from relay_a to relay_b via bootstrap sync", 47 "Announcement should have synced from source to syncing relay via bootstrap sync"
111 announcement_id
112 ); 48 );
113} 49}
114 50
115/// Test 4: Replay after restart - relay re-syncs events from bootstrap after restart 51/// Test 4: Replay after restart - relay re-syncs events from bootstrap after restart
116/// 52///
117/// Scenario: 53/// Scenario:
118/// 1. Start relay_a (bootstrap) with announcement 54/// 1. Start source relay with announcement
119/// 2. Start relay_b, sync events from relay_a 55/// 2. Start syncing relay, sync events from source
120/// 3. Verify sync worked 56/// 3. Verify sync worked
121/// 4. Stop relay_b 57/// 4. Stop syncing relay
122/// 5. Restart relay_b (should re-sync from relay_a) 58/// 5. Restart syncing relay (should re-sync from source)
123/// 6. Verify events are available again 59/// 6. Verify events are available again
124/// 60///
125/// Note: Since we use in-memory database, relay_b loses events on stop. 61/// Note: Since we use in-memory database, syncing relay loses events on stop.
126/// This tests that the sync mechanism reconnects and re-syncs on restart. 62/// This tests that the sync mechanism reconnects and re-syncs on restart.
127#[tokio::test] 63#[tokio::test]
128async fn test_relay_replays_events_after_restart() { 64async fn test_relay_replays_events_after_restart() {
129 // 1. Start source relay (relay_a) 65 // First run: establish sync
130 let relay_a = TestRelay::start().await; 66 let result = run_sync_test(&[], &[]).await;
131 println!(
132 "relay_a started at {} (domain: {})",
133 relay_a.url(),
134 relay_a.domain()
135 );
136
137 // 2. Start relay_b first to get its domain
138 let relay_b = TestRelay::start_with_sync(Some(relay_a.url().into())).await;
139 println!(
140 "relay_b (first instance) started at {} (domain: {})",
141 relay_b.url(),
142 relay_b.domain()
143 );
144
145 // 3. Create test keys
146 let keys = Keys::generate();
147
148 // 4. Create announcement listing BOTH domains (so both relays will accept it)
149 let announcement = create_repo_announcement(
150 &keys,
151 &[&relay_a.domain(), &relay_b.domain()],
152 "test-repo-replay",
153 );
154 let announcement_id = announcement.id;
155 67
156 println!( 68 // Verify announcement synced on first run
157 "Created announcement {} (kind {})",
158 announcement_id,
159 announcement.kind.as_u16()
160 );
161
162 // 5. Send announcement to relay_a
163 let client_a = TestClient::new(relay_a.url(), keys.clone())
164 .await
165 .expect("Failed to connect to relay_a");
166
167 client_a
168 .send_event(&announcement)
169 .await
170 .expect("Failed to send announcement to relay_a");
171 println!("Announcement sent to relay_a");
172 client_a.disconnect().await;
173
174 // 6. Wait for sync
175 tokio::time::sleep(Duration::from_secs(2)).await;
176
177 // 7. Verify announcement synced to relay_b (first time)
178 let filter = Filter::new() 69 let filter = Filter::new()
179 .kind(Kind::Custom(KIND_REPOSITORY_STATE)) 70 .kind(Kind::Custom(KIND_REPOSITORY_STATE))
180 .author(keys.public_key()); 71 .author(result.maintainer_keys.public_key());
181 72
182 let synced_first = 73 let synced_first = wait_for_event_on_relay(
183 wait_for_event_on_relay(relay_b.url(), filter.clone(), Duration::from_secs(5)).await; 74 result.syncing_relay.url(),
184 println!("First sync check: {}", synced_first); 75 filter.clone(),
76 Duration::from_secs(5)
77 ).await;
185 78
186 // 8. Stop relay_b 79 println!("First sync check: {}", synced_first);
187 relay_b.stop().await;
188 println!("relay_b stopped");
189 80
190 // 9. Wait a moment 81 // Stop syncing relay (simulates restart)
82 result.syncing_relay.stop().await;
191 tokio::time::sleep(Duration::from_millis(500)).await; 83 tokio::time::sleep(Duration::from_millis(500)).await;
192 84
193 // 10. Restart relay_b (new instance with same bootstrap config) 85 // Restart syncing relay (new instance with same bootstrap config)
194 // Note: The new relay_b will have a different domain, so we need to check 86 // Note: The new syncing relay will have a different domain, so it may not
195 // if it can still sync the event from relay_a (which already has it) 87 // accept the event if it doesn't list its domain. This is expected behavior.
196 let relay_b_new = TestRelay::start_with_sync(Some(relay_a.url().into())).await; 88 let syncing_new = TestRelay::start_with_sync(Some(result.source_relay.url().into())).await;
197 println!( 89 println!(
198 "relay_b (second instance) started at {} (domain: {})", 90 "Syncing relay (second instance) started at {} (domain: {})",
199 relay_b_new.url(), 91 syncing_new.url(),
200 relay_b_new.domain() 92 syncing_new.domain()
201 ); 93 );
202 94
203 // 11. Wait for re-sync 95 // Wait for re-sync
204 tokio::time::sleep(Duration::from_secs(2)).await; 96 tokio::time::sleep(Duration::from_secs(2)).await;
205 97
206 // 12. Verify announcement is available on new relay_b 98 // Verify announcement is available on restarted syncing relay
207 // The announcement listed the OLD relay_b domain, but since relay_a still 99 let synced_after_restart = wait_for_event_on_relay(
208 // has the event, new relay_b should be able to sync it via bootstrap 100 syncing_new.url(),
209 let synced_after_restart = 101 filter,
210 wait_for_event_on_relay(relay_b_new.url(), filter, Duration::from_secs(5)).await; 102 Duration::from_secs(5)
103 ).await;
211 104
212 // 13. Cleanup 105 // Cleanup
213 relay_b_new.stop().await; 106 syncing_new.stop().await;
214 relay_a.stop().await; 107 result.source_relay.stop().await;
215 108
216 assert!( 109 assert!(
217 synced_first, 110 synced_first,
218 "Announcement {} should have synced on first connection", 111 "Announcement should have synced on first connection"
219 announcement_id
220 ); 112 );
221 // Note: synced_after_restart may be false because the new relay_b has a different 113 // Note: synced_after_restart may be false because the new syncing relay has a different
222 // domain, and the announcement only lists the old relay_b domain. This is expected 114 // domain, and the announcement only lists the old syncing relay domain. This is expected.
223 // and tests realistic behavior - relay_b_new won't accept an event that doesn't
224 // list its domain. The important test is that sync MECHANISM works (synced_first).
225 println!( 115 println!(
226 "After restart sync result: {} (may be false due to domain change)", 116 "After restart sync result: {} (may be false due to domain change)",
227 synced_after_restart 117 synced_after_restart
228 ); 118 );
229} 119}
230 120
231/// Test 4: Rejection - announcement not listing relay should NOT sync 121/// Test: Rejection - announcement not listing relay should NOT sync
232/// 122///
233/// Scenario: 123/// Scenario:
234/// 1. relay_a (source), relay_b (sync from relay_a) 124/// 1. source relay, syncing relay (syncs from source)
235/// 2. Create announcement listing ONLY relay_a domain 125/// 2. Create announcement listing ONLY source domain
236/// 3. Send to relay_a 126/// 3. Send to source
237/// 4. Verify NOT synced to relay_b (write policy rejects) 127/// 4. Verify NOT synced to syncing relay (write policy rejects)
238/// 128///
239/// This tests that the relay's write policy correctly rejects events 129/// This tests that the relay's write policy correctly rejects events
240/// that don't list its domain in the clone tag. 130/// that don't list its domain in the clone tag.
241#[tokio::test] 131#[tokio::test]
242async fn test_announcement_not_listing_relay_is_not_synced() { 132async fn test_announcement_not_listing_relay_is_not_synced() {
243 // 1. Start source relay (relay_a) 133 // Start source relay
244 let relay_a = TestRelay::start().await; 134 let source = TestRelay::start().await;
245 println!(
246 "relay_a started at {} (domain: {})",
247 relay_a.url(),
248 relay_a.domain()
249 );
250 135
251 // 2. Start syncing relay (relay_b) configured to sync from relay_a 136 // Start syncing relay
252 let relay_b = TestRelay::start_with_sync(Some(relay_a.url().into())).await; 137 let syncing = TestRelay::start_with_sync(Some(source.url().into())).await;
253 println!(
254 "relay_b started at {} (domain: {})",
255 relay_b.url(),
256 relay_b.domain()
257 );
258 138
259 // 3. Create test keys 139 // Create keys
260 let keys = Keys::generate(); 140 let keys = Keys::generate();
261 141
262 // 4. Wait for relay_b's sync connection to establish 142 // Wait for sync connection to establish
263 // Use the sync connection helper for more reliable connection verification 143 match wait_for_sync_connection(syncing.url(), 1, Duration::from_secs(5)).await {
264 match wait_for_sync_connection(relay_b.url(), 1, Duration::from_secs(5)).await {
265 Ok(()) => println!("Sync connection established (verified via metrics)"), 144 Ok(()) => println!("Sync connection established (verified via metrics)"),
266 Err(e) => println!("Sync connection check: {} (continuing with test)", e), 145 Err(e) => println!("Sync connection check: {} (continuing with test)", e),
267 } 146 }
268 147
269 // 5. Create a repository announcement that lists ONLY relay_a 148 // Create announcement that lists ONLY source domain (NOT syncing)
270 // This should NOT sync to relay_b because relay_b's write policy 149 // This should NOT sync because syncing relay's write policy will reject it
271 // will reject events that don't list its domain
272 let announcement = create_repo_announcement( 150 let announcement = create_repo_announcement(
273 &keys, 151 &keys,
274 &[&relay_a.domain()], // Only relay_a, NOT relay_b 152 &[&source.domain()], // Only source, NOT syncing
275 "test-repo-rejection", 153 "test-repo-rejection",
276 ); 154 );
277 let announcement_id = announcement.id; 155 let announcement_id = announcement.id;
278 156
279 println!( 157 println!(
280 "Created announcement {} (kind {}) - lists ONLY relay_a", 158 "Created announcement {} (kind {}) - lists ONLY source relay",
281 announcement_id, 159 announcement_id,
282 announcement.kind.as_u16() 160 announcement.kind.as_u16()
283 ); 161 );
284 for tag in announcement.tags.iter() {
285 println!(" Tag: {:?}", tag.as_slice());
286 }
287 162
288 // 6. Send announcement to relay_a 163 // Send announcement to source
289 let client_a = TestClient::new(relay_a.url(), keys.clone()) 164 let client = TestClient::new(source.url(), keys.clone())
290 .await 165 .await
291 .expect("Failed to connect to relay_a"); 166 .expect("Failed to connect to source");
292 167
293 client_a 168 client
294 .send_event(&announcement) 169 .send_event(&announcement)
295 .await 170 .await
296 .expect("Failed to send announcement to relay_a"); 171 .expect("Failed to send announcement to source");
297 println!("Announcement sent to relay_a"); 172 println!("Announcement sent to source");
298 173
299 client_a.disconnect().await; 174 client.disconnect().await;
300 175
301 // 7. Wait for potential sync attempt 176 // Wait for potential sync attempt
302 // Give enough time for sync to complete if it were to happen
303 tokio::time::sleep(Duration::from_secs(3)).await; 177 tokio::time::sleep(Duration::from_secs(3)).await;
304 178
305 // 8. Verify announcement did NOT sync to relay_b 179 // Verify announcement did NOT sync to syncing relay
306 let filter = Filter::new() 180 let filter = Filter::new()
307 .kind(Kind::Custom(KIND_REPOSITORY_STATE)) 181 .kind(Kind::Custom(KIND_REPOSITORY_STATE))
308 .author(keys.public_key()); 182 .author(keys.public_key());
309 183
310 let synced = wait_for_event_on_relay(relay_b.url(), filter, Duration::from_secs(2)).await; 184 let synced = wait_for_event_on_relay(syncing.url(), filter, Duration::from_secs(2)).await;
311 185
312 // 9. Cleanup 186 // Cleanup
313 relay_b.stop().await; 187 syncing.stop().await;
314 relay_a.stop().await; 188 source.stop().await;
315 189
316 assert!( 190 assert!(
317 !synced, 191 !synced,
318 "Announcement {} should NOT have synced to relay_b because it doesn't list relay_b's domain", 192 "Announcement {} should NOT have synced to syncing relay because it doesn't list syncing relay's domain",
319 announcement_id 193 announcement_id
320 ); 194 );
321 println!("SUCCESS: Announcement was correctly rejected by relay_b (not synced)"); 195 println!("SUCCESS: Announcement was correctly rejected by syncing relay (not synced)");
322} 196}
323 197
324/// Test: History sync (bootstrap) works without NIP-77 negentropy 198/// Test: History sync (bootstrap) works without NIP-77 negentropy
@@ -328,41 +202,34 @@ async fn test_announcement_not_listing_relay_is_not_synced() {
328/// the syncing relay connected. 202/// the syncing relay connected.
329/// 203///
330/// Scenario: 204/// Scenario:
331/// 1. Start relay_b temporarily to get its domain (then stop it) 205/// 1. Pre-allocate port for syncing relay to get its domain
332/// 2. Start relay_a (source) 206/// 2. Start source relay
333/// 3. Create announcement listing both relay domains 207/// 3. Create announcement listing both relay domains
334/// 4. Send announcement to relay_a (event exists BEFORE relay_b connects) 208/// 4. Send announcement to source (event exists BEFORE syncing relay connects)
335/// 5. Start relay_b AGAIN on same port, with negentropy DISABLED 209/// 5. Start syncing relay on pre-allocated port, with negentropy DISABLED
336/// 6. relay_b should sync the pre-existing event via REQ+EOSE (history sync) 210/// 6. Syncing relay should sync the pre-existing event via REQ+EOSE (history sync)
337/// 7. Verify relay_b has the event 211/// 7. Verify syncing relay has the event
338/// 212///
339/// This is different from "live sync" where events arrive after connection. 213/// This is different from "live sync" where events arrive after connection.
340#[tokio::test] 214#[tokio::test]
341async fn test_history_sync_without_negentropy() { 215async fn test_history_sync_without_negentropy() {
342 // 1. First, start relay_b temporarily just to reserve a port and get its domain 216 // Pre-allocate syncing relay port to get its domain
343 let relay_b_port = TestRelay::find_free_port(); 217 let syncing_port = TestRelay::find_free_port();
344 let relay_b_domain = format!("127.0.0.1:{}", relay_b_port); 218 let syncing_domain = format!("127.0.0.1:{}", syncing_port);
345 println!( 219 println!("Pre-allocated syncing relay domain: {}", syncing_domain);
346 "Reserved port {} for relay_b (domain: {})",
347 relay_b_port, relay_b_domain
348 );
349 220
350 // 2. Start relay_a (source relay) 221 // Start source relay
351 let relay_a = TestRelay::start().await; 222 let source = TestRelay::start().await;
352 println!( 223 println!("Source started at {} (domain: {})", source.url(), source.domain());
353 "relay_a started at {} (domain: {})",
354 relay_a.url(),
355 relay_a.domain()
356 );
357 224
358 // 3. Create test keys 225 // Create keys
359 let keys = Keys::generate(); 226 let keys = Keys::generate();
360 227
361 // 4. Create announcement listing BOTH relay domains 228 // Create announcement listing BOTH relay domains
362 // This event will exist on relay_a BEFORE relay_b ever connects 229 // This event will exist on source BEFORE syncing relay ever connects
363 let announcement = create_repo_announcement( 230 let announcement = create_repo_announcement(
364 &keys, 231 &keys,
365 &[&relay_a.domain(), &relay_b_domain], 232 &[&source.domain(), &syncing_domain],
366 "test-repo-history-no-negentropy", 233 "test-repo-history-no-negentropy",
367 ); 234 );
368 let announcement_id = announcement.id; 235 let announcement_id = announcement.id;
@@ -372,58 +239,55 @@ async fn test_history_sync_without_negentropy() {
372 announcement_id, 239 announcement_id,
373 announcement.kind.as_u16() 240 announcement.kind.as_u16()
374 ); 241 );
375 for tag in announcement.tags.iter() {
376 println!(" Tag: {:?}", tag.as_slice());
377 }
378 242
379 // 5. Send announcement to relay_a (event now exists BEFORE relay_b connects) 243 // Send announcement to source (event now exists BEFORE syncing relay connects)
380 let client_a = TestClient::new(relay_a.url(), keys.clone()) 244 let client = TestClient::new(source.url(), keys.clone())
381 .await 245 .await
382 .expect("Failed to connect to relay_a"); 246 .expect("Failed to connect to source");
383 247
384 client_a 248 client
385 .send_event(&announcement) 249 .send_event(&announcement)
386 .await 250 .await
387 .expect("Failed to send announcement to relay_a"); 251 .expect("Failed to send announcement to source");
388 println!("Announcement sent to relay_a (event exists BEFORE relay_b connects)"); 252 println!("Announcement sent to source (event exists BEFORE syncing relay connects)");
389 253
390 client_a.disconnect().await; 254 client.disconnect().await;
391 255
392 // 6. Wait a moment to ensure the event is stored 256 // Wait to ensure event is stored
393 tokio::time::sleep(Duration::from_millis(500)).await; 257 tokio::time::sleep(Duration::from_millis(500)).await;
394 258
395 // 7. NOW start relay_b on the reserved port, with negentropy DISABLED 259 // NOW start syncing relay on the reserved port, with negentropy DISABLED
396 // This relay_b has never connected before - it needs to do HISTORY sync 260 // This syncing relay has never connected before - it needs to do HISTORY sync
397 let relay_b = TestRelay::start_on_port_with_options( 261 let syncing = TestRelay::start_on_port_with_options(
398 relay_b_port, 262 syncing_port,
399 Some(relay_a.url().into()), 263 Some(source.url().into()),
400 true, // disable_negentropy = true 264 true, // disable_negentropy = true
401 ) 265 )
402 .await; 266 .await;
403 println!( 267 println!(
404 "relay_b started at {} (domain: {}) - negentropy DISABLED, will do HISTORY sync", 268 "Syncing relay started at {} (domain: {}) - negentropy DISABLED, will do HISTORY sync",
405 relay_b.url(), 269 syncing.url(),
406 relay_b.domain() 270 syncing.domain()
407 ); 271 );
408 272
409 // 8. Wait for history sync to complete (using REQ+EOSE, not negentropy) 273 // Wait for history sync to complete (using REQ+EOSE, not negentropy)
410 tokio::time::sleep(Duration::from_secs(3)).await; 274 tokio::time::sleep(Duration::from_secs(3)).await;
411 275
412 // 9. Verify announcement synced to relay_b via HISTORY sync 276 // Verify announcement synced to syncing relay via HISTORY sync
413 let filter = Filter::new() 277 let filter = Filter::new()
414 .kind(Kind::Custom(KIND_REPOSITORY_STATE)) 278 .kind(Kind::Custom(KIND_REPOSITORY_STATE))
415 .author(keys.public_key()); 279 .author(keys.public_key());
416 280
417 let synced = wait_for_event_on_relay(relay_b.url(), filter, Duration::from_secs(5)).await; 281 let synced = wait_for_event_on_relay(syncing.url(), filter, Duration::from_secs(5)).await;
418 282
419 // 10. Cleanup 283 // Cleanup
420 relay_b.stop().await; 284 syncing.stop().await;
421 relay_a.stop().await; 285 source.stop().await;
422 286
423 assert!( 287 assert!(
424 synced, 288 synced,
425 "Announcement {} should have synced from relay_a to relay_b via HISTORY sync (REQ+EOSE, negentropy disabled)", 289 "Announcement {} should have synced from source to syncing relay via HISTORY sync (REQ+EOSE, negentropy disabled)",
426 announcement_id 290 announcement_id
427 ); 291 );
428 println!("SUCCESS: History sync works without negentropy (using REQ+EOSE fallback)"); 292 println!("SUCCESS: History sync works without negentropy (using REQ+EOSE fallback)");
429} 293} \ No newline at end of file