upleb.uk

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

summaryrefslogtreecommitdiff
path: root/tests/sync/maintainer_reprocessing.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tests/sync/maintainer_reprocessing.rs')
-rw-r--r--tests/sync/maintainer_reprocessing.rs311
1 files changed, 146 insertions, 165 deletions
diff --git a/tests/sync/maintainer_reprocessing.rs b/tests/sync/maintainer_reprocessing.rs
index 2b7fb0f..df1bf78 100644
--- a/tests/sync/maintainer_reprocessing.rs
+++ b/tests/sync/maintainer_reprocessing.rs
@@ -42,23 +42,18 @@ async fn test_maintainer_announcement_reprocessed_immediately() {
42 .await 42 .await
43 .expect("Failed to connect to relay_a"); 43 .expect("Failed to connect to relay_a");
44 44
45 let maintainer_announcement = EventBuilder::new( 45 let maintainer_announcement =
46 Kind::GitRepoAnnouncement, 46 EventBuilder::new(Kind::GitRepoAnnouncement, "Maintainer's repository")
47 "Maintainer's repository", 47 .tags(vec![
48 ) 48 Tag::identifier(identifier),
49 .tags(vec![ 49 Tag::custom(
50 Tag::identifier(identifier), 50 TagKind::custom("clone"),
51 Tag::custom( 51 vec![format!("https://{}/{}.git", relay_a.domain(), identifier)],
52 TagKind::custom("clone"), 52 ),
53 vec![format!("https://{}/{}.git", relay_a.domain(), identifier)], 53 Tag::custom(TagKind::custom("relays"), vec![relay_a.url().to_string()]),
54 ), 54 ])
55 Tag::custom( 55 .sign_with_keys(&maintainer_keys)
56 TagKind::custom("relays"), 56 .unwrap();
57 vec![relay_a.url().to_string()],
58 ),
59 ])
60 .sign_with_keys(&maintainer_keys)
61 .unwrap();
62 57
63 client_a.send_event(&maintainer_announcement).await.unwrap(); 58 client_a.send_event(&maintainer_announcement).await.unwrap();
64 println!("✓ Maintainer announcement sent to relay_a"); 59 println!("✓ Maintainer announcement sent to relay_a");
@@ -68,27 +63,24 @@ async fn test_maintainer_announcement_reprocessed_immediately() {
68 .await 63 .await
69 .expect("Failed to connect to relay_b"); 64 .expect("Failed to connect to relay_b");
70 65
71 let owner_announcement = EventBuilder::new( 66 let owner_announcement = EventBuilder::new(Kind::GitRepoAnnouncement, "Owner's repository")
72 Kind::GitRepoAnnouncement, 67 .tags(vec![
73 "Owner's repository", 68 Tag::identifier(identifier),
74 ) 69 Tag::custom(
75 .tags(vec![ 70 TagKind::custom("clone"),
76 Tag::identifier(identifier), 71 vec![format!("https://{}/{}.git", relay_b.domain(), identifier)],
77 Tag::custom( 72 ),
78 TagKind::custom("clone"), 73 Tag::custom(
79 vec![format!("https://{}/{}.git", relay_b.domain(), identifier)], 74 TagKind::custom("relays"),
80 ), 75 vec![relay_a.url().to_string(), relay_b.url().to_string()],
81 Tag::custom( 76 ),
82 TagKind::custom("relays"), 77 Tag::custom(
83 vec![relay_a.url().to_string(), relay_b.url().to_string()], 78 TagKind::custom("maintainers"),
84 ), 79 vec![maintainer_keys.public_key().to_hex()],
85 Tag::custom( 80 ),
86 TagKind::custom("maintainers"), 81 ])
87 vec![maintainer_keys.public_key().to_hex()], 82 .sign_with_keys(&owner_keys)
88 ), 83 .unwrap();
89 ])
90 .sign_with_keys(&owner_keys)
91 .unwrap();
92 84
93 client_b.send_event(&owner_announcement).await.unwrap(); 85 client_b.send_event(&owner_announcement).await.unwrap();
94 println!("✓ Owner announcement sent to relay_b"); 86 println!("✓ Owner announcement sent to relay_b");
@@ -104,7 +96,8 @@ async fn test_maintainer_announcement_reprocessed_immediately() {
104 .author(owner_keys.public_key()) 96 .author(owner_keys.public_key())
105 .identifier(identifier); 97 .identifier(identifier);
106 98
107 let owner_found = wait_for_event_on_relay(relay_b.url(), owner_filter, Duration::from_secs(2)).await; 99 let owner_found =
100 wait_for_event_on_relay(relay_b.url(), owner_filter, Duration::from_secs(2)).await;
108 assert!(owner_found, "Owner announcement should be in relay_b"); 101 assert!(owner_found, "Owner announcement should be in relay_b");
109 102
110 let maintainer_filter = Filter::new() 103 let maintainer_filter = Filter::new()
@@ -112,8 +105,12 @@ async fn test_maintainer_announcement_reprocessed_immediately() {
112 .author(maintainer_keys.public_key()) 105 .author(maintainer_keys.public_key())
113 .identifier(identifier); 106 .identifier(identifier);
114 107
115 let maintainer_found = wait_for_event_on_relay(relay_b.url(), maintainer_filter, Duration::from_secs(2)).await; 108 let maintainer_found =
116 assert!(maintainer_found, "Maintainer announcement should be re-processed and accepted in relay_b"); 109 wait_for_event_on_relay(relay_b.url(), maintainer_filter, Duration::from_secs(2)).await;
110 assert!(
111 maintainer_found,
112 "Maintainer announcement should be re-processed and accepted in relay_b"
113 );
117 114
118 // Step 5: Verify it happened quickly (not 24 hours!) 115 // Step 5: Verify it happened quickly (not 24 hours!)
119 assert!( 116 assert!(
@@ -145,36 +142,34 @@ async fn test_maintainer_announcement_reprocessed_immediately() {
145#[ignore] // Skip by default due to 2+ minute duration 142#[ignore] // Skip by default due to 2+ minute duration
146async fn test_maintainer_announcement_cold_index_prevents_refetch() { 143async fn test_maintainer_announcement_cold_index_prevents_refetch() {
147 let relay = TestRelay::start().await; 144 let relay = TestRelay::start().await;
148 145
149 // Create keys 146 // Create keys
150 let owner_keys = Keys::generate(); 147 let owner_keys = Keys::generate();
151 let maintainer_keys = Keys::generate(); 148 let maintainer_keys = Keys::generate();
152 149
153 let identifier = "test-repo-cold"; 150 let identifier = "test-repo-cold";
154 151
155 // Create client using TestClient helper 152 // Create client using TestClient helper
156 let client = TestClient::new(relay.url(), maintainer_keys.clone()) 153 let client = TestClient::new(relay.url(), maintainer_keys.clone())
157 .await 154 .await
158 .expect("Failed to connect to relay"); 155 .expect("Failed to connect to relay");
159 156
160 // Step 1: Send maintainer announcement (will be rejected - doesn't list our relay) 157 // Step 1: Send maintainer announcement (will be rejected - doesn't list our relay)
161 let maintainer_announcement = EventBuilder::new( 158 let maintainer_announcement =
162 Kind::GitRepoAnnouncement, 159 EventBuilder::new(Kind::GitRepoAnnouncement, "Maintainer's repository")
163 "Maintainer's repository", 160 .tags(vec![
164 ) 161 Tag::identifier(identifier),
165 .tags(vec![ 162 Tag::custom(
166 Tag::identifier(identifier), 163 TagKind::custom("clone"),
167 Tag::custom( 164 vec![format!("https://example.com/{}.git", identifier)],
168 TagKind::custom("clone"), 165 ),
169 vec![format!("https://example.com/{}.git", identifier)], 166 Tag::custom(
170 ), 167 TagKind::custom("relays"),
171 Tag::custom( 168 vec!["wss://example.com".to_string()],
172 TagKind::custom("relays"), 169 ),
173 vec!["wss://example.com".to_string()], 170 ])
174 ), 171 .sign_with_keys(&maintainer_keys)
175 ]) 172 .unwrap();
176 .sign_with_keys(&maintainer_keys)
177 .unwrap();
178 173
179 // Send maintainer announcement - expect it to be rejected 174 // Send maintainer announcement - expect it to be rejected
180 let _ = client.send_event(&maintainer_announcement).await; 175 let _ = client.send_event(&maintainer_announcement).await;
@@ -185,27 +180,21 @@ async fn test_maintainer_announcement_cold_index_prevents_refetch() {
185 tokio::time::sleep(Duration::from_secs(125)).await; 180 tokio::time::sleep(Duration::from_secs(125)).await;
186 181
187 // Step 3: Send owner announcement (lists maintainer) 182 // Step 3: Send owner announcement (lists maintainer)
188 let owner_announcement = EventBuilder::new( 183 let owner_announcement = EventBuilder::new(Kind::GitRepoAnnouncement, "Owner's repository")
189 Kind::GitRepoAnnouncement, 184 .tags(vec![
190 "Owner's repository", 185 Tag::identifier(identifier),
191 ) 186 Tag::custom(
192 .tags(vec![ 187 TagKind::custom("clone"),
193 Tag::identifier(identifier), 188 vec![format!("https://{}/{}.git", relay.domain(), identifier)],
194 Tag::custom( 189 ),
195 TagKind::custom("clone"), 190 Tag::custom(TagKind::custom("relays"), vec![relay.url().to_string()]),
196 vec![format!("https://{}/{}.git", relay.domain(), identifier)], 191 Tag::custom(
197 ), 192 TagKind::custom("maintainers"),
198 Tag::custom( 193 vec![maintainer_keys.public_key().to_hex()],
199 TagKind::custom("relays"), 194 ),
200 vec![relay.url().to_string()], 195 ])
201 ), 196 .sign_with_keys(&owner_keys)
202 Tag::custom( 197 .unwrap();
203 TagKind::custom("maintainers"),
204 vec![maintainer_keys.public_key().to_hex()],
205 ),
206 ])
207 .sign_with_keys(&owner_keys)
208 .unwrap();
209 198
210 client.send_event(&owner_announcement).await.unwrap(); 199 client.send_event(&owner_announcement).await.unwrap();
211 tokio::time::sleep(Duration::from_millis(500)).await; 200 tokio::time::sleep(Duration::from_millis(500)).await;
@@ -215,16 +204,18 @@ async fn test_maintainer_announcement_cold_index_prevents_refetch() {
215 .kind(Kind::GitRepoAnnouncement) 204 .kind(Kind::GitRepoAnnouncement)
216 .author(owner_keys.public_key()) 205 .author(owner_keys.public_key())
217 .identifier(identifier); 206 .identifier(identifier);
218 207
219 let owner_found = wait_for_event_on_relay(relay.url(), owner_filter, Duration::from_secs(2)).await; 208 let owner_found =
209 wait_for_event_on_relay(relay.url(), owner_filter, Duration::from_secs(2)).await;
220 assert!(owner_found, "Owner announcement should be accepted"); 210 assert!(owner_found, "Owner announcement should be accepted");
221 211
222 let maintainer_filter = Filter::new() 212 let maintainer_filter = Filter::new()
223 .kind(Kind::GitRepoAnnouncement) 213 .kind(Kind::GitRepoAnnouncement)
224 .author(maintainer_keys.public_key()) 214 .author(maintainer_keys.public_key())
225 .identifier(identifier); 215 .identifier(identifier);
226 216
227 let maintainer_found = wait_for_event_on_relay(relay.url(), maintainer_filter, Duration::from_millis(500)).await; 217 let maintainer_found =
218 wait_for_event_on_relay(relay.url(), maintainer_filter, Duration::from_millis(500)).await;
228 assert!( 219 assert!(
229 !maintainer_found, 220 !maintainer_found,
230 "Maintainer announcement should NOT be re-processed (hot cache expired)" 221 "Maintainer announcement should NOT be re-processed (hot cache expired)"
@@ -267,7 +258,10 @@ async fn test_multiple_maintainers_all_reprocessed() {
267 .await 258 .await
268 .expect("Failed to connect to relay_a"); 259 .expect("Failed to connect to relay_a");
269 260
270 for (idx, maintainer_keys) in [&maintainer1_keys, &maintainer2_keys, &maintainer3_keys].iter().enumerate() { 261 for (idx, maintainer_keys) in [&maintainer1_keys, &maintainer2_keys, &maintainer3_keys]
262 .iter()
263 .enumerate()
264 {
271 let announcement = EventBuilder::new( 265 let announcement = EventBuilder::new(
272 Kind::GitRepoAnnouncement, 266 Kind::GitRepoAnnouncement,
273 format!("Maintainer {} repository", idx + 1), 267 format!("Maintainer {} repository", idx + 1),
@@ -278,10 +272,7 @@ async fn test_multiple_maintainers_all_reprocessed() {
278 TagKind::custom("clone"), 272 TagKind::custom("clone"),
279 vec![format!("https://{}/{}.git", relay_a.domain(), identifier)], 273 vec![format!("https://{}/{}.git", relay_a.domain(), identifier)],
280 ), 274 ),
281 Tag::custom( 275 Tag::custom(TagKind::custom("relays"), vec![relay_a.url().to_string()]),
282 TagKind::custom("relays"),
283 vec![relay_a.url().to_string()],
284 ),
285 ]) 276 ])
286 .sign_with_keys(maintainer_keys) 277 .sign_with_keys(maintainer_keys)
287 .unwrap(); 278 .unwrap();
@@ -295,31 +286,28 @@ async fn test_multiple_maintainers_all_reprocessed() {
295 .await 286 .await
296 .expect("Failed to connect to relay_b"); 287 .expect("Failed to connect to relay_b");
297 288
298 let owner_announcement = EventBuilder::new( 289 let owner_announcement = EventBuilder::new(Kind::GitRepoAnnouncement, "Owner's repository")
299 Kind::GitRepoAnnouncement, 290 .tags(vec![
300 "Owner's repository", 291 Tag::identifier(identifier),
301 ) 292 Tag::custom(
302 .tags(vec![ 293 TagKind::custom("clone"),
303 Tag::identifier(identifier), 294 vec![format!("https://{}/{}.git", relay_b.domain(), identifier)],
304 Tag::custom( 295 ),
305 TagKind::custom("clone"), 296 Tag::custom(
306 vec![format!("https://{}/{}.git", relay_b.domain(), identifier)], 297 TagKind::custom("relays"),
307 ), 298 vec![relay_a.url().to_string(), relay_b.url().to_string()],
308 Tag::custom( 299 ),
309 TagKind::custom("relays"), 300 Tag::custom(
310 vec![relay_a.url().to_string(), relay_b.url().to_string()], 301 TagKind::custom("maintainers"),
311 ), 302 vec![
312 Tag::custom( 303 maintainer1_keys.public_key().to_hex(),
313 TagKind::custom("maintainers"), 304 maintainer2_keys.public_key().to_hex(),
314 vec![ 305 maintainer3_keys.public_key().to_hex(),
315 maintainer1_keys.public_key().to_hex(), 306 ],
316 maintainer2_keys.public_key().to_hex(), 307 ),
317 maintainer3_keys.public_key().to_hex(), 308 ])
318 ], 309 .sign_with_keys(&owner_keys)
319 ), 310 .unwrap();
320 ])
321 .sign_with_keys(&owner_keys)
322 .unwrap();
323 311
324 client_b.send_event(&owner_announcement).await.unwrap(); 312 client_b.send_event(&owner_announcement).await.unwrap();
325 println!("✓ Owner announcement sent to relay_b"); 313 println!("✓ Owner announcement sent to relay_b");
@@ -340,11 +328,7 @@ async fn test_multiple_maintainers_all_reprocessed() {
340 .identifier(identifier); 328 .identifier(identifier);
341 329
342 let found = wait_for_event_on_relay(relay_b.url(), filter, Duration::from_secs(2)).await; 330 let found = wait_for_event_on_relay(relay_b.url(), filter, Duration::from_secs(2)).await;
343 assert!( 331 assert!(found, "{} announcement should be in relay_b", name);
344 found,
345 "{} announcement should be in relay_b",
346 name
347 );
348 } 332 }
349 333
350 println!("✅ All three maintainer announcements re-processed successfully"); 334 println!("✅ All three maintainer announcements re-processed successfully");
@@ -365,63 +349,55 @@ async fn test_multiple_maintainers_all_reprocessed() {
365#[tokio::test] 349#[tokio::test]
366async fn test_invalid_maintainer_pubkey_handled_gracefully() { 350async fn test_invalid_maintainer_pubkey_handled_gracefully() {
367 let relay = TestRelay::start().await; 351 let relay = TestRelay::start().await;
368 352
369 // Create keys 353 // Create keys
370 let owner_keys = Keys::generate(); 354 let owner_keys = Keys::generate();
371 let maintainer_keys = Keys::generate(); 355 let maintainer_keys = Keys::generate();
372 356
373 let identifier = "invalid-maintainer-repo"; 357 let identifier = "invalid-maintainer-repo";
374 358
375 // Create client using TestClient helper 359 // Create client using TestClient helper
376 let client = TestClient::new(relay.url(), owner_keys.clone()) 360 let client = TestClient::new(relay.url(), owner_keys.clone())
377 .await 361 .await
378 .expect("Failed to connect to relay"); 362 .expect("Failed to connect to relay");
379 363
380 // Step 1: Send maintainer announcement (will be rejected - doesn't list our relay) 364 // Step 1: Send maintainer announcement (will be rejected - doesn't list our relay)
381 let maintainer_announcement = EventBuilder::new( 365 let maintainer_announcement =
382 Kind::GitRepoAnnouncement, 366 EventBuilder::new(Kind::GitRepoAnnouncement, "Maintainer's repository")
383 "Maintainer's repository", 367 .tags(vec![
384 ) 368 Tag::identifier(identifier),
385 .tags(vec![ 369 Tag::custom(
386 Tag::identifier(identifier), 370 TagKind::custom("clone"),
387 Tag::custom( 371 vec![format!("https://example.com/{}.git", identifier)],
388 TagKind::custom("clone"), 372 ),
389 vec![format!("https://example.com/{}.git", identifier)], 373 Tag::custom(
390 ), 374 TagKind::custom("relays"),
391 Tag::custom( 375 vec!["wss://example.com".to_string()],
392 TagKind::custom("relays"), 376 ),
393 vec!["wss://example.com".to_string()], 377 ])
394 ), 378 .sign_with_keys(&maintainer_keys)
395 ]) 379 .unwrap();
396 .sign_with_keys(&maintainer_keys)
397 .unwrap();
398 380
399 // Send maintainer announcement - expect it to be rejected 381 // Send maintainer announcement - expect it to be rejected
400 let _ = client.send_event(&maintainer_announcement).await; 382 let _ = client.send_event(&maintainer_announcement).await;
401 tokio::time::sleep(Duration::from_millis(200)).await; 383 tokio::time::sleep(Duration::from_millis(200)).await;
402 384
403 // Step 2: Send owner announcement with INVALID maintainer hex 385 // Step 2: Send owner announcement with INVALID maintainer hex
404 let owner_announcement = EventBuilder::new( 386 let owner_announcement = EventBuilder::new(Kind::GitRepoAnnouncement, "Owner's repository")
405 Kind::GitRepoAnnouncement, 387 .tags(vec![
406 "Owner's repository", 388 Tag::identifier(identifier),
407 ) 389 Tag::custom(
408 .tags(vec![ 390 TagKind::custom("clone"),
409 Tag::identifier(identifier), 391 vec![format!("https://{}/{}.git", relay.domain(), identifier)],
410 Tag::custom( 392 ),
411 TagKind::custom("clone"), 393 Tag::custom(TagKind::custom("relays"), vec![relay.url().to_string()]),
412 vec![format!("https://{}/{}.git", relay.domain(), identifier)], 394 Tag::custom(
413 ), 395 TagKind::custom("maintainers"),
414 Tag::custom( 396 vec!["invalid-hex-not-a-pubkey".to_string()],
415 TagKind::custom("relays"), 397 ),
416 vec![relay.url().to_string()], 398 ])
417 ), 399 .sign_with_keys(&owner_keys)
418 Tag::custom( 400 .unwrap();
419 TagKind::custom("maintainers"),
420 vec!["invalid-hex-not-a-pubkey".to_string()],
421 ),
422 ])
423 .sign_with_keys(&owner_keys)
424 .unwrap();
425 401
426 client.send_event(&owner_announcement).await.unwrap(); 402 client.send_event(&owner_announcement).await.unwrap();
427 tokio::time::sleep(Duration::from_millis(500)).await; 403 tokio::time::sleep(Duration::from_millis(500)).await;
@@ -431,16 +407,21 @@ async fn test_invalid_maintainer_pubkey_handled_gracefully() {
431 .kind(Kind::GitRepoAnnouncement) 407 .kind(Kind::GitRepoAnnouncement)
432 .author(owner_keys.public_key()) 408 .author(owner_keys.public_key())
433 .identifier(identifier); 409 .identifier(identifier);
434 410
435 let owner_found = wait_for_event_on_relay(relay.url(), owner_filter, Duration::from_secs(2)).await; 411 let owner_found =
436 assert!(owner_found, "Owner announcement should be accepted despite invalid maintainer"); 412 wait_for_event_on_relay(relay.url(), owner_filter, Duration::from_secs(2)).await;
413 assert!(
414 owner_found,
415 "Owner announcement should be accepted despite invalid maintainer"
416 );
437 417
438 let maintainer_filter = Filter::new() 418 let maintainer_filter = Filter::new()
439 .kind(Kind::GitRepoAnnouncement) 419 .kind(Kind::GitRepoAnnouncement)
440 .author(maintainer_keys.public_key()) 420 .author(maintainer_keys.public_key())
441 .identifier(identifier); 421 .identifier(identifier);
442 422
443 let maintainer_found = wait_for_event_on_relay(relay.url(), maintainer_filter, Duration::from_millis(500)).await; 423 let maintainer_found =
424 wait_for_event_on_relay(relay.url(), maintainer_filter, Duration::from_millis(500)).await;
444 assert!( 425 assert!(
445 !maintainer_found, 426 !maintainer_found,
446 "Maintainer announcement should NOT be re-processed (invalid pubkey)" 427 "Maintainer announcement should NOT be re-processed (invalid pubkey)"