test: use fixtures in push tests

This commit is contained in:
DanConwayDev
2025-11-26 17:16:24 +00:00
parent 158d3f0722
commit 734d255efa
7 changed files with 874 additions and 1231 deletions
+85 -62
View File
@@ -10,6 +10,10 @@ pub struct AuditClient {
client: Client,
pub config: AuditConfig,
keys: Keys,
/// Maintainer keys for testing push authorization scenarios
maintainer_keys: Keys,
/// Recursive maintainer keys for testing recursive authorization scenarios
recursive_maintainer_keys: Keys,
}
impl AuditClient {
@@ -17,17 +21,23 @@ impl AuditClient {
#[cfg(test)]
pub fn new_test(config: AuditConfig) -> Self {
let keys = Keys::generate();
let maintainer_keys = Keys::generate();
let recursive_maintainer_keys = Keys::generate();
let client = Client::new(keys.clone());
Self {
client,
config,
keys,
maintainer_keys,
recursive_maintainer_keys,
}
}
/// Create a new audit client
pub async fn new(relay_url: &str, config: AuditConfig) -> Result<Self> {
let keys = Keys::generate();
let maintainer_keys = Keys::generate();
let recursive_maintainer_keys = Keys::generate();
let client = Client::new(keys.clone());
// Add relay and connect
@@ -76,6 +86,8 @@ impl AuditClient {
client,
config,
keys,
maintainer_keys,
recursive_maintainer_keys,
})
}
@@ -222,17 +234,45 @@ impl AuditClient {
&self.keys
}
/// Create a NIP-34 repository announcement event
/// Get the maintainer keys (for push authorization testing)
pub fn maintainer_keys(&self) -> &Keys {
&self.maintainer_keys
}
/// Get the maintainer public key as a hex string
pub fn maintainer_pubkey_hex(&self) -> String {
self.maintainer_keys.public_key().to_hex()
}
/// Get the recursive maintainer keys (for recursive authorization testing)
pub fn recursive_maintainer_keys(&self) -> &Keys {
&self.recursive_maintainer_keys
}
/// Get the recursive maintainer public key as a hex string
pub fn recursive_maintainer_pubkey_hex(&self) -> String {
self.recursive_maintainer_keys.public_key().to_hex()
}
/// Create a NIP-34 repository announcement event with full customization
///
/// This helper creates a properly formatted NIP-34 announcement that will be
/// accepted by GRASP relays (which require events to list the relay in clone/relays tags).
/// This is the core method for creating repository announcements. It allows
/// specifying the signing keys and maintainers, making it suitable for all
/// repo creation scenarios including maintainer and recursive maintainer testing.
///
/// # Arguments
/// * `test_name` - Name of the test (used to create unique repo identifier)
/// * `signing_keys` - The keys to sign the event with (also used for clone URL)
/// * `maintainer_pubkeys` - Hex pubkeys of maintainers who can push to the repository
///
/// # Returns
/// A built and signed Event ready to be sent to the relay
pub async fn create_repo_announcement(&self, test_name: &str) -> Result<Event> {
/// A tuple of (Event, repo_id) - the built event and the repository identifier
pub async fn create_repo_announcement_custom(
&self,
test_name: &str,
signing_keys: &Keys,
maintainer_pubkeys: &[String],
) -> Result<(Event, String)> {
// Get relay URL from client
let relay_url = self
.client
@@ -251,8 +291,8 @@ impl AuditClient {
// Create unique repository identifier using UUID for consistency
let repo_id = format!("{}-{}", test_name, &uuid::Uuid::new_v4().to_string()[..8]);
// Get npub for clone URL
let npub = self
// Get npub for clone URL from signing keys
let npub = signing_keys
.public_key()
.to_bech32()
.map_err(|e| anyhow!("Failed to convert public key to bech32 npub format: {}", e))?;
@@ -280,9 +320,35 @@ impl AuditClient {
TagKind::custom("relays"),
vec![relay_url.clone()],
))
.build(self.keys())
.tag(Tag::custom(
TagKind::custom("maintainers"),
maintainer_pubkeys.to_vec(),
))
.build(signing_keys)
.map_err(|e| anyhow!("Failed to build repository announcement event: {}", e))?;
Ok((event, repo_id))
}
/// Create a NIP-34 repository announcement event with the client's maintainer
///
/// This helper creates a properly formatted NIP-34 announcement that will be
/// accepted by GRASP relays (which require events to list the relay in clone/relays tags).
/// The client's maintainer key is automatically added to the maintainers tag.
///
/// # Arguments
/// * `test_name` - Name of the test (used to create unique repo identifier)
///
/// # Returns
/// A built and signed Event ready to be sent to the relay
pub async fn create_repo_announcement(&self, test_name: &str) -> Result<Event> {
let (event, _repo_id) = self
.create_repo_announcement_custom(
test_name,
self.keys(),
&[self.maintainer_pubkey_hex()],
)
.await?;
Ok(event)
}
@@ -303,60 +369,9 @@ impl AuditClient {
test_name: &str,
maintainer_pubkeys: &[String],
) -> Result<Event> {
// Get relay URL from client
let relay_url = self
.client
.relays()
.await
.keys()
.next()
.ok_or_else(|| anyhow!("No relay connected"))?
.to_string();
// Convert WebSocket URL to HTTP URL for clone tag
let http_url = relay_url
.replace("ws://", "http://")
.replace("wss://", "https://");
// Create unique repository identifier using UUID for consistency
let repo_id = format!("{}-{}", test_name, &uuid::Uuid::new_v4().to_string()[..8]);
// Get npub for clone URL
let npub = self
.public_key()
.to_bech32()
.map_err(|e| anyhow!("Failed to convert public key to bech32 npub format: {}", e))?;
// Build kind 30617 repository announcement with maintainers tag
let event = self
.event_builder(
Kind::GitRepoAnnouncement,
format!("Test repository for {}", test_name),
)
.tag(Tag::identifier(&repo_id))
.tag(Tag::custom(
TagKind::custom("name"),
vec![format!("{} Test Repository", test_name)],
))
.tag(Tag::custom(
TagKind::custom("description"),
vec![format!("Repository for {} testing", test_name)],
))
.tag(Tag::custom(
TagKind::custom("clone"),
vec![format!("{}/{}/{}.git", http_url, npub, repo_id)],
))
.tag(Tag::custom(
TagKind::custom("relays"),
vec![relay_url.clone()],
))
.tag(Tag::custom(
TagKind::custom("maintainers"),
maintainer_pubkeys.to_vec(),
))
.build(self.keys())
.map_err(|e| anyhow!("Failed to build repository announcement event: {}", e))?;
let (event, _repo_id) = self
.create_repo_announcement_custom(test_name, self.keys(), maintainer_pubkeys)
.await?;
Ok(event)
}
@@ -465,10 +480,14 @@ mod tests {
fn test_event_builder() {
let config = AuditConfig::ci();
let keys = Keys::generate();
let maintainer_keys = Keys::generate();
let recursive_maintainer_keys = Keys::generate();
let client = AuditClient {
client: Client::new(keys.clone()),
config: config.clone(),
keys: keys.clone(),
maintainer_keys,
recursive_maintainer_keys,
};
let _builder = client.event_builder(Kind::TextNote, "test content");
@@ -481,10 +500,14 @@ mod tests {
fn test_audit_tags_automatically_added() {
let config = AuditConfig::ci();
let keys = Keys::generate();
let maintainer_keys = Keys::generate();
let recursive_maintainer_keys = Keys::generate();
let client = AuditClient {
client: Client::new(keys.clone()),
config: config.clone(),
keys: keys.clone(),
maintainer_keys,
recursive_maintainer_keys,
};
// Create an event with a custom tag
+359 -19
View File
@@ -28,7 +28,7 @@ use nostr_sdk::prelude::Event;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
/// Deterministic commit hash used in RepoState fixtures
/// Deterministic commit hash used in RepoState fixtures (Owner variant)
/// This is the hash produced by creating a commit with:
/// - Message: "Initial commit"
/// - File: test.txt containing "Initial commit"
@@ -39,20 +39,101 @@ use std::sync::{Arc, Mutex};
/// - Parent: Initial empty commit (09cc37de80f3434fa98864a86730b8d7777bd6ae)
pub const DETERMINISTIC_COMMIT_HASH: &str = "64ea71d79a57a7acb334cd9651f8aec067c0ce5d";
/// Deterministic commit hash for maintainer fixtures (Maintainer variant)
/// This is the hash produced by creating a commit with:
/// - Message: "Maintainer initial commit"
/// - File: test.txt containing "Maintainer initial commit"
/// - Author date: 2024-01-01T00:00:00Z
/// - Committer date: 2024-01-01T00:00:00Z
/// - GPG signing: disabled
/// - User: "GRASP Audit Test <test@grasp-audit.local>"
/// - Parent: none (root commit)
/// NOTE: This value is different from DETERMINISTIC_COMMIT_HASH due to different content
pub const MAINTAINER_DETERMINISTIC_COMMIT_HASH: &str = "1c2d472c9b71ed51968a66500281a3c4a6840464";
/// Deterministic commit hash for recursive maintainer fixtures (RecursiveMaintainer variant)
/// This is the hash produced by creating a commit with:
/// - Message: "Recursive maintainer initial commit"
/// - File: test.txt containing "Recursive maintainer initial commit"
/// - Author date: 2024-01-01T00:00:00Z
/// - Committer date: 2024-01-01T00:00:00Z
/// - GPG signing: disabled
/// - User: "GRASP Audit Test <test@grasp-audit.local>"
/// - Parent: none (root commit)
/// NOTE: This value is different from DETERMINISTIC_COMMIT_HASH due to different content
pub const RECURSIVE_MAINTAINER_DETERMINISTIC_COMMIT_HASH: &str = "05939b82de66fbdb9c077d0a64fc68522f3cb8e0";
/// Types of test fixtures available
///
/// ## Fixture Dependencies
///
/// Several fixtures depend on `ValidRepo` - they all use the SAME repo_id
/// within a single TestContext instance to ensure proper fixture relationships:
/// - `RepoState` → uses ValidRepo's repo_id
/// - `MaintainerAnnouncement` + `MaintainerState` → uses ValidRepo's repo_id
/// - `RecursiveMaintainerRepoAndState` → uses ValidRepo's repo_id
///
/// This enables testing recursive maintainer authorization chains where multiple
/// parties publish announcements and state events for the same repository.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum FixtureKind {
/// Basic repository announcement (kind 30617)
/// - Signed by owner keys (`client.keys()`)
/// - Lists `client.maintainer_pubkey_hex()` in maintainers tag
ValidRepo,
/// Repository with one issue (kind 1621)
/// - Requires ValidRepo (reuses same repo_id)
RepoWithIssue,
/// Repository with issue and comment (kind 1111)
/// - Requires RepoWithIssue (reuses same repo_id)
RepoWithComment,
/// Repository state announcement (kind 30618)
/// Repository state announcement (kind 30618) for owner
/// - Requires ValidRepo (uses same repo_id)
/// - Signed by owner keys (`client.keys()`)
/// - Points to DETERMINISTIC_COMMIT_HASH
/// - Timestamp: 10 seconds in the past
RepoState,
/// Maintainer's repo announcement only for the SAME repo_id as ValidRepo
/// - Requires ValidRepo (uses same repo_id for maintainer chain)
/// - Announcement signed by `client.maintainer_keys()`
/// - Lists `client.recursive_maintainer_pubkey_hex()` in maintainers tag
/// - Does NOT include state event (use MaintainerState for that)
MaintainerAnnouncement,
/// Maintainer's state event only for the SAME repo_id as ValidRepo
/// - Requires ValidRepo (uses same repo_id for maintainer chain)
/// - State event signed by `client.maintainer_keys()`
/// - Points to MAINTAINER_DETERMINISTIC_COMMIT_HASH
/// - Timestamp: 5 seconds in the past (more recent than owner's state)
/// - Does NOT include announcement (use MaintainerAnnouncement for that)
MaintainerState,
/// Recursive maintainer's announcement only for the SAME repo_id as ValidRepo
/// - Requires ValidRepo (uses same repo_id for recursive chain)
/// - Announcement signed by `client.recursive_maintainer_keys()`
/// - Lists owner and maintainer in maintainers tag
/// - Does NOT include state event (use RecursiveMaintainerState for that)
RecursiveMaintainerAnnouncement,
/// Recursive maintainer's state event only for the SAME repo_id as ValidRepo
/// - Requires ValidRepo (uses same repo_id for recursive chain)
/// - State event signed by `client.recursive_maintainer_keys()`
/// - Points to RECURSIVE_MAINTAINER_DETERMINISTIC_COMMIT_HASH
/// - Timestamp: 2 seconds in the past (most recent)
/// - Does NOT include announcement (use RecursiveMaintainerAnnouncement for that)
RecursiveMaintainerState,
/// Recursive maintainer's announcement + state for the SAME repo_id as ValidRepo
/// - Requires ValidRepo (uses same repo_id for recursive chain)
/// - Announcement signed by `client.recursive_maintainer_keys()`
/// - Lists owner and maintainer in maintainers tag
/// - State event points to RECURSIVE_MAINTAINER_DETERMINISTIC_COMMIT_HASH
/// - Timestamp: 2 seconds in the past (most recent)
RecursiveMaintainerRepoAndState,
}
/// Context mode for fixture management
@@ -214,12 +295,17 @@ impl<'a> TestContext<'a> {
Ok(event)
}
/// Get or create a ValidRepo, with mode-appropriate caching.
/// Get or create a ValidRepo, with caching within the TestContext.
/// This is a helper method that avoids async recursion by not going
/// through get_fixture. It handles the repo specifically.
///
/// IMPORTANT: We always cache within a TestContext instance to ensure
/// fixture dependencies work correctly. The isolation between tests
/// comes from each test having its own TestContext with a fresh cache.
async fn get_or_create_repo(&self) -> Result<Event> {
// In Shared mode, check cache first
if self.mode == ContextMode::Shared {
// Always check cache first - this ensures fixture dependencies work
// (e.g., MaintainerRepoAndState needs the SAME repo_id as RepoState)
{
let cache = self.cache.lock().unwrap();
if let Some(event) = cache.get(&FixtureKind::ValidRepo) {
return Ok(event.clone());
@@ -237,8 +323,8 @@ impl<'a> TestContext<'a> {
// Send it
self.client.send_event(repo.clone()).await?;
// Cache it in Shared mode
if self.mode == ContextMode::Shared {
// Always cache it - isolation comes from each test having its own TestContext
{
let mut cache = self.cache.lock().unwrap();
cache.insert(FixtureKind::ValidRepo, repo.clone());
}
@@ -246,18 +332,18 @@ impl<'a> TestContext<'a> {
Ok(repo)
}
/// Get or create a RepoWithIssue, with mode-appropriate caching.
/// Get or create a RepoWithIssue, with caching within the TestContext.
/// Returns the issue event (repo is already sent/cached via get_or_create_repo).
async fn get_or_create_issue(&self) -> Result<Event> {
// In Shared mode, check cache first
if self.mode == ContextMode::Shared {
// Always check cache first - ensures fixture dependencies work
{
let cache = self.cache.lock().unwrap();
if let Some(event) = cache.get(&FixtureKind::RepoWithIssue) {
return Ok(event.clone());
}
}
// Get or create repo (reuses cached in Shared mode)
// Get or create repo (reuses cached within this TestContext)
let repo = self.get_or_create_repo().await?;
// Create the issue
@@ -271,8 +357,8 @@ impl<'a> TestContext<'a> {
// Send it
self.client.send_event(issue.clone()).await?;
// Cache it in Shared mode
if self.mode == ContextMode::Shared {
// Always cache it - isolation comes from each test having its own TestContext
{
let mut cache = self.cache.lock().unwrap();
cache.insert(FixtureKind::RepoWithIssue, issue.clone());
}
@@ -284,12 +370,8 @@ impl<'a> TestContext<'a> {
async fn build_fixture(&self, kind: FixtureKind) -> Result<Event> {
match kind {
FixtureKind::ValidRepo => {
let test_name = format!(
"fixture-{:?}-{}",
kind,
&uuid::Uuid::new_v4().to_string()[..8]
);
self.client.create_repo_announcement(&test_name).await
// Delegate to get_or_create_repo() which handles caching properly.
self.get_or_create_repo().await
}
FixtureKind::RepoWithIssue => {
@@ -340,6 +422,9 @@ impl<'a> TestContext<'a> {
.to_string();
// Create state announcement with deterministic commit hash
let base_time = Timestamp::now().as_u64();
let older_timestamp = Timestamp::from(base_time - 10); // 10 seconds ago
// Tag format: ["refs/heads/main", "<commit_hash>"]
// Note: We build the state but DON'T send it here - the caller will send it
self.client
@@ -353,12 +438,267 @@ impl<'a> TestContext<'a> {
TagKind::custom("HEAD"),
vec!["ref: refs/heads/main".to_string()],
))
.custom_time(older_timestamp)
.build(self.client.keys())
.map_err(|e| anyhow::anyhow!("Failed to build state announcement: {}", e))
}
FixtureKind::MaintainerAnnouncement => {
use nostr_sdk::prelude::*;
// Get the owner's repo to use the SAME repo_id
let owner_repo = self.get_or_create_repo().await?;
// Extract repo_id from owner's repo announcement
let repo_id = owner_repo
.tags
.iter()
.find(|t| t.kind() == TagKind::d())
.and_then(|t| t.content())
.ok_or_else(|| anyhow::anyhow!("Missing d tag in owner repo announcement"))?
.to_string();
self.build_maintainer_announcement(&repo_id).await
}
FixtureKind::MaintainerState => {
use nostr_sdk::prelude::*;
// Get the owner's repo to use the SAME repo_id
let owner_repo = self.get_or_create_repo().await?;
// Extract repo_id from owner's repo announcement
let repo_id = owner_repo
.tags
.iter()
.find(|t| t.kind() == TagKind::d())
.and_then(|t| t.content())
.ok_or_else(|| anyhow::anyhow!("Missing d tag in owner repo announcement"))?
.to_string();
// Build state event ONLY - does NOT send announcement
// This allows testing state-only scenarios
self.build_maintainer_state(&repo_id)
}
FixtureKind::RecursiveMaintainerAnnouncement => {
use nostr_sdk::prelude::*;
// Get the owner's repo to use the SAME repo_id
let owner_repo = self.get_or_create_repo().await?;
// Extract repo_id from owner's repo announcement
let repo_id = owner_repo
.tags
.iter()
.find(|t| t.kind() == TagKind::d())
.and_then(|t| t.content())
.ok_or_else(|| anyhow::anyhow!("Missing d tag in owner repo announcement"))?
.to_string();
self.build_recursive_maintainer_announcement(&repo_id).await
}
FixtureKind::RecursiveMaintainerState => {
use nostr_sdk::prelude::*;
// Get the owner's repo to use the SAME repo_id
let owner_repo = self.get_or_create_repo().await?;
// Extract repo_id from owner's repo announcement
let repo_id = owner_repo
.tags
.iter()
.find(|t| t.kind() == TagKind::d())
.and_then(|t| t.content())
.ok_or_else(|| anyhow::anyhow!("Missing d tag in owner repo announcement"))?
.to_string();
// Build state event ONLY - does NOT send announcement
self.build_recursive_maintainer_state(&repo_id)
}
FixtureKind::RecursiveMaintainerRepoAndState => {
use nostr_sdk::prelude::*;
// Get the owner's repo to use the SAME repo_id
let owner_repo = self.get_or_create_repo().await?;
// Extract repo_id from owner's repo announcement
let repo_id = owner_repo
.tags
.iter()
.find(|t| t.kind() == TagKind::d())
.and_then(|t| t.content())
.ok_or_else(|| anyhow::anyhow!("Missing d tag in owner repo announcement"))?
.to_string();
// Build and send the recursive maintainer's repo announcement
let recursive_maintainer_announcement = self.build_recursive_maintainer_announcement(&repo_id).await?;
self.client.send_event(recursive_maintainer_announcement).await?;
// Return the state event (caller will send it)
self.build_recursive_maintainer_state(&repo_id)
}
}
}
/// Build maintainer announcement event for the given repo_id
async fn build_maintainer_announcement(&self, repo_id: &str) -> Result<Event> {
use nostr_sdk::prelude::*;
// Get relay URL for clone tag
let relay_url = self.client
.client()
.relays()
.await
.keys()
.next()
.ok_or_else(|| anyhow::anyhow!("No relay connected"))?
.to_string();
let http_url = relay_url
.replace("ws://", "http://")
.replace("wss://", "https://");
// Create maintainer's repo announcement for the SAME repo_id
let maintainer_npub = self.client
.maintainer_keys()
.public_key()
.to_bech32()
.map_err(|e| anyhow::anyhow!("Failed to convert maintainer pubkey: {}", e))?;
self.client
.event_builder(
Kind::GitRepoAnnouncement,
format!("Maintainer announcement for {}", repo_id),
)
.tag(Tag::identifier(repo_id))
.tag(Tag::custom(
TagKind::custom("name"),
vec![format!("{} (maintainer)", repo_id)],
))
.tag(Tag::custom(
TagKind::custom("clone"),
vec![format!("{}/{}/{}.git", http_url, maintainer_npub, repo_id)],
))
.tag(Tag::custom(
TagKind::custom("relays"),
vec![relay_url],
))
.tag(Tag::custom(
TagKind::custom("maintainers"),
vec![self.client.recursive_maintainer_pubkey_hex()],
))
.build(self.client.maintainer_keys())
.map_err(|e| anyhow::anyhow!("Failed to build maintainer repo announcement: {}", e))
}
/// Build maintainer state event for the given repo_id
fn build_maintainer_state(&self, repo_id: &str) -> Result<Event> {
use nostr_sdk::prelude::*;
// Create state announcement 5 seconds in the past, signed by maintainer
let base_time = Timestamp::now().as_u64();
let older_timestamp = Timestamp::from(base_time - 5); // 5 seconds ago
self.client
.event_builder(Kind::Custom(30618), "")
.tag(Tag::identifier(repo_id))
.tag(Tag::custom(
TagKind::custom("refs/heads/main"),
vec![MAINTAINER_DETERMINISTIC_COMMIT_HASH.to_string()],
))
.tag(Tag::custom(
TagKind::custom("HEAD"),
vec!["ref: refs/heads/main".to_string()],
))
.custom_time(older_timestamp)
.build(self.client.maintainer_keys())
.map_err(|e| anyhow::anyhow!("Failed to build maintainer state announcement: {}", e))
}
/// Build recursive maintainer announcement event for the given repo_id
async fn build_recursive_maintainer_announcement(&self, repo_id: &str) -> Result<Event> {
use nostr_sdk::prelude::*;
// Get relay URL for clone tag
let relay_url = self.client
.client()
.relays()
.await
.keys()
.next()
.ok_or_else(|| anyhow::anyhow!("No relay connected"))?
.to_string();
let http_url = relay_url
.replace("ws://", "http://")
.replace("wss://", "https://");
// Create recursive maintainer's repo announcement for the SAME repo_id
let recursive_maintainer_npub = self.client
.recursive_maintainer_keys()
.public_key()
.to_bech32()
.map_err(|e| anyhow::anyhow!("Failed to convert recursive maintainer pubkey: {}", e))?;
self.client
.event_builder(
Kind::GitRepoAnnouncement,
format!("Recursive maintainer announcement for {}", repo_id),
)
.tag(Tag::identifier(repo_id))
.tag(Tag::custom(
TagKind::custom("name"),
vec![format!("{} (recursive maintainer)", repo_id)],
))
.tag(Tag::custom(
TagKind::custom("clone"),
vec![format!("{}/{}/{}.git", http_url, recursive_maintainer_npub, repo_id)],
))
.tag(Tag::custom(
TagKind::custom("relays"),
vec![relay_url],
))
.tag(Tag::custom(
TagKind::custom("maintainers"),
vec![
self.client.public_key().to_hex(),
self.client.maintainer_pubkey_hex(),
],
))
.build(self.client.recursive_maintainer_keys())
.map_err(|e| anyhow::anyhow!("Failed to build recursive maintainer repo announcement: {}", e))
}
/// Build recursive maintainer state event for the given repo_id
fn build_recursive_maintainer_state(&self, repo_id: &str) -> Result<Event> {
use nostr_sdk::prelude::*;
// Create state announcement 2 seconds in the past, signed by recursive maintainer
let base_time = Timestamp::now().as_u64();
let older_timestamp = Timestamp::from(base_time - 2); // 2 seconds ago
self.client
.event_builder(Kind::Custom(30618), "")
.tag(Tag::identifier(repo_id))
.tag(Tag::custom(
TagKind::custom("refs/heads/main"),
vec![RECURSIVE_MAINTAINER_DETERMINISTIC_COMMIT_HASH.to_string()],
))
.tag(Tag::custom(
TagKind::custom("HEAD"),
vec!["ref: refs/heads/main".to_string()],
))
.custom_time(older_timestamp)
.build(self.client.recursive_maintainer_keys())
.map_err(|e| {
anyhow::anyhow!(
"Failed to build recursive maintainer state announcement: {}",
e
)
})
}
/// Clear the fixture cache
///
/// This is useful for tests that want to ensure fresh fixtures
+4 -1
View File
@@ -37,7 +37,10 @@ pub mod specs;
pub use audit::{AuditConfig, AuditMode};
pub use client::AuditClient;
pub use fixtures::{ContextMode, FixtureKind, TestContext, DETERMINISTIC_COMMIT_HASH};
pub use fixtures::{
ContextMode, FixtureKind, TestContext, DETERMINISTIC_COMMIT_HASH,
MAINTAINER_DETERMINISTIC_COMMIT_HASH, RECURSIVE_MAINTAINER_DETERMINISTIC_COMMIT_HASH,
};
pub use result::{AuditResult, TestResult};
// Re-export commonly used types
+1 -1
View File
@@ -267,7 +267,7 @@ impl GitCloneTests {
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_module_exists() {
+1 -1
View File
@@ -13,5 +13,5 @@ pub use event_acceptance_policy::EventAcceptancePolicyTests;
pub use git_clone::GitCloneTests;
pub use nip01_smoke::Nip01SmokeTests;
pub use nip11_document::Nip11DocumentTests;
pub use push_authorization::PushAuthorizationTests;
pub use push_authorization::{CommitVariant, PushAuthorizationTests};
pub use repository_creation::RepositoryCreationTests;
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -65,5 +65,6 @@ macro_rules! isolated_push_test {
isolated_push_test!(test_push_authorized_by_owner_state);
isolated_push_test!(test_push_rejected_without_state_event);
isolated_push_test!(test_push_rejected_wrong_commit);
isolated_push_test!(test_latest_state_event_used);
isolated_push_test!(test_push_authorized_by_direct_maintainer_state);
isolated_push_test!(test_push_authorized_by_recursive_maintainer_state);
isolated_push_test!(test_non_maintainer_state_rejected);