upleb.uk

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

summaryrefslogtreecommitdiff
path: root/tests/purgatory_sync.rs
blob: 1065c9d56ebf9bc334dbf9cf0dd5986695eedc1c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
//! Purgatory Sync Integration Tests
//!
//! Tests that verify purgatory sync behavior:
//! - Events entering purgatory are released when git data arrives
//! - Git push triggers unified processing
//! - Remote sync fetches git data and releases events
//!
//! # Test Strategy
//!
//! These tests verify the end-to-end purgatory flow:
//! 1. State/PR events go to purgatory when git data is missing
//! 2. Git push triggers `process_newly_available_git_data`
//! 3. Events are released from purgatory when git data becomes available
//!
//! # Running Tests
//!
//! ```bash
//! # Run all purgatory sync tests
//! cargo test --test purgatory_sync
//!
//! # Run specific test
//! cargo test --test purgatory_sync test_push_triggers_unified_processing
//!
//! # With output for debugging
//! cargo test --test purgatory_sync -- --nocapture
//! ```

mod common;

use common::{
    create_repo_announcement, create_state_event, create_test_repo_with_commit, push_to_relay,
    verify_event_not_served, wait_for_event_served, CommitVariant, TestRelay,
};
use nostr_sdk::prelude::*;
use std::time::Duration;

/// Test that a git push triggers `process_newly_available_git_data` and
/// releases state events from purgatory.
///
/// Scenario:
/// 1. Start relay
/// 2. Create and send repository announcement
/// 3. Create and send state event (goes to purgatory - no git data yet)
/// 4. Verify event is NOT served (in purgatory)
/// 5. Git push the required commit
/// 6. Verify event IS now served (released from purgatory)
#[tokio::test]
async fn test_push_triggers_unified_processing() {
    // 1. Start relay
    let relay = TestRelay::start().await;
    let keys = Keys::generate();
    let identifier = "push-test-repo";

    // 2. Create test repository locally with deterministic commit
    let temp_dir = tempfile::tempdir().expect("Failed to create temp dir");
    let commit_hash =
        create_test_repo_with_commit(temp_dir.path(), CommitVariant::StateTest)
            .expect("Failed to create test repo");

    // 3. Create and send announcement
    let announcement = create_repo_announcement(&keys, &[&relay.domain()], identifier);

    let client = Client::new(keys.clone());
    client
        .add_relay(relay.url())
        .await
        .expect("Failed to add relay");
    client.connect().await;

    // Wait for connection to be established
    tokio::time::sleep(Duration::from_millis(500)).await;

    // Send announcement
    client
        .send_event(&announcement)
        .await
        .expect("Failed to send announcement");

    // Small delay to ensure announcement is processed
    tokio::time::sleep(Duration::from_millis(200)).await;

    // 4. Create and send state event referencing the commit
    // The state event has refs that point to commits we haven't pushed yet
    let npub = keys.public_key().to_bech32().expect("Failed to get npub");
    let clone_url = format!("http://{}/{}/{}.git", relay.domain(), npub, identifier);

    let state_event = create_state_event(
        &keys,
        identifier,
        &[("main", &commit_hash)],
        &[],
        &[&clone_url],
        &[relay.url()],
    )
    .expect("Failed to create state event");

    let state_event_id = state_event.id;
    client
        .send_event(&state_event)
        .await
        .expect("Failed to send state event");

    // 5. Verify event is NOT served yet (in purgatory)
    // Give a moment for the event to be processed into purgatory
    tokio::time::sleep(Duration::from_millis(200)).await;

    verify_event_not_served(relay.url(), &state_event_id, Duration::from_secs(1))
        .await
        .expect("State event should NOT be served before git push (should be in purgatory)");

    // 6. Git push to relay (this should trigger process_newly_available_git_data)
    push_to_relay(temp_dir.path(), &relay.domain(), &npub, identifier)
        .expect("Git push should succeed");

    // 7. Verify event IS now served (released from purgatory)
    let found_event = wait_for_event_served(relay.url(), &state_event_id, Duration::from_secs(5))
        .await
        .expect("State event should be served after git push");

    // Verify it's the same event
    assert_eq!(found_event.id, state_event_id);

    // Cleanup
    client.disconnect().await;
    relay.stop().await;
}