diff --git a/docs/how-to/test-fixtures.md b/docs/how-to/test-fixtures.md index 1f693d3..adec5f8 100644 --- a/docs/how-to/test-fixtures.md +++ b/docs/how-to/test-fixtures.md @@ -27,6 +27,24 @@ Connection tasks belong to their fixture's accept loop. Stopping the fixture cancels and joins them; dropping it cancels the owner. Git fixture subprocesses are cancelled with their request, and all three pipes are driven concurrently. +## Shared repository identity + +`setup_announcement_on_relay` returns an announcement and a `RepositoryFixture`. +Prepare it once for each logical repository, then call `fixture.install(&relay)` +for every other relay. It reuses the signed announcement, signed state event, +and Git commit. Repeating setup independently can create competing replaceable +events at the same owner/identifier and different Git histories. + +List all participating domains when preparing the fixture. If historic tests +must seed a source before starting the syncing relay, reserve the target's +listener first and transfer it into the target after seeding. Do not use sleeps +or fabricated future timestamps to order copies of the same fixture. Tests of +actual repository revisions should construct those revisions explicitly. + +The sync regression `reinstalling_shared_repository_preserves_event_ids_and_git_refs` +checks exact announcement/state IDs and remote Git refs across installation and +reinstallation on two relays. + ## Time and streaming assertions Age private cache timestamps explicitly and bracket wall-clock timestamps diff --git a/tests/common/sync_helpers.rs b/tests/common/sync_helpers.rs index f448f2c..55e4fb0 100644 --- a/tests/common/sync_helpers.rs +++ b/tests/common/sync_helpers.rs @@ -1351,100 +1351,121 @@ pub async fn push_unique_git_data_to_relay( git_temp_dir } -/// Set up a repository announcement on a relay with git data so it passes purgatory. +/// One repository's immutable Git data and signed events for all test relays. /// -/// With the announcement purgatory feature, announcements (kind 30617) require git -/// data before they are promoted to the relay's main DB. This helper: -/// -/// 1. Creates a local git repo with a commit -/// 2. Builds an announcement and state event (kind 30618) pointing to the relay -/// 3. Sends both to the relay (they go to purgatory) -/// 4. Git pushes to the relay → releases both from purgatory immediately -/// 5. Returns the announcement event and temp dir (keep alive for test duration) -/// -/// # Arguments -/// * `relay` - The relay to set up the announcement on -/// * `keys` - Keys to sign the announcement with (repo owner) -/// * `domains` - All domains that should be listed in the announcement (including relay.domain()) -/// * `identifier` - Repository identifier (d-tag) -/// -/// # Returns -/// `(Event, tempfile::TempDir)` - The announcement event and temp dir. -/// The temp dir MUST be kept alive for the duration of the test. +/// Preparing separate copies can mint competing replaceable events for the same +/// owner/identifier and different Git commits. Prepare once, list every endpoint +/// (reserve its listener first if necessary), and install this fixture on each +/// relay. Keep it alive until the test finishes. +pub struct RepositoryFixture { + git_dir: tempfile::TempDir, + announcement: Event, + state_event: Event, + keys: Keys, + identifier: String, +} + +impl RepositoryFixture { + pub fn new(keys: &Keys, domains: &[&str], identifier: &str) -> Self { + use super::purgatory_helpers::{ + create_state_event, create_test_repo_with_commit, CommitVariant, + }; + + let npub = keys + .public_key() + .to_bech32() + .expect("Failed to convert public key to npub"); + + // Create local git repo with a commit + let git_temp_dir = tempfile::tempdir().expect("Failed to create temp dir for git repo"); + let commit_hash = + create_test_repo_with_commit(git_temp_dir.path(), CommitVariant::StateTest) + .expect("Failed to create test git repo"); + + // Build clone URLs and relay URLs from domains + let clone_urls: Vec = domains + .iter() + .map(|d| format!("http://{}/{}/{}.git", d, npub, identifier)) + .collect(); + let relay_urls: Vec = domains.iter().map(|d| format!("ws://{}", d)).collect(); + + // Build announcement event (lists ALL domains for relay discovery) + let announcement = EventBuilder::new(Kind::GitRepoAnnouncement, "Repository state") + .tags(vec![ + Tag::identifier(identifier), + Tag::custom("clone", clone_urls.clone()), + Tag::custom("relays", relay_urls.clone()), + ]) + .finalize(keys) + .expect("Failed to sign repo announcement"); + + // Build state event with all domains' clone URLs + let state_event = create_state_event( + keys, + identifier, + &[("main", &commit_hash)], + &[], + &clone_urls.iter().map(|s| s.as_str()).collect::>(), + &relay_urls.iter().map(|s| s.as_str()).collect::>(), + ) + .expect("Failed to create state event"); + + Self { + git_dir: git_temp_dir, + announcement, + state_event, + keys: keys.clone(), + identifier: identifier.to_string(), + } + } + + pub fn path(&self) -> &std::path::Path { + self.git_dir.path() + } + + /// Publish the same events and push the same commit to another relay. + pub async fn install(&self, relay: &TestRelay) { + use super::purgatory_helpers::push_to_relay; + + send_to_relay(relay, &self.announcement) + .await + .expect("Failed to send announcement"); + send_to_relay(relay, &self.state_event) + .await + .expect("Failed to send state event"); + let npub = self.keys.public_key().to_bech32().expect("owner npub"); + push_to_relay(self.path(), &relay.domain(), &npub, &self.identifier) + .expect("Failed to push git data to relay"); + + for (label, event) in [ + ("state", &self.state_event), + ("announcement", &self.announcement), + ] { + let visible = wait_for_event_on_relay( + relay.url(), + Filter::new().id(event.id), + Duration::from_secs(10), + ) + .await; + if !visible { + report_setup_visibility_failure(relay, &self.keys, &self.identifier, event).await; + } + assert!(visible, "pushed {label} must leave purgatory"); + } + } +} + +/// Prepare and install a repository on its first relay. For another relay, +/// call `install` on the returned fixture instead of preparing a new copy. pub async fn setup_announcement_on_relay( relay: &TestRelay, keys: &Keys, domains: &[&str], identifier: &str, -) -> (Event, tempfile::TempDir) { - use super::purgatory_helpers::{ - create_state_event, create_test_repo_with_commit, push_to_relay, CommitVariant, - }; - - let npub = keys - .public_key() - .to_bech32() - .expect("Failed to convert public key to npub"); - - // Create local git repo with a commit - let git_temp_dir = tempfile::tempdir().expect("Failed to create temp dir for git repo"); - let commit_hash = create_test_repo_with_commit(git_temp_dir.path(), CommitVariant::StateTest) - .expect("Failed to create test git repo"); - - // Build clone URLs and relay URLs from domains - let clone_urls: Vec = domains - .iter() - .map(|d| format!("http://{}/{}/{}.git", d, npub, identifier)) - .collect(); - let relay_urls: Vec = domains.iter().map(|d| format!("ws://{}", d)).collect(); - - // Build announcement event (lists ALL domains for relay discovery) - let announcement = EventBuilder::new(Kind::GitRepoAnnouncement, "Repository state") - .tags(vec![ - Tag::identifier(identifier), - Tag::custom("clone", clone_urls.clone()), - Tag::custom("relays", relay_urls.clone()), - ]) - .finalize(keys) - .expect("Failed to sign repo announcement"); - - // Build state event with all domains' clone URLs - let state_event = create_state_event( - keys, - identifier, - &[("main", &commit_hash)], - &[], - &clone_urls.iter().map(|s| s.as_str()).collect::>(), - &relay_urls.iter().map(|s| s.as_str()).collect::>(), - ) - .expect("Failed to create state event"); - - // Send announcement and state event to relay (both go to purgatory) - send_to_relay(relay, &announcement) - .await - .expect("Failed to send announcement"); - send_to_relay(relay, &state_event) - .await - .expect("Failed to send state event"); - - // Git push to relay → releases both from purgatory - push_to_relay(git_temp_dir.path(), &relay.domain(), &npub, identifier) - .expect("Failed to push git data to relay"); - - for (label, event) in [("state", &state_event), ("announcement", &announcement)] { - let visible = wait_for_event_on_relay( - relay.url(), - Filter::new().id(event.id), - Duration::from_secs(10), - ) - .await; - if !visible { - report_setup_visibility_failure(relay, keys, identifier, event).await; - } - assert!(visible, "pushed {label} must leave purgatory"); - } - - (announcement, git_temp_dir) +) -> (Event, RepositoryFixture) { + let fixture = RepositoryFixture::new(keys, domains, identifier); + fixture.install(relay).await; + (fixture.announcement.clone(), fixture) } /// Diagnose a failed exact-ID check without extending its success deadline. diff --git a/tests/sync.rs b/tests/sync.rs index 9ce8a73..bd9b66d 100644 --- a/tests/sync.rs +++ b/tests/sync.rs @@ -46,6 +46,7 @@ mod sync { pub mod proactive_sync_plus; pub mod purgatory_fetch; pub mod reconnect_backoff; + pub mod repository_fixture; pub mod req_concurrency; pub mod stale_connect_result; pub mod tag_variations; diff --git a/tests/sync/descendant_sync.rs b/tests/sync/descendant_sync.rs index 672f55b..9a4d8ed 100644 --- a/tests/sync/descendant_sync.rs +++ b/tests/sync/descendant_sync.rs @@ -31,12 +31,14 @@ async fn historic_recursive_cap_is_enforced_and_reconstructed_after_restart() { let source = TestRelay::start_with_relay_max_subscriptions(4).await; let keys = Keys::generate(); let repo_id = "restart-safe-recursive-cap"; - let source_domains = [source.domain()]; + let syncing_reservation = reserve_port(); + let syncing_domain = format!("127.0.0.1:{}", syncing_reservation.port()); + let source_domains = [source.domain(), syncing_domain]; let source_refs = source_domains .iter() .map(String::as_str) .collect::>(); - let (_announcement, _source_git) = + let (_announcement, repository) = setup_announcement_on_relay(&source, &keys, &source_refs, repo_id).await; let source_client = TestClient::new(source.url(), keys.clone()) .await @@ -64,7 +66,7 @@ async fn historic_recursive_cap_is_enforced_and_reconstructed_after_restart() { let syncing_git_dir = tempfile::tempdir().expect("create syncing git dir"); let syncing_data_dir = tempfile::tempdir().expect("create syncing relay data dir"); let syncing = TestRelay::start_on_reservation_persistent_sync_with_recursive_limit( - reserve_port(), + syncing_reservation, None, true, syncing_git_dir.path().to_path_buf(), @@ -72,10 +74,7 @@ async fn historic_recursive_cap_is_enforced_and_reconstructed_after_restart() { LIMIT, ) .await; - let domains = [source.domain(), syncing.domain()]; - let domain_refs = domains.iter().map(String::as_str).collect::>(); - let (_target_announcement, _target_git) = - setup_announcement_on_relay(&syncing, &keys, &domain_refs, repo_id).await; + repository.install(&syncing).await; for descendant in [&first, &second] { assert!( @@ -154,12 +153,14 @@ async fn historic_sync_recovers_recursive_parent_only_descendants() { // Seed the source before the syncing relay exists so this exercises the // complete historic rotation, not ordinary live coverage. - let source_domains = [source.domain()]; + let syncing_reservation = reserve_port(); + let syncing_domain = format!("127.0.0.1:{}", syncing_reservation.port()); + let source_domains = [source.domain(), syncing_domain]; let source_refs = source_domains .iter() .map(String::as_str) .collect::>(); - let (_announcement, _source_git) = + let (_announcement, repository) = setup_announcement_on_relay(&source, &keys, &source_refs, repo_id).await; let source_client = TestClient::new(source.url(), keys.clone()) .await @@ -188,11 +189,9 @@ async fn historic_sync_recovers_recursive_parent_only_descendants() { .expect("seed source event"); } - let syncing = TestRelay::start_with_sync(None).await; - let domains = [source.domain(), syncing.domain()]; - let domain_refs = domains.iter().map(String::as_str).collect::>(); - let (_target_announcement, _target_git) = - setup_announcement_on_relay(&syncing, &keys, &domain_refs, repo_id).await; + let syncing = + TestRelay::start_on_reservation_with_options(syncing_reservation, None, false).await; + repository.install(&syncing).await; assert!( wait_for_event_on_relay( @@ -235,12 +234,14 @@ async fn descendant_live_coverage_is_preferred_when_capacity_remains() { let source = TestRelay::start().await; let keys = Keys::generate(); let repo_id = "live-descendant-coverage"; - let source_domains = [source.domain()]; + let syncing_reservation = reserve_port(); + let syncing_domain = format!("127.0.0.1:{}", syncing_reservation.port()); + let source_domains = [source.domain(), syncing_domain]; let source_refs = source_domains .iter() .map(String::as_str) .collect::>(); - let (_announcement, _source_git) = + let (_announcement, repository) = setup_announcement_on_relay(&source, &keys, &source_refs, repo_id).await; let source_client = TestClient::new(source.url(), keys.clone()) .await @@ -252,11 +253,9 @@ async fn descendant_live_coverage_is_preferred_when_capacity_remains() { source_client.send_event(&issue).await.unwrap(); source_client.send_event(&direct_reply).await.unwrap(); - let syncing = TestRelay::start_with_sync(None).await; - let domains = [source.domain(), syncing.domain()]; - let domain_refs = domains.iter().map(String::as_str).collect::>(); - let (_target_announcement, _target_git) = - setup_announcement_on_relay(&syncing, &keys, &domain_refs, repo_id).await; + let syncing = + TestRelay::start_on_reservation_with_options(syncing_reservation, None, false).await; + repository.install(&syncing).await; assert!( wait_for_log( &syncing.log_path(), @@ -295,12 +294,14 @@ async fn historic_sync_recovers_address_tag_descendants() { let source = TestRelay::start_with_relay_max_subscriptions(4).await; let keys = Keys::generate(); let repo_id = "addressable-descendant-history"; - let source_domains = [source.domain()]; + let syncing_reservation = reserve_port(); + let syncing_domain = format!("127.0.0.1:{}", syncing_reservation.port()); + let source_domains = [source.domain(), syncing_domain]; let source_refs = source_domains .iter() .map(String::as_str) .collect::>(); - let (_announcement, _source_git) = + let (_announcement, repository) = setup_announcement_on_relay(&source, &keys, &source_refs, repo_id).await; let source_client = TestClient::new(source.url(), keys.clone()) .await @@ -334,11 +335,9 @@ async fn historic_sync_recovers_address_tag_descendants() { source_client.send_event(event).await.unwrap(); } - let syncing = TestRelay::start_with_sync(None).await; - let domains = [source.domain(), syncing.domain()]; - let domain_refs = domains.iter().map(String::as_str).collect::>(); - let (_target_announcement, _target_git) = - setup_announcement_on_relay(&syncing, &keys, &domain_refs, repo_id).await; + let syncing = + TestRelay::start_on_reservation_with_options(syncing_reservation, None, false).await; + repository.install(&syncing).await; for event in &address_only_children { assert!( diff --git a/tests/sync/discovery.rs b/tests/sync/discovery.rs index 84f549a..ef9315c 100644 --- a/tests/sync/discovery.rs +++ b/tests/sync/discovery.rs @@ -61,7 +61,7 @@ async fn test_discovers_layer3_via_layer2() { let domains = [relay_a.domain(), relay_b.domain()]; let domain_refs: Vec<&str> = domains.iter().map(|s| s.as_str()).collect(); - let (announcement, _git_dir_a) = + let (announcement, repository) = setup_announcement_on_relay(&relay_a, &keys, &domain_refs, repo_id).await; let announcement_id = announcement.id; println!( @@ -102,8 +102,7 @@ async fn test_discovers_layer3_via_layer2() { client_a.disconnect().await; // 8. Set up announcement on relay_b (triggers discovery of relay_a) - let (_announcement_b, _git_dir_b) = - setup_announcement_on_relay(&relay_b, &keys, &domain_refs, repo_id).await; + repository.install(&relay_b).await; println!("Announcement set up on relay_b (should trigger discovery of relay_a)"); // 9/10. Verify the patch syncs to relay_b. The bounded poll on the synced @@ -176,7 +175,7 @@ async fn test_relay_discovery_via_announcements_with_historic_sync() { let domain_refs: Vec<&str> = domains.iter().map(|s| s.as_str()).collect(); let repo_id = "test-repo-chain"; - let (announcement, _git_dir_a) = + let (announcement, repository) = setup_announcement_on_relay(&relay_a, &keys, &domain_refs, repo_id).await; let announcement_id = announcement.id; println!( @@ -207,8 +206,7 @@ async fn test_relay_discovery_via_announcements_with_historic_sync() { client_a.disconnect().await; // 6. Set up announcement on relay_b (triggers discovery of relay_a) - let (_announcement_b, _git_dir_b) = - setup_announcement_on_relay(&relay_b, &keys, &domain_refs, repo_id).await; + repository.install(&relay_b).await; println!("Announcement set up on relay_b (should trigger discovery of relay_a)"); // 7/8. Verify the Layer 2 event syncs to relay_b. The bounded poll on the diff --git a/tests/sync/live_sync.rs b/tests/sync/live_sync.rs index 4961b6c..fb9f1bd 100644 --- a/tests/sync/live_sync.rs +++ b/tests/sync/live_sync.rs @@ -299,12 +299,11 @@ async fn test_live_sync_layer2_events() { let domains = [relay_a.domain(), relay_b.domain()]; let domain_refs: Vec<&str> = domains.iter().map(|s| s.as_str()).collect(); - let (_announcement, _git_dir_a) = + let (_announcement, repository) = setup_announcement_on_relay(&relay_a, &keys, &domain_refs, repo_id).await; println!("Announcement set up on relay_a with git data"); - let (_announcement_b, _git_dir_b) = - setup_announcement_on_relay(&relay_b, &keys, &domain_refs, repo_id).await; + repository.install(&relay_b).await; println!("Announcement set up on relay_b with git data (triggers discovery)"); // 5. Wait for discovery: events published before the syncing relay has @@ -397,12 +396,11 @@ async fn test_live_sync_layer3_events() { let domains = [relay_a.domain(), relay_b.domain()]; let domain_refs: Vec<&str> = domains.iter().map(|s| s.as_str()).collect(); - let (_announcement, _git_dir_a) = + let (_announcement, repository) = setup_announcement_on_relay(&relay_a, &keys, &domain_refs, repo_id).await; println!("Announcement set up on relay_a with git data"); - let (_announcement_b, _git_dir_b) = - setup_announcement_on_relay(&relay_b, &keys, &domain_refs, repo_id).await; + repository.install(&relay_b).await; println!("Announcement set up on relay_b with git data (triggers discovery)"); // 3. Wait for discovery: events published before the syncing relay has @@ -573,10 +571,9 @@ async fn test_live_sync_event_ordering() { let domains = [relay_a.domain(), relay_b.domain()]; let domain_refs: Vec<&str> = domains.iter().map(|s| s.as_str()).collect(); - let (_announcement, _git_dir_a) = + let (_announcement, repository) = setup_announcement_on_relay(&relay_a, &keys, &domain_refs, repo_id).await; - let (_announcement_b, _git_dir_b) = - setup_announcement_on_relay(&relay_b, &keys, &domain_refs, repo_id).await; + repository.install(&relay_b).await; println!("Announcements set up on both relays with git data"); // 3. Wait for discovery: events published before the syncing relay has diff --git a/tests/sync/metrics.rs b/tests/sync/metrics.rs index 5bfe3d5..9ba34a8 100644 --- a/tests/sync/metrics.rs +++ b/tests/sync/metrics.rs @@ -243,7 +243,7 @@ async fn test_startup_sync_event_count() { let domains = [source_relay.domain(), syncing_relay.domain()]; let domain_refs: Vec<&str> = domains.iter().map(|s| s.as_str()).collect(); - let (announcement, _git_dir_source) = + let (announcement, repository) = setup_announcement_on_relay(&source_relay, &keys, &domain_refs, repo_id).await; println!( "Announcement {} set up on source relay with git data", @@ -286,8 +286,7 @@ async fn test_startup_sync_event_count() { source_client.disconnect().await; // 8. Set up announcement on SYNCING relay (triggers discovery of source relay) - let (_announcement_syncing, _git_dir_syncing) = - setup_announcement_on_relay(&syncing_relay, &keys, &domain_refs, repo_id).await; + repository.install(&syncing_relay).await; println!("Announcement set up on syncing relay (triggers discovery of source)"); // 9. Wait for discovery + sync on the observable condition the test diff --git a/tests/sync/repository_fixture.rs b/tests/sync/repository_fixture.rs new file mode 100644 index 0000000..1d71d04 --- /dev/null +++ b/tests/sync/repository_fixture.rs @@ -0,0 +1,104 @@ +//! Reusing a repository fixture must not mint replaceable event revisions. +use std::{collections::BTreeSet, time::Duration}; + +use nostr_sdk::prelude::*; + +use crate::common::{reserve_port, setup_announcement_on_relay, TestRelay}; + +async fn repository_event_ids( + relay: &TestRelay, + keys: &Keys, + identifier: &str, +) -> BTreeSet { + let client = Client::builder() + .authenticator(SignerAuthenticator::new(keys.clone())) + .build(); + client.add_relay(relay.url()).await.unwrap(); + client + .try_connect_relay(relay.url(), Duration::from_secs(5)) + .await + .expect("connect to installed repository"); + let events = client + .fetch_events( + Filter::new() + .author(keys.public_key()) + .identifier(identifier) + .kinds([Kind::GitRepoAnnouncement, Kind::RepoState]), + ) + .timeout(Duration::from_secs(5)) + .await + .expect("fetch installed repository events"); + client.disconnect().await; + events.iter().map(|event| event.id).collect() +} + +async fn remote_head(relay: &TestRelay, keys: &Keys, identifier: &str) -> String { + let url = format!( + "http://{}/{}/{}.git", + relay.domain(), + keys.public_key().to_bech32().unwrap(), + identifier + ); + let output = tokio::process::Command::from(grasp_audit::git_command()) + .args(["ls-remote", &url, "refs/heads/main"]) + .kill_on_drop(true) + .output() + .await + .expect("query repository ref"); + assert!(output.status.success()); + String::from_utf8(output.stdout) + .unwrap() + .split_whitespace() + .next() + .expect("main ref exists") + .to_string() +} + +#[tokio::test] +async fn reinstalling_shared_repository_preserves_event_ids_and_git_refs() { + tokio::time::timeout(Duration::from_secs(120), async { + let source = TestRelay::start().await; + let target_reservation = reserve_port(); + let target_domain = format!("127.0.0.1:{}", target_reservation.port()); + let domains = [source.domain(), target_domain]; + let refs = domains.iter().map(String::as_str).collect::>(); + let keys = Keys::generate(); + let identifier = "shared-fixture-identity"; + let (announcement, repository) = + setup_announcement_on_relay(&source, &keys, &refs, identifier).await; + let original_ids = repository_event_ids(&source, &keys, identifier).await; + assert_eq!( + original_ids.len(), + 2, + "announcement and state must both exist" + ); + assert!(original_ids.contains(&announcement.id)); + let original_head = remote_head(&source, &keys, identifier).await; + + // Start the peer only after seeding the source, matching historic sync. + let target = + TestRelay::start_on_reservation_with_options(target_reservation, None, false).await; + repository.install(&target).await; + assert_eq!( + repository_event_ids(&target, &keys, identifier).await, + original_ids + ); + assert_eq!(remote_head(&target, &keys, identifier).await, original_head); + + // Reinstall after sync has seen the same address. There must be no new + // event IDs, timestamps or competing Git state in either direction. + repository.install(&source).await; + repository.install(&target).await; + for relay in [&source, &target] { + assert_eq!( + repository_event_ids(relay, &keys, identifier).await, + original_ids + ); + assert_eq!(remote_head(relay, &keys, identifier).await, original_head); + } + target.stop().await; + source.stop().await; + }) + .await + .expect("shared repository setup and reinstalls must complete"); +} diff --git a/tests/sync/tag_variations.rs b/tests/sync/tag_variations.rs index 5fb764d..1e43ac5 100644 --- a/tests/sync/tag_variations.rs +++ b/tests/sync/tag_variations.rs @@ -61,12 +61,11 @@ async fn test_layer2_sync_with_lowercase_a_tag() { let domains = [relay_a.domain(), relay_b.domain()]; let domain_refs: Vec<&str> = domains.iter().map(|s| s.as_str()).collect(); - let (_announcement, _git_dir_a) = + let (_announcement, repository) = setup_announcement_on_relay(&relay_a, &keys, &domain_refs, repo_id).await; println!("Announcement set up on relay_a with git data"); - let (_announcement_b, _git_dir_b) = - setup_announcement_on_relay(&relay_b, &keys, &domain_refs, repo_id).await; + repository.install(&relay_b).await; println!("Announcement set up on relay_b with git data (triggers discovery)"); // 3. Wait for discovery: events published before the syncing relay has @@ -152,12 +151,11 @@ async fn test_layer2_sync_with_uppercase_a_tag() { let domains = [relay_a.domain(), relay_b.domain()]; let domain_refs: Vec<&str> = domains.iter().map(|s| s.as_str()).collect(); - let (_announcement, _git_dir_a) = + let (_announcement, repository) = setup_announcement_on_relay(&relay_a, &keys, &domain_refs, repo_id).await; println!("Announcement set up on relay_a with git data"); - let (_announcement_b, _git_dir_b) = - setup_announcement_on_relay(&relay_b, &keys, &domain_refs, repo_id).await; + repository.install(&relay_b).await; println!("Announcement set up on relay_b with git data (triggers discovery)"); // 3. Wait for discovery: events published before the syncing relay has @@ -245,12 +243,11 @@ async fn test_layer2_sync_with_q_tag() { let domains = [relay_a.domain(), relay_b.domain()]; let domain_refs: Vec<&str> = domains.iter().map(|s| s.as_str()).collect(); - let (_announcement, _git_dir_a) = + let (_announcement, repository) = setup_announcement_on_relay(&relay_a, &keys, &domain_refs, repo_id).await; println!("Announcement set up on relay_a with git data"); - let (_announcement_b, _git_dir_b) = - setup_announcement_on_relay(&relay_b, &keys, &domain_refs, repo_id).await; + repository.install(&relay_b).await; println!("Announcement set up on relay_b with git data (triggers discovery)"); // 3. Wait for discovery: events published before the syncing relay has @@ -344,12 +341,11 @@ async fn test_layer3_sync_with_lowercase_e_tag() { let domains = [relay_a.domain(), relay_b.domain()]; let domain_refs: Vec<&str> = domains.iter().map(|s| s.as_str()).collect(); - let (_announcement, _git_dir_a) = + let (_announcement, repository) = setup_announcement_on_relay(&relay_a, &keys, &domain_refs, repo_id).await; println!("Announcement set up on relay_a with git data"); - let (_announcement_b, _git_dir_b) = - setup_announcement_on_relay(&relay_b, &keys, &domain_refs, repo_id).await; + repository.install(&relay_b).await; println!("Announcement set up on relay_b with git data (triggers discovery)"); // 3. Wait for discovery: events published before the syncing relay has @@ -460,12 +456,11 @@ async fn test_layer3_sync_with_uppercase_e_tag() { let domains = [relay_a.domain(), relay_b.domain()]; let domain_refs: Vec<&str> = domains.iter().map(|s| s.as_str()).collect(); - let (_announcement, _git_dir_a) = + let (_announcement, repository) = setup_announcement_on_relay(&relay_a, &keys, &domain_refs, repo_id).await; println!("Announcement set up on relay_a with git data"); - let (_announcement_b, _git_dir_b) = - setup_announcement_on_relay(&relay_b, &keys, &domain_refs, repo_id).await; + repository.install(&relay_b).await; println!("Announcement set up on relay_b with git data (triggers discovery)"); // 3. Wait for discovery: events published before the syncing relay has @@ -580,12 +575,11 @@ async fn test_layer3_sync_with_q_tag() { let domains = [relay_a.domain(), relay_b.domain()]; let domain_refs: Vec<&str> = domains.iter().map(|s| s.as_str()).collect(); - let (_announcement, _git_dir_a) = + let (_announcement, repository) = setup_announcement_on_relay(&relay_a, &keys, &domain_refs, repo_id).await; println!("Announcement set up on relay_a with git data"); - let (_announcement_b, _git_dir_b) = - setup_announcement_on_relay(&relay_b, &keys, &domain_refs, repo_id).await; + repository.install(&relay_b).await; println!("Announcement set up on relay_b with git data (triggers discovery)"); // 3. Wait for discovery: events published before the syncing relay has