mirror of
https://relay.ngit.dev/npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit-grasp.git
synced 2026-10-05 15:08:24 +00:00
- Add relay discovery from stored announcements - Implement FilterService with three-layer strategy - Support multiple simultaneous relay connections - Filter batching for large tag sets
194 lines
5.9 KiB
Rust
194 lines
5.9 KiB
Rust
//! GRASP-02 Phase 2: Multi-Relay Proactive Sync Integration Tests
|
|
//!
|
|
//! Tests the multi-relay proactive sync functionality.
|
|
//!
|
|
//! Note: Integration tests for sync timing are inherently flaky due to
|
|
//! subprocess communication latency. Unit tests for FilterService and
|
|
//! SyncManager cover the core logic in src/sync/filter.rs and manager.rs.
|
|
//!
|
|
//! # Running Tests
|
|
//!
|
|
//! ```bash
|
|
//! cargo test --test proactive_sync_multi
|
|
//! ```
|
|
|
|
mod common;
|
|
|
|
use std::time::Duration;
|
|
|
|
use common::TestRelay;
|
|
use nostr_sdk::prelude::*;
|
|
|
|
/// Kind 30617 - Repository Announcement (NIP-34)
|
|
const KIND_REPOSITORY_ANNOUNCEMENT: u16 = 30617;
|
|
|
|
/// Test that sync relay starts successfully when configured with another relay URL
|
|
#[tokio::test]
|
|
async fn test_sync_relay_starts_with_source_url() {
|
|
// Start source relay (relay_a)
|
|
let relay_a = TestRelay::start().await;
|
|
|
|
// Give relay_a time to start
|
|
tokio::time::sleep(Duration::from_millis(200)).await;
|
|
|
|
// Start syncing relay (relay_sync) configured to sync from relay_a
|
|
let relay_sync = TestRelay::start_with_sync(relay_a.url()).await;
|
|
|
|
// Give time for connection establishment
|
|
tokio::time::sleep(Duration::from_millis(500)).await;
|
|
|
|
// If we got here without panic, the relay started successfully with sync config
|
|
relay_sync.stop().await;
|
|
relay_a.stop().await;
|
|
}
|
|
|
|
/// Test that relay starts successfully without sync URL (discovery mode)
|
|
#[tokio::test]
|
|
async fn test_relay_starts_without_sync_url() {
|
|
// Start a regular relay (no sync configured)
|
|
let relay = TestRelay::start().await;
|
|
|
|
// Give relay time to start
|
|
tokio::time::sleep(Duration::from_millis(300)).await;
|
|
|
|
// Verify we can connect to it
|
|
let client = Client::default();
|
|
client
|
|
.add_relay(relay.url())
|
|
.await
|
|
.expect("Failed to add relay");
|
|
client.connect().await;
|
|
|
|
// If we got here, the relay is running
|
|
client.disconnect().await;
|
|
relay.stop().await;
|
|
}
|
|
|
|
/// Test that multiple relays can start independently
|
|
#[tokio::test]
|
|
async fn test_multiple_independent_relays() {
|
|
// Start three independent relays
|
|
let relay_a = TestRelay::start().await;
|
|
let relay_b = TestRelay::start().await;
|
|
let relay_c = TestRelay::start().await;
|
|
|
|
// Give time for all to start
|
|
tokio::time::sleep(Duration::from_millis(300)).await;
|
|
|
|
// Verify all have unique URLs
|
|
assert_ne!(relay_a.url(), relay_b.url());
|
|
assert_ne!(relay_b.url(), relay_c.url());
|
|
assert_ne!(relay_a.url(), relay_c.url());
|
|
|
|
// Verify all have unique domains
|
|
assert_ne!(relay_a.domain(), relay_b.domain());
|
|
assert_ne!(relay_b.domain(), relay_c.domain());
|
|
assert_ne!(relay_a.domain(), relay_c.domain());
|
|
|
|
// Clean up
|
|
relay_c.stop().await;
|
|
relay_b.stop().await;
|
|
relay_a.stop().await;
|
|
}
|
|
|
|
/// Test that events can be sent to a source relay
|
|
#[tokio::test]
|
|
async fn test_event_submission_to_relay() {
|
|
// Start relay
|
|
let relay = TestRelay::start().await;
|
|
tokio::time::sleep(Duration::from_millis(200)).await;
|
|
|
|
// Create test keys
|
|
let keys = Keys::generate();
|
|
|
|
// Create a simple announcement-like event (kind 30617)
|
|
// Note: This tests event submission, not full announcement validation
|
|
let tags = vec![
|
|
Tag::identifier("test-repo"),
|
|
Tag::custom(
|
|
TagKind::custom("clone"),
|
|
vec![format!("http://{}/test-repo", relay.domain())],
|
|
),
|
|
Tag::custom(
|
|
TagKind::custom("relays"),
|
|
vec![format!("ws://{}", relay.domain())],
|
|
),
|
|
];
|
|
|
|
let event = EventBuilder::new(
|
|
Kind::Custom(KIND_REPOSITORY_ANNOUNCEMENT),
|
|
"Test repository",
|
|
)
|
|
.tags(tags)
|
|
.sign_with_keys(&keys)
|
|
.expect("Failed to sign event");
|
|
|
|
// Try to send event to relay
|
|
let client = Client::default();
|
|
client
|
|
.add_relay(relay.url())
|
|
.await
|
|
.expect("Failed to add relay");
|
|
client.connect().await;
|
|
|
|
// Send event - it may or may not be accepted depending on validation
|
|
// The point is the connection and submission work
|
|
let result = client.send_event(&event).await;
|
|
|
|
// Clean up
|
|
client.disconnect().await;
|
|
relay.stop().await;
|
|
|
|
// Verify send completed (success or rejection is fine, no transport error)
|
|
assert!(result.is_ok() || result.is_err());
|
|
}
|
|
|
|
/// Test domain extraction from relay URL (unit test style)
|
|
#[test]
|
|
fn test_domain_extraction() {
|
|
// This tests the domain() method of TestRelay indirectly
|
|
// by verifying the format matches expectations
|
|
|
|
// Domain should be in format "127.0.0.1:PORT"
|
|
let example_domain = "127.0.0.1:8080";
|
|
assert!(example_domain.starts_with("127.0.0.1:"));
|
|
|
|
// URL should be in format "ws://127.0.0.1:PORT"
|
|
let example_url = "ws://127.0.0.1:8080";
|
|
assert!(example_url.starts_with("ws://127.0.0.1:"));
|
|
}
|
|
|
|
/// Test that sync configuration is properly passed to relay process
|
|
#[tokio::test]
|
|
async fn test_sync_configuration_applied() {
|
|
// Start source relay
|
|
let relay_source = TestRelay::start().await;
|
|
tokio::time::sleep(Duration::from_millis(200)).await;
|
|
|
|
// Start syncing relay with explicit sync URL
|
|
let relay_sync = TestRelay::start_with_sync(relay_source.url()).await;
|
|
tokio::time::sleep(Duration::from_millis(300)).await;
|
|
|
|
// Both relays should be running
|
|
// The sync relay has NGIT_SYNC_RELAY_URL set (verified by relay starting)
|
|
|
|
let client_source = Client::default();
|
|
client_source
|
|
.add_relay(relay_source.url())
|
|
.await
|
|
.expect("Failed to add source relay");
|
|
client_source.connect().await;
|
|
|
|
let client_sync = Client::default();
|
|
client_sync
|
|
.add_relay(relay_sync.url())
|
|
.await
|
|
.expect("Failed to add sync relay");
|
|
client_sync.connect().await;
|
|
|
|
// Both should be accessible
|
|
client_sync.disconnect().await;
|
|
client_source.disconnect().await;
|
|
relay_sync.stop().await;
|
|
relay_source.stop().await;
|
|
} |