upleb.uk

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

summaryrefslogtreecommitdiff
path: root/grasp-audit/src/specs/grasp01/purgatory.rs
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2026-02-13 09:24:51 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2026-02-13 09:24:51 +0000
commitf4e8e1089ae6e8e78c3576246d9747bb585fdc18 (patch)
tree37cd429b6c5468996178f1d9bbaafe6f789b3605 /grasp-audit/src/specs/grasp01/purgatory.rs
parentfaac6027deaf5f1e121c05df2d8a6336fd6eaf8d (diff)
test: add PR purgatory tests with PREvent2 fixtures
Add new fixtures for testing PR purgatory mechanism: - PREvent2Generated: PR event with different commit hash - PREvent2Sent: PR event sent to relay (enters purgatory) - PREvent2GitDataPushed: Git data pushed after event sent - PREvent2Served: Full fixture with event served Add PRTestCommit2 variant for second PR test commit. Update purgatory tests to use new fixtures for proper PR purgatory testing.
Diffstat (limited to 'grasp-audit/src/specs/grasp01/purgatory.rs')
-rw-r--r--grasp-audit/src/specs/grasp01/purgatory.rs144
1 files changed, 94 insertions, 50 deletions
diff --git a/grasp-audit/src/specs/grasp01/purgatory.rs b/grasp-audit/src/specs/grasp01/purgatory.rs
index 60b6096..27ab97b 100644
--- a/grasp-audit/src/specs/grasp01/purgatory.rs
+++ b/grasp-audit/src/specs/grasp01/purgatory.rs
@@ -49,9 +49,11 @@ impl PurgatoryTests {
49 results.add(Self::test_state_event_not_served_before_git_data(client).await); 49 results.add(Self::test_state_event_not_served_before_git_data(client).await);
50 results.add(Self::test_state_event_served_after_git_push(client).await); 50 results.add(Self::test_state_event_served_after_git_push(client).await);
51 51
52 // PR purgatory tests (feature not yet implemented) 52 // PR purgatory tests
53 results.add(Self::test_pr_event_not_served_before_git_data(client).await); 53 results.add(Self::test_pr_event_before_git_data_accepted_into_purgatory(client).await);
54 results.add(Self::test_pr_event_served_after_correct_push(client).await); 54 results.add(Self::test_pr_event_remains_in_purgatory_until_git_data(client).await);
55 results.add(Self::test_pr_event_git_push_accepted(client).await);
56 results.add(Self::test_pr_event_served_after_git_push(client).await);
55 57
56 results 58 results
57 } 59 }
@@ -515,37 +517,37 @@ impl PurgatoryTests {
515 /// 1. Send PR event for a repo 517 /// 1. Send PR event for a repo
516 /// 2. PR event is NOT queryable (in purgatory) 518 /// 2. PR event is NOT queryable (in purgatory)
517 /// 3. No git data exists at refs/nostr/<pr-event-id> 519 /// 3. No git data exists at refs/nostr/<pr-event-id>
518 pub async fn test_pr_event_not_served_before_git_data(client: &AuditClient) -> TestResult { 520 pub async fn test_pr_event_before_git_data_accepted_into_purgatory(
521 client: &AuditClient,
522 ) -> TestResult {
519 TestResult::new( 523 TestResult::new(
520 "pr_event_not_served_before_git_data", 524 "pr_event_before_git_data_accepted_into_purgatory",
521 SpecRef::PurgatoryAcceptUntilGitData, 525 SpecRef::PurgatoryAcceptUntilGitData,
522 "PR events SHOULD be accepted but not served until git data arrives", 526 "PR event SHOULD be accepted into purgatory when git data doesn't exist",
523 ) 527 )
524 .run(|| async { 528 .run(|| async {
525 let ctx = TestContext::new(client); 529 let ctx = TestContext::new(client);
526 530
527 // Get a repo announcement
528 let _repo = ctx
529 .get_fixture(FixtureKind::ValidRepoSent)
530 .await
531 .map_err(|e| format!("Failed to create repo: {}", e))?;
532
533 // Build PR event (not sent yet)
534 let pr_event = ctx 531 let pr_event = ctx
535 .build_fixture_only(FixtureKind::PREvent) 532 .get_fixture(FixtureKind::PREvent2Sent)
536 .await 533 .await
537 .map_err(|e| format!("Failed to build PR event: {}", e))?; 534 .map_err(|e| format!("Failed to send PR event: {}", e))?;
538 535
539 // Send PR event 536 let filter = Filter::new()
540 let (_, in_purgatory) = client 537 .kind(Kind::GitPullRequest)
541 .send_event_and_note_purgatory(pr_event.clone()) 538 .author(client.pr_author_keys().public_key())
539 .id(pr_event.id);
540
541 tokio::time::sleep(Duration::from_millis(300)).await;
542
543 let events = client
544 .query(filter)
542 .await 545 .await
543 .map_err(|e| format!("Failed to send PR event: {}", e))?; 546 .map_err(|e| format!("Failed to query PR events: {}", e))?;
544 547
545 if !in_purgatory { 548 if !events.is_empty() {
546 return Err(format!( 549 return Err(format!(
547 "PR event was served immediately - purgatory not implemented. \ 550 "PR event was served immediately - should be in purgatory. Event ID: {}",
548 Event ID: {} should NOT be queryable until git data arrives",
549 pr_event.id 551 pr_event.id
550 )); 552 ));
551 } 553 }
@@ -555,46 +557,89 @@ impl PurgatoryTests {
555 .await 557 .await
556 } 558 }
557 559
558 /// Test: PR event served after correct push 560 /// Test: PR event remains in purgatory until git data arrives
559 ///
560 /// Spec: GRASP-01 Line 22
561 /// "...kept in purgatory (not served) until the related git data arrives"
562 /// 561 ///
563 /// This test verifies: 562 /// Verifies the event stays in purgatory until matching git data is pushed.
564 /// 1. Send PR event (enters purgatory) 563 pub async fn test_pr_event_remains_in_purgatory_until_git_data(
565 /// 2. Push git data to refs/nostr/<pr-event-id> with correct commit 564 client: &AuditClient,
566 /// 3. PR event is now served 565 ) -> TestResult {
567 pub async fn test_pr_event_served_after_correct_push(client: &AuditClient) -> TestResult {
568 TestResult::new( 566 TestResult::new(
569 "pr_event_served_after_correct_push", 567 "pr_event_remains_in_purgatory_until_git_data",
570 SpecRef::PurgatoryAcceptUntilGitData, 568 SpecRef::PurgatoryAcceptUntilGitData,
571 "PR events SHOULD be served after matching git data arrives", 569 "PR event SHOULD remain in purgatory until git data arrives",
572 ) 570 )
573 .run(|| async { 571 .run(|| async {
574 let ctx = TestContext::new(client); 572 let ctx = TestContext::new(client);
575 573
576 // Get a repo with git data 574 let pr_event = ctx
577 let _existing_state = ctx 575 .get_fixture(FixtureKind::PREvent2Sent)
578 .get_fixture(FixtureKind::OwnerStateDataPushed)
579 .await 576 .await
580 .map_err(|e| format!("Failed to get existing repo: {}", e))?; 577 .map_err(|e| format!("Failed to get PR event: {}", e))?;
581 578
582 // Build PR event 579 tokio::time::sleep(Duration::from_millis(500)).await;
583 let pr_event = ctx 580
584 .build_fixture_only(FixtureKind::PREvent) 581 let filter = Filter::new()
582 .kind(Kind::GitPullRequest)
583 .author(client.pr_author_keys().public_key())
584 .id(pr_event.id);
585
586 let events = client
587 .query(filter)
585 .await 588 .await
586 .map_err(|e| format!("Failed to build PR event: {}", e))?; 589 .map_err(|e| format!("Failed to query PR events: {}", e))?;
590
591 if !events.is_empty() {
592 return Err(format!(
593 "PR event was served without git data - purgatory not working. Event ID: {}",
594 pr_event.id
595 ));
596 }
597
598 Ok(())
599 })
600 .await
601 }
587 602
588 // Send PR event (should enter purgatory) 603 /// Test: Git push accepted for PR event in purgatory
589 let (_, _in_purgatory) = client 604 ///
590 .send_event_and_note_purgatory(pr_event.clone()) 605 /// Verifies that pushing the correct commit to refs/nostr/<pr-event-id>
606 /// is accepted.
607 pub async fn test_pr_event_git_push_accepted(client: &AuditClient) -> TestResult {
608 TestResult::new(
609 "pr_event_git_push_accepted",
610 SpecRef::PurgatoryAcceptUntilGitData,
611 "Git push for PR event SHOULD be accepted",
612 )
613 .run(|| async {
614 let ctx = TestContext::new(client);
615
616 let _pr_event = ctx
617 .get_fixture(FixtureKind::PREvent2GitDataPushed)
591 .await 618 .await
592 .map_err(|e| format!("Failed to send PR event: {}", e))?; 619 .map_err(|e| format!("Failed to push git data for PR event: {}", e))?;
593 620
594 // TODO: Push git data to refs/nostr/<pr-event-id> 621 Ok(())
595 // This requires git operations similar to OwnerStateDataPushed 622 })
623 .await
624 }
625
626 /// Test: PR event served after git push
627 ///
628 /// Verifies the full purgatory release mechanism.
629 pub async fn test_pr_event_served_after_git_push(client: &AuditClient) -> TestResult {
630 TestResult::new(
631 "pr_event_served_after_git_push",
632 SpecRef::PurgatoryAcceptUntilGitData,
633 "PR event SHOULD be served after matching git data arrives",
634 )
635 .run(|| async {
636 let ctx = TestContext::new(client);
637
638 let pr_event = ctx
639 .get_fixture(FixtureKind::PREvent2Served)
640 .await
641 .map_err(|e| format!("Failed to complete purgatory release: {}", e))?;
596 642
597 // For now, verify the PR event exists
598 let filter = Filter::new() 643 let filter = Filter::new()
599 .kind(Kind::GitPullRequest) 644 .kind(Kind::GitPullRequest)
600 .author(client.pr_author_keys().public_key()) 645 .author(client.pr_author_keys().public_key())
@@ -607,8 +652,7 @@ impl PurgatoryTests {
607 652
608 if events.is_empty() { 653 if events.is_empty() {
609 return Err(format!( 654 return Err(format!(
610 "PR event not served after git push - purgatory release not implemented. \ 655 "PR event not served after git push. Event ID: {} should be queryable",
611 Event ID: {} should be queryable after git data arrives",
612 pr_event.id 656 pr_event.id
613 )); 657 ));
614 } 658 }