diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2026-02-13 09:24:51 +0000 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2026-02-13 09:24:51 +0000 |
| commit | f4e8e1089ae6e8e78c3576246d9747bb585fdc18 (patch) | |
| tree | 37cd429b6c5468996178f1d9bbaafe6f789b3605 /grasp-audit/src/specs | |
| parent | faac6027deaf5f1e121c05df2d8a6336fd6eaf8d (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')
| -rw-r--r-- | grasp-audit/src/specs/grasp01/purgatory.rs | 144 |
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 | } |