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.rs153
1 files changed, 110 insertions, 43 deletions
diff --git a/tests/sync/maintainer_reprocessing.rs b/tests/sync/maintainer_reprocessing.rs
index df1bf78..266a437 100644
--- a/tests/sync/maintainer_reprocessing.rs
+++ b/tests/sync/maintainer_reprocessing.rs
@@ -7,7 +7,10 @@ use std::time::Duration;
7 7
8use nostr_sdk::prelude::*; 8use nostr_sdk::prelude::*;
9 9
10use crate::common::{sync_helpers::*, TestRelay}; 10use crate::common::{
11 sync_helpers::*,
12 TestRelay,
13};
11 14
12/// Test that maintainer announcements are re-processed immediately when owner announcement accepted 15/// Test that maintainer announcements are re-processed immediately when owner announcement accepted
13/// 16///
@@ -37,10 +40,12 @@ async fn test_maintainer_announcement_reprocessed_immediately() {
37 40
38 let start = std::time::Instant::now(); 41 let start = std::time::Instant::now();
39 42
40 // Step 1: Send maintainer announcement to relay_a (will be rejected - doesn't list relay_b) 43 // Step 1: Send maintainer announcement to relay_a (will be rejected by relay_b - doesn't list relay_b)
41 let client_a = TestClient::new(relay_a.url(), maintainer_keys.clone()) 44 // Use HTTP clone URL pointing to relay_a's git endpoint so it can be released from purgatory
42 .await 45 let maintainer_npub = maintainer_keys
43 .expect("Failed to connect to relay_a"); 46 .public_key()
47 .to_bech32()
48 .expect("Failed to get npub");
44 49
45 let maintainer_announcement = 50 let maintainer_announcement =
46 EventBuilder::new(Kind::GitRepoAnnouncement, "Maintainer's repository") 51 EventBuilder::new(Kind::GitRepoAnnouncement, "Maintainer's repository")
@@ -48,27 +53,50 @@ async fn test_maintainer_announcement_reprocessed_immediately() {
48 Tag::identifier(identifier), 53 Tag::identifier(identifier),
49 Tag::custom( 54 Tag::custom(
50 TagKind::custom("clone"), 55 TagKind::custom("clone"),
51 vec![format!("https://{}/{}.git", relay_a.domain(), identifier)], 56 vec![format!(
57 "http://{}/{}/{}.git",
58 relay_a.domain(),
59 maintainer_npub,
60 identifier
61 )],
52 ), 62 ),
53 Tag::custom(TagKind::custom("relays"), vec![relay_a.url().to_string()]), 63 Tag::custom(TagKind::custom("relays"), vec![relay_a.url().to_string()]),
54 ]) 64 ])
55 .sign_with_keys(&maintainer_keys) 65 .sign_with_keys(&maintainer_keys)
56 .unwrap(); 66 .unwrap();
57 67
58 client_a.send_event(&maintainer_announcement).await.unwrap(); 68 send_to_relay(&relay_a, &maintainer_announcement)
69 .await
70 .unwrap();
59 println!("✓ Maintainer announcement sent to relay_a"); 71 println!("✓ Maintainer announcement sent to relay_a");
60 72
61 // Step 2: Send owner announcement to relay_b (lists relay_a + maintainer) 73 // Push git data for maintainer's repo to relay_a → releases maintainer announcement from purgatory
62 let client_b = TestClient::new(relay_b.url(), owner_keys.clone()) 74 let _git_dir_maintainer = push_git_data_to_relay(
63 .await 75 &relay_a,
64 .expect("Failed to connect to relay_b"); 76 &maintainer_keys,
77 identifier,
78 &[&relay_a.domain()],
79 )
80 .await;
81 println!("✓ Maintainer git data pushed to relay_a (announcement released from purgatory)");
82
83 // Step 2: Set up owner announcement on relay_b (lists relay_a + maintainer) with git data
84 let owner_npub = owner_keys
85 .public_key()
86 .to_bech32()
87 .expect("Failed to get npub");
65 88
66 let owner_announcement = EventBuilder::new(Kind::GitRepoAnnouncement, "Owner's repository") 89 let owner_announcement = EventBuilder::new(Kind::GitRepoAnnouncement, "Owner's repository")
67 .tags(vec![ 90 .tags(vec![
68 Tag::identifier(identifier), 91 Tag::identifier(identifier),
69 Tag::custom( 92 Tag::custom(
70 TagKind::custom("clone"), 93 TagKind::custom("clone"),
71 vec![format!("https://{}/{}.git", relay_b.domain(), identifier)], 94 vec![format!(
95 "http://{}/{}/{}.git",
96 relay_b.domain(),
97 owner_npub,
98 identifier
99 )],
72 ), 100 ),
73 Tag::custom( 101 Tag::custom(
74 TagKind::custom("relays"), 102 TagKind::custom("relays"),
@@ -82,9 +110,14 @@ async fn test_maintainer_announcement_reprocessed_immediately() {
82 .sign_with_keys(&owner_keys) 110 .sign_with_keys(&owner_keys)
83 .unwrap(); 111 .unwrap();
84 112
85 client_b.send_event(&owner_announcement).await.unwrap(); 113 send_to_relay(&relay_b, &owner_announcement).await.unwrap();
86 println!("✓ Owner announcement sent to relay_b"); 114 println!("✓ Owner announcement sent to relay_b");
87 115
116 // Push git data for owner's repo to relay_b → releases owner announcement from purgatory
117 let _git_dir_owner =
118 push_git_data_to_relay(&relay_b, &owner_keys, identifier, &[&relay_b.domain()]).await;
119 println!("✓ Owner git data pushed to relay_b (announcement released from purgatory)");
120
88 // Step 3: Wait for sync and re-processing (relay_b discovers relay_a, syncs, re-processes) 121 // Step 3: Wait for sync and re-processing (relay_b discovers relay_a, syncs, re-processes)
89 tokio::time::sleep(Duration::from_secs(3)).await; 122 tokio::time::sleep(Duration::from_secs(3)).await;
90 123
@@ -114,15 +147,13 @@ async fn test_maintainer_announcement_reprocessed_immediately() {
114 147
115 // Step 5: Verify it happened quickly (not 24 hours!) 148 // Step 5: Verify it happened quickly (not 24 hours!)
116 assert!( 149 assert!(
117 elapsed.as_secs() < 10, 150 elapsed.as_secs() < 15,
118 "Re-processing should happen in <10 seconds, took {:?}", 151 "Re-processing should happen in <15 seconds, took {:?}",
119 elapsed 152 elapsed
120 ); 153 );
121 154
122 println!("✅ Maintainer announcement re-processed in {:?}", elapsed); 155 println!("✅ Maintainer announcement re-processed in {:?}", elapsed);
123 156
124 client_a.disconnect().await;
125 client_b.disconnect().await;
126 relay_a.stop().await; 157 relay_a.stop().await;
127 relay_b.stop().await; 158 relay_b.stop().await;
128} 159}
@@ -253,15 +284,18 @@ async fn test_multiple_maintainers_all_reprocessed() {
253 284
254 let identifier = "multi-maintainer-repo"; 285 let identifier = "multi-maintainer-repo";
255 286
256 // Step 1: Send three maintainer announcements to relay_a 287 // Step 1: Send three maintainer announcements to relay_a with git data
257 let client_a = TestClient::new(relay_a.url(), maintainer1_keys.clone()) 288 // (purgatory requires git data before announcements are accepted)
258 .await 289 let mut git_dirs_maintainers = Vec::new();
259 .expect("Failed to connect to relay_a");
260
261 for (idx, maintainer_keys) in [&maintainer1_keys, &maintainer2_keys, &maintainer3_keys] 290 for (idx, maintainer_keys) in [&maintainer1_keys, &maintainer2_keys, &maintainer3_keys]
262 .iter() 291 .iter()
263 .enumerate() 292 .enumerate()
264 { 293 {
294 let m_npub = maintainer_keys
295 .public_key()
296 .to_bech32()
297 .expect("Failed to get npub");
298
265 let announcement = EventBuilder::new( 299 let announcement = EventBuilder::new(
266 Kind::GitRepoAnnouncement, 300 Kind::GitRepoAnnouncement,
267 format!("Maintainer {} repository", idx + 1), 301 format!("Maintainer {} repository", idx + 1),
@@ -270,28 +304,45 @@ async fn test_multiple_maintainers_all_reprocessed() {
270 Tag::identifier(identifier), 304 Tag::identifier(identifier),
271 Tag::custom( 305 Tag::custom(
272 TagKind::custom("clone"), 306 TagKind::custom("clone"),
273 vec![format!("https://{}/{}.git", relay_a.domain(), identifier)], 307 vec![format!(
308 "http://{}/{}/{}.git",
309 relay_a.domain(),
310 m_npub,
311 identifier
312 )],
274 ), 313 ),
275 Tag::custom(TagKind::custom("relays"), vec![relay_a.url().to_string()]), 314 Tag::custom(TagKind::custom("relays"), vec![relay_a.url().to_string()]),
276 ]) 315 ])
277 .sign_with_keys(maintainer_keys) 316 .sign_with_keys(maintainer_keys)
278 .unwrap(); 317 .unwrap();
279 318
280 client_a.send_event(&announcement).await.unwrap(); 319 send_to_relay(&relay_a, &announcement).await.unwrap();
320
321 // Push git data to release each maintainer's announcement from purgatory
322 let git_dir =
323 push_git_data_to_relay(&relay_a, maintainer_keys, identifier, &[&relay_a.domain()])
324 .await;
325 git_dirs_maintainers.push(git_dir);
281 } 326 }
282 println!("✓ Three maintainer announcements sent to relay_a"); 327 println!("✓ Three maintainer announcements sent to relay_a with git data");
283 328
284 // Step 2: Send owner announcement to relay_b (lists relay_a + all three maintainers) 329 // Step 2: Send owner announcement to relay_b (lists relay_a + all three maintainers)
285 let client_b = TestClient::new(relay_b.url(), owner_keys.clone()) 330 let owner_npub = owner_keys
286 .await 331 .public_key()
287 .expect("Failed to connect to relay_b"); 332 .to_bech32()
333 .expect("Failed to get npub");
288 334
289 let owner_announcement = EventBuilder::new(Kind::GitRepoAnnouncement, "Owner's repository") 335 let owner_announcement = EventBuilder::new(Kind::GitRepoAnnouncement, "Owner's repository")
290 .tags(vec![ 336 .tags(vec![
291 Tag::identifier(identifier), 337 Tag::identifier(identifier),
292 Tag::custom( 338 Tag::custom(
293 TagKind::custom("clone"), 339 TagKind::custom("clone"),
294 vec![format!("https://{}/{}.git", relay_b.domain(), identifier)], 340 vec![format!(
341 "http://{}/{}/{}.git",
342 relay_b.domain(),
343 owner_npub,
344 identifier
345 )],
295 ), 346 ),
296 Tag::custom( 347 Tag::custom(
297 TagKind::custom("relays"), 348 TagKind::custom("relays"),
@@ -309,9 +360,14 @@ async fn test_multiple_maintainers_all_reprocessed() {
309 .sign_with_keys(&owner_keys) 360 .sign_with_keys(&owner_keys)
310 .unwrap(); 361 .unwrap();
311 362
312 client_b.send_event(&owner_announcement).await.unwrap(); 363 send_to_relay(&relay_b, &owner_announcement).await.unwrap();
313 println!("✓ Owner announcement sent to relay_b"); 364 println!("✓ Owner announcement sent to relay_b");
314 365
366 // Push git data for owner to relay_b → releases owner announcement from purgatory
367 let _git_dir_owner =
368 push_git_data_to_relay(&relay_b, &owner_keys, identifier, &[&relay_b.domain()]).await;
369 println!("✓ Owner git data pushed to relay_b (announcement released from purgatory)");
370
315 // Step 3: Wait for sync and re-processing 371 // Step 3: Wait for sync and re-processing
316 tokio::time::sleep(Duration::from_secs(3)).await; 372 tokio::time::sleep(Duration::from_secs(3)).await;
317 373
@@ -333,8 +389,6 @@ async fn test_multiple_maintainers_all_reprocessed() {
333 389
334 println!("✅ All three maintainer announcements re-processed successfully"); 390 println!("✅ All three maintainer announcements re-processed successfully");
335 391
336 client_a.disconnect().await;
337 client_b.disconnect().await;
338 relay_a.stop().await; 392 relay_a.stop().await;
339 relay_b.stop().await; 393 relay_b.stop().await;
340} 394}
@@ -356,12 +410,8 @@ async fn test_invalid_maintainer_pubkey_handled_gracefully() {
356 410
357 let identifier = "invalid-maintainer-repo"; 411 let identifier = "invalid-maintainer-repo";
358 412
359 // Create client using TestClient helper
360 let client = TestClient::new(relay.url(), owner_keys.clone())
361 .await
362 .expect("Failed to connect to relay");
363
364 // Step 1: Send maintainer announcement (will be rejected - doesn't list our relay) 413 // Step 1: Send maintainer announcement (will be rejected - doesn't list our relay)
414 // This one uses example.com clone URL - it goes to purgatory on relay, never promoted
365 let maintainer_announcement = 415 let maintainer_announcement =
366 EventBuilder::new(Kind::GitRepoAnnouncement, "Maintainer's repository") 416 EventBuilder::new(Kind::GitRepoAnnouncement, "Maintainer's repository")
367 .tags(vec![ 417 .tags(vec![
@@ -378,17 +428,28 @@ async fn test_invalid_maintainer_pubkey_handled_gracefully() {
378 .sign_with_keys(&maintainer_keys) 428 .sign_with_keys(&maintainer_keys)
379 .unwrap(); 429 .unwrap();
380 430
381 // Send maintainer announcement - expect it to be rejected 431 // Send maintainer announcement - expect it to be rejected (purgatory / policy)
382 let _ = client.send_event(&maintainer_announcement).await; 432 send_to_relay(&relay, &maintainer_announcement).await.ok();
383 tokio::time::sleep(Duration::from_millis(200)).await; 433 tokio::time::sleep(Duration::from_millis(200)).await;
384 434
385 // Step 2: Send owner announcement with INVALID maintainer hex 435 // Step 2: Set up owner announcement with INVALID maintainer hex and git data
436 // Use HTTP clone URL to relay's git endpoint so it can be released from purgatory
437 let owner_npub = owner_keys
438 .public_key()
439 .to_bech32()
440 .expect("Failed to get npub");
441
386 let owner_announcement = EventBuilder::new(Kind::GitRepoAnnouncement, "Owner's repository") 442 let owner_announcement = EventBuilder::new(Kind::GitRepoAnnouncement, "Owner's repository")
387 .tags(vec![ 443 .tags(vec![
388 Tag::identifier(identifier), 444 Tag::identifier(identifier),
389 Tag::custom( 445 Tag::custom(
390 TagKind::custom("clone"), 446 TagKind::custom("clone"),
391 vec![format!("https://{}/{}.git", relay.domain(), identifier)], 447 vec![format!(
448 "http://{}/{}/{}.git",
449 relay.domain(),
450 owner_npub,
451 identifier
452 )],
392 ), 453 ),
393 Tag::custom(TagKind::custom("relays"), vec![relay.url().to_string()]), 454 Tag::custom(TagKind::custom("relays"), vec![relay.url().to_string()]),
394 Tag::custom( 455 Tag::custom(
@@ -399,7 +460,14 @@ async fn test_invalid_maintainer_pubkey_handled_gracefully() {
399 .sign_with_keys(&owner_keys) 460 .sign_with_keys(&owner_keys)
400 .unwrap(); 461 .unwrap();
401 462
402 client.send_event(&owner_announcement).await.unwrap(); 463 send_to_relay(&relay, &owner_announcement).await.unwrap();
464
465 // Push git data to relay → releases owner announcement from purgatory
466 let _git_dir =
467 push_git_data_to_relay(&relay, &owner_keys, identifier, &[&relay.domain()]).await;
468 println!("✓ Owner git data pushed to relay (announcement released from purgatory)");
469
470 // Wait for processing
403 tokio::time::sleep(Duration::from_millis(500)).await; 471 tokio::time::sleep(Duration::from_millis(500)).await;
404 472
405 // Step 3: Verify owner announcement accepted, maintainer not re-processed 473 // Step 3: Verify owner announcement accepted, maintainer not re-processed
@@ -429,6 +497,5 @@ async fn test_invalid_maintainer_pubkey_handled_gracefully() {
429 497
430 println!("✅ Invalid maintainer pubkey handled gracefully without panic"); 498 println!("✅ Invalid maintainer pubkey handled gracefully without panic");
431 499
432 client.disconnect().await;
433 relay.stop().await; 500 relay.stop().await;
434} 501}