From 7a81643367515a9d01eb2d4deb623e9a7c071a12 Mon Sep 17 00:00:00 2001 From: DanConwayDev Date: Fri, 21 Nov 2025 05:18:15 +0000 Subject: add repository creation --- tests/common/relay.rs | 37 +++++++++++++++++++++++-- tests/repository_creation.rs | 64 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 2 deletions(-) create mode 100644 tests/repository_creation.rs (limited to 'tests') diff --git a/tests/common/relay.rs b/tests/common/relay.rs index 7185acd..6b512cd 100644 --- a/tests/common/relay.rs +++ b/tests/common/relay.rs @@ -2,6 +2,8 @@ //! //! Provides automatic relay lifecycle management for integration tests. +use nostr_sdk::ToBech32; +use std::path::PathBuf; use std::process::{Child, Command, Stdio}; use std::time::Duration; use tokio::time::sleep; @@ -9,11 +11,12 @@ use tokio::time::sleep; /// Test relay fixture that manages relay lifecycle /// /// Automatically starts and stops the ngit-grasp relay for testing. -/// Uses a random port to avoid conflicts. +/// Uses a random port to avoid conflicts and cleans up created repositories. pub struct TestRelay { process: Child, url: String, port: u16, + git_data_dir: tempfile::TempDir, } impl TestRelay { @@ -40,6 +43,10 @@ impl TestRelay { let bind_address = format!("127.0.0.1:{}", port); let url = format!("ws://127.0.0.1:{}", port); + // Create temporary directory for git repositories + let git_data_dir = tempfile::tempdir() + .expect("Failed to create temporary git data directory"); + // Use the built binary directly (faster than cargo run) let binary_path = std::env::current_exe() .expect("Failed to get current exe") @@ -49,17 +56,29 @@ impl TestRelay { .expect("Failed to get grandparent dir") .join("ngit-grasp"); + // Generate a test owner npub (using a random keypair) + let test_keys = nostr_sdk::Keys::generate(); + let test_npub = test_keys.public_key().to_bech32() + .expect("Failed to generate test npub"); + // Start the relay process let process = Command::new(&binary_path) .env("NGIT_BIND_ADDRESS", &bind_address) .env("NGIT_DOMAIN", &bind_address) // Set domain to match bind address + .env("NGIT_GIT_DATA_PATH", git_data_dir.path()) + .env("NGIT_OWNER_NPUB", &test_npub) .env("RUST_LOG", "warn") // Less logging during tests .stdout(Stdio::null()) .stderr(Stdio::null()) .spawn() .expect("Failed to start relay process"); - let relay = Self { process, url, port }; + let relay = Self { + process, + url, + port, + git_data_dir, + }; // Wait for relay to be ready relay.wait_for_ready().await; @@ -82,6 +101,20 @@ impl TestRelay { format!("127.0.0.1:{}", self.port) } + /// Get the git data directory path + pub fn git_data_dir(&self) -> &std::path::Path { + self.git_data_dir.path() + } + + /// Get the expected repository path for a given npub and repo identifier + /// + /// Repositories are stored at: //.git + pub fn repo_path(&self, npub: &str, identifier: &str) -> PathBuf { + self.git_data_dir.path() + .join(npub) + .join(format!("{}.git", identifier)) + } + /// Wait for the relay to be ready to accept connections async fn wait_for_ready(&self) { let max_attempts = 50; // 5 seconds total diff --git a/tests/repository_creation.rs b/tests/repository_creation.rs new file mode 100644 index 0000000..f57899d --- /dev/null +++ b/tests/repository_creation.rs @@ -0,0 +1,64 @@ +//! Repository Creation Integration Tests +//! +//! Tests that verify bare Git repositories are created when repository announcements +//! are accepted by ngit-grasp relay. +//! +//! # Test Strategy +//! +//! - Each test runs in complete isolation with its own fresh relay instance +//! - Uses macro to eliminate boilerplate while maintaining test isolation +//! - Calls individual test methods from grasp-audit for minimal duplication +//! - Automatic cleanup via TestRelay fixture (removes container and temp dirs) +//! +//! # Running Tests +//! +//! ```bash +//! # Run all repository creation tests +//! cargo test --test repository_creation +//! +//! # Run specific test +//! cargo test --test repository_creation test_bare_repo_created_on_announcement +//! +//! # With output +//! cargo test --test repository_creation -- --nocapture +//! ``` + +mod common; + +use common::TestRelay; +use grasp_audit::*; +use grasp_audit::specs::grasp01::RepositoryCreationTests; + +/// Macro to generate isolated integration tests +/// +/// Each test runs with its own fresh relay instance to ensure complete isolation. +/// This eliminates issues with leftover repositories and ensures clean state. +macro_rules! isolated_test { + ($test_name:ident) => { + #[tokio::test] + async fn $test_name() { + let relay = TestRelay::start().await; + let config = AuditConfig::ci(); + let client = AuditClient::new(relay.url(), config) + .await + .expect("Failed to create audit client"); + + let result = RepositoryCreationTests::$test_name(&client, relay.git_data_dir()).await; + + relay.stop().await; + + assert!( + result.passed, + "{} failed: {}", + stringify!($test_name), + result.error.as_deref().unwrap_or("unknown error") + ); + } + }; +} + +// Generate isolated tests for all repository creation tests +isolated_test!(test_bare_repo_created_on_announcement); +isolated_test!(test_repo_creation_idempotent); +isolated_test!(test_bare_repo_structure); +isolated_test!(test_repo_cleanup); \ No newline at end of file -- cgit v1.2.3