upleb.uk

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

summaryrefslogtreecommitdiff
path: root/grasp-audit/src
diff options
context:
space:
mode:
Diffstat (limited to 'grasp-audit/src')
-rw-r--r--grasp-audit/src/bin/grasp-audit.rs16
-rw-r--r--grasp-audit/src/lib.rs22
-rw-r--r--grasp-audit/src/result.rs12
-rw-r--r--grasp-audit/src/specs/grasp01/cors.rs51
-rw-r--r--grasp-audit/src/specs/grasp01/event_acceptance_policy.rs62
-rw-r--r--grasp-audit/src/specs/grasp01/git_clone.rs54
-rw-r--r--grasp-audit/src/specs/grasp01/mod.rs2
-rw-r--r--grasp-audit/src/specs/grasp01/nip01_smoke.rs32
-rw-r--r--grasp-audit/src/specs/grasp01/nip11_document.rs61
-rw-r--r--grasp-audit/src/specs/grasp01/push_authorization.rs10
-rw-r--r--grasp-audit/src/specs/grasp01/repository_creation.rs20
11 files changed, 147 insertions, 195 deletions
diff --git a/grasp-audit/src/bin/grasp-audit.rs b/grasp-audit/src/bin/grasp-audit.rs
index 2aabefe..48c1580 100644
--- a/grasp-audit/src/bin/grasp-audit.rs
+++ b/grasp-audit/src/bin/grasp-audit.rs
@@ -47,14 +47,18 @@ async fn main() -> Result<()> {
47 let cli = Cli::parse(); 47 let cli = Cli::parse();
48 48
49 match cli.command { 49 match cli.command {
50 Commands::Audit { relay, mode, spec, git_data_dir } => { 50 Commands::Audit {
51 51 relay,
52 mode,
53 spec,
54 git_data_dir,
55 } => {
52 let mut config = match mode.as_str() { 56 let mut config = match mode.as_str() {
53 "ci" => AuditConfig::ci(), 57 "ci" => AuditConfig::ci(),
54 "production" => AuditConfig::production(), 58 "production" => AuditConfig::production(),
55 _ => return Err(anyhow!("Invalid mode: {}. Use 'ci' or 'production'", mode)), 59 _ => return Err(anyhow!("Invalid mode: {}. Use 'ci' or 'production'", mode)),
56 }; 60 };
57 61
58 // Audit needs to create events to test the relay, so disable read-only mode 62 // Audit needs to create events to test the relay, so disable read-only mode
59 config.read_only = false; 63 config.read_only = false;
60 64
@@ -145,17 +149,17 @@ async fn main() -> Result<()> {
145 println!(" → NIP-01 smoke tests..."); 149 println!(" → NIP-01 smoke tests...");
146 let nip01_results = specs::Nip01SmokeTests::run_all(&client).await; 150 let nip01_results = specs::Nip01SmokeTests::run_all(&client).await;
147 all_results.merge(nip01_results); 151 all_results.merge(nip01_results);
148 152
149 // NIP-11 document tests 153 // NIP-11 document tests
150 println!(" → NIP-11 document tests..."); 154 println!(" → NIP-11 document tests...");
151 let nip11_results = specs::Nip11DocumentTests::run_all(&client).await; 155 let nip11_results = specs::Nip11DocumentTests::run_all(&client).await;
152 all_results.merge(nip11_results); 156 all_results.merge(nip11_results);
153 157
154 // CORS tests 158 // CORS tests
155 println!(" → CORS tests..."); 159 println!(" → CORS tests...");
156 let cors_results = specs::CorsTests::run_all(&client, &relay_domain).await; 160 let cors_results = specs::CorsTests::run_all(&client, &relay_domain).await;
157 all_results.merge(cors_results); 161 all_results.merge(cors_results);
158 162
159 println!(); 163 println!();
160 all_results 164 all_results
161 } 165 }
diff --git a/grasp-audit/src/lib.rs b/grasp-audit/src/lib.rs
index fb52ba7..6df240f 100644
--- a/grasp-audit/src/lib.rs
+++ b/grasp-audit/src/lib.rs
@@ -39,14 +39,24 @@ pub use audit::{AuditConfig, AuditEventBuilder, AuditMode};
39pub use client::AuditClient; 39pub use client::AuditClient;
40pub use fixtures::{ 40pub use fixtures::{
41 // Git operation helpers 41 // Git operation helpers
42 clone_repo, create_commit, create_deterministic_commit, create_deterministic_commit_with_variant, 42 clone_repo,
43 try_push, try_push_to_ref, 43 create_commit,
44 create_deterministic_commit,
45 create_deterministic_commit_with_variant,
44 // Verification helpers 46 // Verification helpers
45 send_and_verify_accepted, send_and_verify_rejected, 47 send_and_verify_accepted,
48 send_and_verify_rejected,
49 try_push,
50 try_push_to_ref,
46 // Types and constants 51 // Types and constants
47 CommitVariant, ContextMode, FixtureKind, TestContext, 52 CommitVariant,
48 DETERMINISTIC_COMMIT_HASH, MAINTAINER_DETERMINISTIC_COMMIT_HASH, 53 ContextMode,
49 PR_TEST_COMMIT_HASH, RECURSIVE_MAINTAINER_DETERMINISTIC_COMMIT_HASH, 54 FixtureKind,
55 TestContext,
56 DETERMINISTIC_COMMIT_HASH,
57 MAINTAINER_DETERMINISTIC_COMMIT_HASH,
58 PR_TEST_COMMIT_HASH,
59 RECURSIVE_MAINTAINER_DETERMINISTIC_COMMIT_HASH,
50}; 60};
51pub use result::{AuditResult, TestResult}; 61pub use result::{AuditResult, TestResult};
52 62
diff --git a/grasp-audit/src/result.rs b/grasp-audit/src/result.rs
index 2bec5c8..bc0008a 100644
--- a/grasp-audit/src/result.rs
+++ b/grasp-audit/src/result.rs
@@ -17,7 +17,12 @@ fn extract_spec_category(spec_ref: &str) -> String {
17 if parts.len() >= 2 { 17 if parts.len() >= 2 {
18 // Check if the last part looks like a test number (starts with digit) 18 // Check if the last part looks like a test number (starts with digit)
19 if let Some(last) = parts.last() { 19 if let Some(last) = parts.last() {
20 if last.chars().next().map(|c| c.is_ascii_digit()).unwrap_or(false) { 20 if last
21 .chars()
22 .next()
23 .map(|c| c.is_ascii_digit())
24 .unwrap_or(false)
25 {
21 // Remove the trailing number part 26 // Remove the trailing number part
22 return parts[..parts.len() - 1].join(":"); 27 return parts[..parts.len() - 1].join(":");
23 } 28 }
@@ -146,10 +151,7 @@ impl AuditResult {
146 for result in &self.results { 151 for result in &self.results {
147 // Extract category from spec_ref (e.g., "GRASP-01:event-acceptance:1.1" -> "GRASP-01:event-acceptance") 152 // Extract category from spec_ref (e.g., "GRASP-01:event-acceptance:1.1" -> "GRASP-01:event-acceptance")
148 let category = extract_spec_category(&result.spec_ref); 153 let category = extract_spec_category(&result.spec_ref);
149 grouped 154 grouped.entry(category).or_default().push(result);
150 .entry(category)
151 .or_default()
152 .push(result);
153 } 155 }
154 156
155 // Print grouped results 157 // Print grouped results
diff --git a/grasp-audit/src/specs/grasp01/cors.rs b/grasp-audit/src/specs/grasp01/cors.rs
index 08c5ab6..c877c04 100644
--- a/grasp-audit/src/specs/grasp01/cors.rs
+++ b/grasp-audit/src/specs/grasp01/cors.rs
@@ -16,7 +16,6 @@
16 16
17use crate::{AuditClient, AuditResult, FixtureKind, TestContext, TestResult}; 17use crate::{AuditClient, AuditResult, FixtureKind, TestContext, TestResult};
18use nostr_sdk::prelude::*; 18use nostr_sdk::prelude::*;
19use std::path::Path;
20 19
21pub struct CorsTests; 20pub struct CorsTests;
22 21
@@ -42,10 +41,7 @@ impl CorsTests {
42 /// 41 ///
43 /// Spec: Line 44 of ../grasp/01.md 42 /// Spec: Line 44 of ../grasp/01.md
44 /// Requirement: Set `Access-Control-Allow-Origin: *` on ALL responses 43 /// Requirement: Set `Access-Control-Allow-Origin: *` on ALL responses
45 pub async fn test_cors_allow_origin( 44 pub async fn test_cors_allow_origin(_client: &AuditClient, relay_domain: &str) -> TestResult {
46 _client: &AuditClient,
47 relay_domain: &str,
48 ) -> TestResult {
49 TestResult::new( 45 TestResult::new(
50 "cors_allow_origin", 46 "cors_allow_origin",
51 "GRASP-01:git-http:cors:44", 47 "GRASP-01:git-http:cors:44",
@@ -91,10 +87,7 @@ impl CorsTests {
91 /// 87 ///
92 /// Spec: Line 45 of ../grasp/01.md 88 /// Spec: Line 45 of ../grasp/01.md
93 /// Requirement: Set `Access-Control-Allow-Methods: GET, POST` on ALL responses 89 /// Requirement: Set `Access-Control-Allow-Methods: GET, POST` on ALL responses
94 pub async fn test_cors_allow_methods( 90 pub async fn test_cors_allow_methods(_client: &AuditClient, relay_domain: &str) -> TestResult {
95 _client: &AuditClient,
96 relay_domain: &str,
97 ) -> TestResult {
98 TestResult::new( 91 TestResult::new(
99 "cors_allow_methods", 92 "cors_allow_methods",
100 "GRASP-01:git-http:cors:45", 93 "GRASP-01:git-http:cors:45",
@@ -138,10 +131,7 @@ impl CorsTests {
138 /// 131 ///
139 /// Spec: Line 46 of ../grasp/01.md 132 /// Spec: Line 46 of ../grasp/01.md
140 /// Requirement: Set `Access-Control-Allow-Headers: Content-Type` on ALL responses 133 /// Requirement: Set `Access-Control-Allow-Headers: Content-Type` on ALL responses
141 pub async fn test_cors_allow_headers( 134 pub async fn test_cors_allow_headers(_client: &AuditClient, relay_domain: &str) -> TestResult {
142 _client: &AuditClient,
143 relay_domain: &str,
144 ) -> TestResult {
145 TestResult::new( 135 TestResult::new(
146 "cors_allow_headers", 136 "cors_allow_headers",
147 "GRASP-01:git-http:cors:46", 137 "GRASP-01:git-http:cors:46",
@@ -212,10 +202,8 @@ impl CorsTests {
212 check_options_response(&response, "root endpoint")?; 202 check_options_response(&response, "root endpoint")?;
213 203
214 // 2. Test OPTIONS on git-upload-pack endpoint 204 // 2. Test OPTIONS on git-upload-pack endpoint
215 let repo_url = format!( 205 let repo_url =
216 "http://{}/npub1test/test.git/git-upload-pack", 206 format!("http://{}/npub1test/test.git/git-upload-pack", relay_domain);
217 relay_domain
218 );
219 let response = http_client 207 let response = http_client
220 .request(reqwest::Method::OPTIONS, &repo_url) 208 .request(reqwest::Method::OPTIONS, &repo_url)
221 .header("Origin", "https://example.com") 209 .header("Origin", "https://example.com")
@@ -227,10 +215,7 @@ impl CorsTests {
227 check_options_response(&response, "git-upload-pack endpoint")?; 215 check_options_response(&response, "git-upload-pack endpoint")?;
228 216
229 // 3. Test OPTIONS on info/refs endpoint 217 // 3. Test OPTIONS on info/refs endpoint
230 let refs_url = format!( 218 let refs_url = format!("http://{}/npub1test/test.git/info/refs", relay_domain);
231 "http://{}/npub1test/test.git/info/refs",
232 relay_domain
233 );
234 let response = http_client 219 let response = http_client
235 .request(reqwest::Method::OPTIONS, &refs_url) 220 .request(reqwest::Method::OPTIONS, &refs_url)
236 .header("Origin", "https://example.com") 221 .header("Origin", "https://example.com")
@@ -255,10 +240,7 @@ impl CorsTests {
255 /// Integration test: CORS Allow-Origin header with repository creation 240 /// Integration test: CORS Allow-Origin header with repository creation
256 /// 241 ///
257 /// For integration tests that want to test against real repositories 242 /// For integration tests that want to test against real repositories
258 pub async fn test_cors_on_real_repo( 243 pub async fn test_cors_on_real_repo(client: &AuditClient, relay_domain: &str) -> TestResult {
259 client: &AuditClient,
260 relay_domain: &str,
261 ) -> TestResult {
262 let test_name = "test_cors_on_real_repo"; 244 let test_name = "test_cors_on_real_repo";
263 let ctx = TestContext::new(client); 245 let ctx = TestContext::new(client);
264 246
@@ -271,7 +253,7 @@ impl CorsTests {
271 "GRASP-01", 253 "GRASP-01",
272 "CORS headers on real repository endpoint", 254 "CORS headers on real repository endpoint",
273 ) 255 )
274 .fail(&format!("Failed to create repo fixture: {}", e)) 256 .fail(format!("Failed to create repo fixture: {}", e))
275 } 257 }
276 }; 258 };
277 259
@@ -304,7 +286,7 @@ impl CorsTests {
304 "GRASP-01", 286 "GRASP-01",
305 "CORS headers on real repository endpoint", 287 "CORS headers on real repository endpoint",
306 ) 288 )
307 .fail(&format!("Failed to convert pubkey to npub: {}", e)) 289 .fail(format!("Failed to convert pubkey to npub: {}", e))
308 } 290 }
309 }; 291 };
310 292
@@ -323,7 +305,7 @@ impl CorsTests {
323 "GRASP-01", 305 "GRASP-01",
324 "CORS headers on real repository endpoint", 306 "CORS headers on real repository endpoint",
325 ) 307 )
326 .fail(&format!("Failed to GET info/refs: {}", e)) 308 .fail(format!("Failed to GET info/refs: {}", e))
327 } 309 }
328 }; 310 };
329 311
@@ -492,15 +474,6 @@ mod tests {
492 results.print_report(); 474 results.print_report();
493 475
494 // Assert all tests passed 476 // Assert all tests passed
495 assert!( 477 assert!(results.all_passed(), "Some GRASP-01 CORS tests failed");
496 results.all_passed(),
497 "Some GRASP-01 CORS tests failed"
498 );
499 } 478 }
500 479}
501 #[test]
502 fn test_module_exists() {
503 // Simple compilation test
504 assert!(true);
505 }
506} \ No newline at end of file
diff --git a/grasp-audit/src/specs/grasp01/event_acceptance_policy.rs b/grasp-audit/src/specs/grasp01/event_acceptance_policy.rs
index 3a8f18d..1fc7f73 100644
--- a/grasp-audit/src/specs/grasp01/event_acceptance_policy.rs
+++ b/grasp-audit/src/specs/grasp01/event_acceptance_policy.rs
@@ -247,7 +247,9 @@ impl EventAcceptancePolicyTests {
247 /// 247 ///
248 /// Spec: Line 5 of ../grasp/01.md 248 /// Spec: Line 5 of ../grasp/01.md
249 /// Requirement: MUST reject announcements not listing service (unless GRASP-05) 249 /// Requirement: MUST reject announcements not listing service (unless GRASP-05)
250 pub async fn test_reject_repo_announcement_missing_clone_tag(client: &AuditClient) -> TestResult { 250 pub async fn test_reject_repo_announcement_missing_clone_tag(
251 client: &AuditClient,
252 ) -> TestResult {
251 TestResult::new( 253 TestResult::new(
252 "reject_repo_announcement_missing_clone_tag", 254 "reject_repo_announcement_missing_clone_tag",
253 "GRASP-01:nostr-relay:5", 255 "GRASP-01:nostr-relay:5",
@@ -321,7 +323,9 @@ impl EventAcceptancePolicyTests {
321 /// 323 ///
322 /// Spec: Line 5 of ../grasp/01.md 324 /// Spec: Line 5 of ../grasp/01.md
323 /// Requirement: MUST reject announcements not listing service in relays 325 /// Requirement: MUST reject announcements not listing service in relays
324 pub async fn test_reject_repo_announcement_missing_relays_tag(client: &AuditClient) -> TestResult { 326 pub async fn test_reject_repo_announcement_missing_relays_tag(
327 client: &AuditClient,
328 ) -> TestResult {
325 TestResult::new( 329 TestResult::new(
326 "reject_repo_announcement_missing_relays_tag", 330 "reject_repo_announcement_missing_relays_tag",
327 "GRASP-01:nostr-relay:5", 331 "GRASP-01:nostr-relay:5",
@@ -546,8 +550,7 @@ impl EventAcceptancePolicyTests {
546 let issue = Self::create_issue_for_repo(client, &repo, "Test Issue 1")?; 550 let issue = Self::create_issue_for_repo(client, &repo, "Test Issue 1")?;
547 551
548 // 3. Send issue and verify it's accepted 552 // 3. Send issue and verify it's accepted
549 send_and_verify_accepted(client, issue, "issue referencing repo via 'a' tag") 553 send_and_verify_accepted(client, issue, "issue referencing repo via 'a' tag").await?;
550 .await?;
551 554
552 Ok(()) 555 Ok(())
553 }) 556 })
@@ -693,8 +696,7 @@ impl EventAcceptancePolicyTests {
693 .map_err(|e| format!("Failed to build issue B: {}", e))?; 696 .map_err(|e| format!("Failed to build issue B: {}", e))?;
694 697
695 // Send Issue B and verify it's ACCEPTED (via transitive quote to Issue A) 698 // Send Issue B and verify it's ACCEPTED (via transitive quote to Issue A)
696 send_and_verify_accepted(client, issue_b, "issue B quoting accepted issue A") 699 send_and_verify_accepted(client, issue_b, "issue B quoting accepted issue A").await?;
697 .await?;
698 700
699 Ok(()) 701 Ok(())
700 }) 702 })
@@ -772,8 +774,7 @@ impl EventAcceptancePolicyTests {
772 .build(client.keys()) 774 .build(client.keys())
773 .map_err(|e| format!("Failed to build kind1 A: {}", e))?; 775 .map_err(|e| format!("Failed to build kind1 A: {}", e))?;
774 776
775 send_and_verify_accepted(client, kind1_a.clone(), "kind 1 A quoting repo") 777 send_and_verify_accepted(client, kind1_a.clone(), "kind 1 A quoting repo").await?;
776 .await?;
777 778
778 // Create Kind 1 B that replies to Kind 1 A via 'e' tag 779 // Create Kind 1 B that replies to Kind 1 A via 'e' tag
779 let kind1_b = client 780 let kind1_b = client
@@ -783,12 +784,8 @@ impl EventAcceptancePolicyTests {
783 .map_err(|e| format!("Failed to build kind1 B: {}", e))?; 784 .map_err(|e| format!("Failed to build kind1 B: {}", e))?;
784 785
785 // Send Kind 1 B and verify it's accepted (via 'e' tag to accepted kind 1 A) 786 // Send Kind 1 B and verify it's accepted (via 'e' tag to accepted kind 1 A)
786 send_and_verify_accepted( 787 send_and_verify_accepted(client, kind1_b, "kind 1 B replying to accepted kind 1 A")
787 client, 788 .await?;
788 kind1_b,
789 "kind 1 B replying to accepted kind 1 A",
790 )
791 .await?;
792 789
793 Ok(()) 790 Ok(())
794 }) 791 })
@@ -828,17 +825,19 @@ impl EventAcceptancePolicyTests {
828 .kind(Kind::GitRepoAnnouncement) 825 .kind(Kind::GitRepoAnnouncement)
829 .author(repo.pubkey) 826 .author(repo.pubkey)
830 .identifier(repo_id); 827 .identifier(repo_id);
831 828
832 // Poll until repo is available (with timeout) 829 // Poll until repo is available (with timeout)
833 for _ in 0..10 { 830 for _ in 0..10 {
834 let events = client.query(verify_filter.clone()).await 831 let events = client
832 .query(verify_filter.clone())
833 .await
835 .map_err(|e| format!("Failed to verify repo: {}", e))?; 834 .map_err(|e| format!("Failed to verify repo: {}", e))?;
836 if !events.is_empty() { 835 if !events.is_empty() {
837 break; 836 break;
838 } 837 }
839 tokio::time::sleep(Duration::from_millis(50)).await; 838 tokio::time::sleep(Duration::from_millis(50)).await;
840 } 839 }
841 840
842 // Extra delay to ensure relay's internal database is fully synchronized 841 // Extra delay to ensure relay's internal database is fully synchronized
843 tokio::time::sleep(Duration::from_millis(200)).await; 842 tokio::time::sleep(Duration::from_millis(200)).await;
844 843
@@ -907,12 +906,7 @@ impl EventAcceptancePolicyTests {
907 let issue = ctx 906 let issue = ctx
908 .get_fixture(FixtureKind::RepoWithIssue) 907 .get_fixture(FixtureKind::RepoWithIssue)
909 .await 908 .await
910 .map_err(|e| { 909 .map_err(|e| format!("Test setup failed: could not get issue fixture: {}", e))?;
911 format!(
912 "Test setup failed: could not get issue fixture: {}",
913 e
914 )
915 })?;
916 910
917 // Create Comment A locally but DON'T send it yet 911 // Create Comment A locally but DON'T send it yet
918 let comment_a = Self::create_comment_for_event(client, &issue, "Comment A")?; 912 let comment_a = Self::create_comment_for_event(client, &issue, "Comment A")?;
@@ -997,16 +991,11 @@ impl EventAcceptancePolicyTests {
997 .build(client.keys()) 991 .build(client.keys())
998 .map_err(|e| format!("Failed to build kind1 B: {}", e))?; 992 .map_err(|e| format!("Failed to build kind1 B: {}", e))?;
999 993
1000 send_and_verify_accepted(client, kind1_b, "kind1 B mentioning unsent kind1 A") 994 send_and_verify_accepted(client, kind1_b, "kind1 B mentioning unsent kind1 A").await?;
1001 .await?;
1002 995
1003 // NOW send Kind 1 A - should be accepted because accepted Kind 1 B mentions it 996 // NOW send Kind 1 A - should be accepted because accepted Kind 1 B mentions it
1004 send_and_verify_accepted( 997 send_and_verify_accepted(client, kind1_a, "kind1 A referenced by accepted kind1 B")
1005 client, 998 .await?;
1006 kind1_a,
1007 "kind1 A referenced by accepted kind1 B",
1008 )
1009 .await?;
1010 999
1011 Ok(()) 1000 Ok(())
1012 }) 1001 })
@@ -1033,12 +1022,8 @@ impl EventAcceptancePolicyTests {
1033 Self::create_issue_for_repo(client, &unaccepted_repo, "Orphan Issue")?; 1022 Self::create_issue_for_repo(client, &unaccepted_repo, "Orphan Issue")?;
1034 1023
1035 // 3. Send issue and verify it's REJECTED 1024 // 3. Send issue and verify it's REJECTED
1036 send_and_verify_rejected( 1025 send_and_verify_rejected(client, orphan_issue, "issue referencing unaccepted repo")
1037 client, 1026 .await?;
1038 orphan_issue,
1039 "issue referencing unaccepted repo",
1040 )
1041 .await?;
1042 1027
1043 Ok(()) 1028 Ok(())
1044 }) 1029 })
@@ -1060,8 +1045,7 @@ impl EventAcceptancePolicyTests {
1060 .map_err(|e| format!("Failed to build note: {}", e))?; 1045 .map_err(|e| format!("Failed to build note: {}", e))?;
1061 1046
1062 // 2. Send note and verify it's REJECTED 1047 // 2. Send note and verify it's REJECTED
1063 send_and_verify_rejected(client, orphan_note, "kind 1 with no repo references") 1048 send_and_verify_rejected(client, orphan_note, "kind 1 with no repo references").await?;
1064 .await?;
1065 1049
1066 Ok(()) 1050 Ok(())
1067 }) 1051 })
diff --git a/grasp-audit/src/specs/grasp01/git_clone.rs b/grasp-audit/src/specs/grasp01/git_clone.rs
index 9ee6ed7..95338e4 100644
--- a/grasp-audit/src/specs/grasp01/git_clone.rs
+++ b/grasp-audit/src/specs/grasp01/git_clone.rs
@@ -25,10 +25,7 @@ pub struct GitCloneTests;
25 25
26impl GitCloneTests { 26impl GitCloneTests {
27 /// Run all Git clone tests 27 /// Run all Git clone tests
28 pub async fn run_all( 28 pub async fn run_all(client: &AuditClient, relay_domain: &str) -> crate::AuditResult {
29 client: &AuditClient,
30 relay_domain: &str,
31 ) -> crate::AuditResult {
32 let mut results = crate::AuditResult::new("GRASP-01 Git Clone Tests"); 29 let mut results = crate::AuditResult::new("GRASP-01 Git Clone Tests");
33 30
34 results.add(Self::test_basic_git_clone(client, relay_domain).await); 31 results.add(Self::test_basic_git_clone(client, relay_domain).await);
@@ -45,10 +42,7 @@ impl GitCloneTests {
45 /// 2. Waits for repository creation 42 /// 2. Waits for repository creation
46 /// 3. Attempts to clone the repository using git clone 43 /// 3. Attempts to clone the repository using git clone
47 /// 4. Verifies the clone succeeded 44 /// 4. Verifies the clone succeeded
48 pub async fn test_basic_git_clone( 45 pub async fn test_basic_git_clone(client: &AuditClient, relay_domain: &str) -> TestResult {
49 client: &AuditClient,
50 relay_domain: &str,
51 ) -> TestResult {
52 let test_name = "test_basic_git_clone"; 46 let test_name = "test_basic_git_clone";
53 let ctx = TestContext::new(client); 47 let ctx = TestContext::new(client);
54 48
@@ -61,7 +55,7 @@ impl GitCloneTests {
61 "GRASP-01", 55 "GRASP-01",
62 "Repository must be cloneable via Git HTTP backend", 56 "Repository must be cloneable via Git HTTP backend",
63 ) 57 )
64 .fail(&format!("Failed to create repo fixture: {}", e)) 58 .fail(format!("Failed to create repo fixture: {}", e))
65 } 59 }
66 }; 60 };
67 61
@@ -94,7 +88,7 @@ impl GitCloneTests {
94 "GRASP-01", 88 "GRASP-01",
95 "Repository must be cloneable via Git HTTP backend", 89 "Repository must be cloneable via Git HTTP backend",
96 ) 90 )
97 .fail(&format!("Failed to convert pubkey to npub: {}", e)) 91 .fail(format!("Failed to convert pubkey to npub: {}", e))
98 } 92 }
99 }; 93 };
100 94
@@ -102,7 +96,7 @@ impl GitCloneTests {
102 let temp_base = std::env::temp_dir(); 96 let temp_base = std::env::temp_dir();
103 let clone_dir_name = format!("grasp-test-clone-{}", uuid::Uuid::new_v4()); 97 let clone_dir_name = format!("grasp-test-clone-{}", uuid::Uuid::new_v4());
104 let clone_path = temp_base.join(&clone_dir_name); 98 let clone_path = temp_base.join(&clone_dir_name);
105 99
106 // Ensure clean state 100 // Ensure clean state
107 let _ = fs::remove_dir_all(&clone_path); 101 let _ = fs::remove_dir_all(&clone_path);
108 102
@@ -114,7 +108,7 @@ impl GitCloneTests {
114 .args(["clone", &clone_url, clone_path.to_str().unwrap()]) 108 .args(["clone", &clone_url, clone_path.to_str().unwrap()])
115 .env("GIT_TERMINAL_PROMPT", "0") // Disable password prompts 109 .env("GIT_TERMINAL_PROMPT", "0") // Disable password prompts
116 .output(); 110 .output();
117 111
118 // Clean up on success or failure 112 // Clean up on success or failure
119 let cleanup = || { 113 let cleanup = || {
120 let _ = fs::remove_dir_all(&clone_path); 114 let _ = fs::remove_dir_all(&clone_path);
@@ -129,7 +123,7 @@ impl GitCloneTests {
129 "GRASP-01", 123 "GRASP-01",
130 "Repository must be cloneable via Git HTTP backend", 124 "Repository must be cloneable via Git HTTP backend",
131 ) 125 )
132 .fail(&format!("Failed to execute git clone: {}", e)) 126 .fail(format!("Failed to execute git clone: {}", e));
133 } 127 }
134 }; 128 };
135 129
@@ -141,7 +135,7 @@ impl GitCloneTests {
141 "GRASP-01", 135 "GRASP-01",
142 "Repository must be cloneable via Git HTTP backend", 136 "Repository must be cloneable via Git HTTP backend",
143 ) 137 )
144 .fail(&format!("Git clone failed: {}", stderr)); 138 .fail(format!("Git clone failed: {}", stderr));
145 } 139 }
146 140
147 // Verify clone succeeded by checking for .git directory 141 // Verify clone succeeded by checking for .git directory
@@ -169,10 +163,7 @@ impl GitCloneTests {
169 /// This test verifies: 163 /// This test verifies:
170 /// 1. URLs follow the pattern http://domain/npub/identifier.git 164 /// 1. URLs follow the pattern http://domain/npub/identifier.git
171 /// 2. Invalid URLs are rejected properly 165 /// 2. Invalid URLs are rejected properly
172 pub async fn test_clone_url_format( 166 pub async fn test_clone_url_format(client: &AuditClient, relay_domain: &str) -> TestResult {
173 client: &AuditClient,
174 relay_domain: &str,
175 ) -> TestResult {
176 let test_name = "test_clone_url_format"; 167 let test_name = "test_clone_url_format";
177 let ctx = TestContext::new(client); 168 let ctx = TestContext::new(client);
178 169
@@ -185,7 +176,7 @@ impl GitCloneTests {
185 "GRASP-01", 176 "GRASP-01",
186 "Clone URL must follow correct format", 177 "Clone URL must follow correct format",
187 ) 178 )
188 .fail(&format!("Failed to create repo fixture: {}", e)) 179 .fail(format!("Failed to create repo fixture: {}", e))
189 } 180 }
190 }; 181 };
191 182
@@ -205,7 +196,7 @@ impl GitCloneTests {
205 196
206 // Test valid URL format 197 // Test valid URL format
207 let valid_url = format!("http://{}/{}/{}.git", relay_domain, npub, repo_id); 198 let valid_url = format!("http://{}/{}/{}.git", relay_domain, npub, repo_id);
208 199
209 // Verify URL contains expected components 200 // Verify URL contains expected components
210 if !valid_url.contains(&npub) { 201 if !valid_url.contains(&npub) {
211 return TestResult::new( 202 return TestResult::new(
@@ -229,10 +220,10 @@ impl GitCloneTests {
229 let temp_base = std::env::temp_dir(); 220 let temp_base = std::env::temp_dir();
230 let clone_dir_name = format!("grasp-test-invalid-{}", uuid::Uuid::new_v4()); 221 let clone_dir_name = format!("grasp-test-invalid-{}", uuid::Uuid::new_v4());
231 let clone_path = temp_base.join(&clone_dir_name); 222 let clone_path = temp_base.join(&clone_dir_name);
232 223
233 // Ensure clean state 224 // Ensure clean state
234 let _ = fs::remove_dir_all(&clone_path); 225 let _ = fs::remove_dir_all(&clone_path);
235 226
236 let invalid_url = format!("http://{}/invalid/path", relay_domain); 227 let invalid_url = format!("http://{}/invalid/path", relay_domain);
237 228
238 let output = Command::new("git") 229 let output = Command::new("git")
@@ -287,7 +278,7 @@ impl GitCloneTests {
287 "GRASP-01", 278 "GRASP-01",
288 "MUST include allow-reachable-sha1-in-want and allow-tip-sha1-in-want in advertisement", 279 "MUST include allow-reachable-sha1-in-want and allow-tip-sha1-in-want in advertisement",
289 ) 280 )
290 .fail(&format!("Failed to create repo fixture: {}", e)) 281 .fail(format!("Failed to create repo fixture: {}", e))
291 } 282 }
292 }; 283 };
293 284
@@ -320,7 +311,7 @@ impl GitCloneTests {
320 "GRASP-01", 311 "GRASP-01",
321 "MUST include allow-reachable-sha1-in-want and allow-tip-sha1-in-want in advertisement", 312 "MUST include allow-reachable-sha1-in-want and allow-tip-sha1-in-want in advertisement",
322 ) 313 )
323 .fail(&format!("Failed to convert pubkey to npub: {}", e)) 314 .fail(format!("Failed to convert pubkey to npub: {}", e))
324 } 315 }
325 }; 316 };
326 317
@@ -340,7 +331,7 @@ impl GitCloneTests {
340 "GRASP-01", 331 "GRASP-01",
341 "MUST include allow-reachable-sha1-in-want and allow-tip-sha1-in-want in advertisement", 332 "MUST include allow-reachable-sha1-in-want and allow-tip-sha1-in-want in advertisement",
342 ) 333 )
343 .fail(&format!("HTTP request failed: {}", e)) 334 .fail(format!("HTTP request failed: {}", e))
344 } 335 }
345 }; 336 };
346 337
@@ -350,7 +341,7 @@ impl GitCloneTests {
350 "GRASP-01", 341 "GRASP-01",
351 "MUST include allow-reachable-sha1-in-want and allow-tip-sha1-in-want in advertisement", 342 "MUST include allow-reachable-sha1-in-want and allow-tip-sha1-in-want in advertisement",
352 ) 343 )
353 .fail(&format!( 344 .fail(format!(
354 "info/refs request failed with status: {}", 345 "info/refs request failed with status: {}",
355 response.status() 346 response.status()
356 )); 347 ));
@@ -365,7 +356,7 @@ impl GitCloneTests {
365 "GRASP-01", 356 "GRASP-01",
366 "MUST include allow-reachable-sha1-in-want and allow-tip-sha1-in-want in advertisement", 357 "MUST include allow-reachable-sha1-in-want and allow-tip-sha1-in-want in advertisement",
367 ) 358 )
368 .fail(&format!("Failed to read response body: {}", e)) 359 .fail(format!("Failed to read response body: {}", e))
369 } 360 }
370 }; 361 };
371 362
@@ -399,12 +390,3 @@ impl GitCloneTests {
399 .pass() 390 .pass()
400 } 391 }
401} 392}
402
403#[cfg(test)]
404mod tests {
405 #[test]
406 fn test_module_exists() {
407 // Simple compilation test
408 assert!(true);
409 }
410} \ No newline at end of file
diff --git a/grasp-audit/src/specs/grasp01/mod.rs b/grasp-audit/src/specs/grasp01/mod.rs
index 6f58b96..e16a351 100644
--- a/grasp-audit/src/specs/grasp01/mod.rs
+++ b/grasp-audit/src/specs/grasp01/mod.rs
@@ -26,4 +26,4 @@ pub use git_clone::GitCloneTests;
26pub use nip01_smoke::Nip01SmokeTests; 26pub use nip01_smoke::Nip01SmokeTests;
27pub use nip11_document::Nip11DocumentTests; 27pub use nip11_document::Nip11DocumentTests;
28pub use push_authorization::PushAuthorizationTests; 28pub use push_authorization::PushAuthorizationTests;
29pub use repository_creation::{RepositoryCreationTests}; 29pub use repository_creation::RepositoryCreationTests;
diff --git a/grasp-audit/src/specs/grasp01/nip01_smoke.rs b/grasp-audit/src/specs/grasp01/nip01_smoke.rs
index b16d61a..5161da8 100644
--- a/grasp-audit/src/specs/grasp01/nip01_smoke.rs
+++ b/grasp-audit/src/specs/grasp01/nip01_smoke.rs
@@ -163,27 +163,23 @@ impl Nip01SmokeTests {
163 /// Spec: NIP-01 CLOSE message 163 /// Spec: NIP-01 CLOSE message
164 /// Requirement: Relay MUST support CLOSE to end subscriptions 164 /// Requirement: Relay MUST support CLOSE to end subscriptions
165 pub async fn test_close_subscription(client: &AuditClient) -> TestResult { 165 pub async fn test_close_subscription(client: &AuditClient) -> TestResult {
166 TestResult::new( 166 TestResult::new("close_subscription", "NIP-01", "Can close subscriptions")
167 "close_subscription", 167 .run(|| async {
168 "NIP-01", 168 // For now, we just verify we can query events
169 "Can close subscriptions", 169 // Full subscription management with CLOSE would require
170 ) 170 // lower-level WebSocket access
171 .run(|| async {
172 // For now, we just verify we can query events
173 // Full subscription management with CLOSE would require
174 // lower-level WebSocket access
175 171
176 let filter = Filter::new().kind(Kind::TextNote).limit(1); 172 let filter = Filter::new().kind(Kind::TextNote).limit(1);
177 173
178 let _events = client 174 let _events = client
179 .subscribe(vec![filter], Some(std::time::Duration::from_secs(2))) 175 .subscribe(vec![filter], Some(std::time::Duration::from_secs(2)))
180 .await 176 .await
181 .map_err(|e| format!("Failed to subscribe: {}", e))?; 177 .map_err(|e| format!("Failed to subscribe: {}", e))?;
182 178
183 // If we got here, subscription worked 179 // If we got here, subscription worked
184 Ok(()) 180 Ok(())
185 }) 181 })
186 .await 182 .await
187 } 183 }
188 184
189 /// Test 5: Rejects events with invalid signatures 185 /// Test 5: Rejects events with invalid signatures
diff --git a/grasp-audit/src/specs/grasp01/nip11_document.rs b/grasp-audit/src/specs/grasp01/nip11_document.rs
index bb864f2..51b147d 100644
--- a/grasp-audit/src/specs/grasp01/nip11_document.rs
+++ b/grasp-audit/src/specs/grasp01/nip11_document.rs
@@ -42,7 +42,9 @@ impl Nip11DocumentTests {
42 ) 42 )
43 .run(|| async { 43 .run(|| async {
44 // 1. Extract HTTP(S) URL from client's WebSocket URL 44 // 1. Extract HTTP(S) URL from client's WebSocket URL
45 let ws_url = client.relay_url().await 45 let ws_url = client
46 .relay_url()
47 .await
46 .map_err(|e| format!("Failed to get relay URL: {}", e))?; 48 .map_err(|e| format!("Failed to get relay URL: {}", e))?;
47 let http_url = AuditClient::ws_to_http_url(&ws_url) 49 let http_url = AuditClient::ws_to_http_url(&ws_url)
48 .map_err(|e| format!("Failed to convert WebSocket URL to HTTP: {}", e))?; 50 .map_err(|e| format!("Failed to convert WebSocket URL to HTTP: {}", e))?;
@@ -66,16 +68,18 @@ impl Nip11DocumentTests {
66 } 68 }
67 69
68 // 4. Verify response is valid JSON 70 // 4. Verify response is valid JSON
69 let json_text = response.text().await 71 let json_text = response
72 .text()
73 .await
70 .map_err(|e| format!("Failed to read response body: {}", e))?; 74 .map_err(|e| format!("Failed to read response body: {}", e))?;
71 75
72 let doc: serde_json::Value = serde_json::from_str(&json_text) 76 let doc: serde_json::Value = serde_json::from_str(&json_text)
73 .map_err(|e| format!("Response is not valid JSON: {}", e))?; 77 .map_err(|e| format!("Response is not valid JSON: {}", e))?;
74 78
75 // 5. Verify has required NIP-11 fields 79 // 5. Verify has required NIP-11 fields
76 let required_fields = ["name", "description", "software", "version"]; 80 let required_fields = ["name", "description", "software", "version"];
77 for field in &required_fields { 81 for field in &required_fields {
78 if !doc.get(field).is_some() { 82 if doc.get(field).is_none() {
79 return Err(format!("Missing required NIP-11 field: {}", field)); 83 return Err(format!("Missing required NIP-11 field: {}", field));
80 } 84 }
81 } 85 }
@@ -97,7 +101,9 @@ impl Nip11DocumentTests {
97 ) 101 )
98 .run(|| async { 102 .run(|| async {
99 // 1. Fetch NIP-11 document 103 // 1. Fetch NIP-11 document
100 let ws_url = client.relay_url().await 104 let ws_url = client
105 .relay_url()
106 .await
101 .map_err(|e| format!("Failed to get relay URL: {}", e))?; 107 .map_err(|e| format!("Failed to get relay URL: {}", e))?;
102 let http_url = AuditClient::ws_to_http_url(&ws_url) 108 let http_url = AuditClient::ws_to_http_url(&ws_url)
103 .map_err(|e| format!("Failed to convert WebSocket URL to HTTP: {}", e))?; 109 .map_err(|e| format!("Failed to convert WebSocket URL to HTTP: {}", e))?;
@@ -110,18 +116,22 @@ impl Nip11DocumentTests {
110 .await 116 .await
111 .map_err(|e| format!("Failed to fetch NIP-11 document: {}", e))?; 117 .map_err(|e| format!("Failed to fetch NIP-11 document: {}", e))?;
112 118
113 let json_text = response.text().await 119 let json_text = response
120 .text()
121 .await
114 .map_err(|e| format!("Failed to read response body: {}", e))?; 122 .map_err(|e| format!("Failed to read response body: {}", e))?;
115 123
116 let doc: serde_json::Value = serde_json::from_str(&json_text) 124 let doc: serde_json::Value = serde_json::from_str(&json_text)
117 .map_err(|e| format!("Response is not valid JSON: {}", e))?; 125 .map_err(|e| format!("Response is not valid JSON: {}", e))?;
118 126
119 // 2. Verify `supported_grasps` field exists 127 // 2. Verify `supported_grasps` field exists
120 let supported_grasps = doc.get("supported_grasps") 128 let supported_grasps = doc
129 .get("supported_grasps")
121 .ok_or_else(|| "Missing required field: supported_grasps".to_string())?; 130 .ok_or_else(|| "Missing required field: supported_grasps".to_string())?;
122 131
123 // 3. Verify it's a JSON array 132 // 3. Verify it's a JSON array
124 let grasps_array = supported_grasps.as_array() 133 let grasps_array = supported_grasps
134 .as_array()
125 .ok_or_else(|| "supported_grasps must be an array".to_string())?; 135 .ok_or_else(|| "supported_grasps must be an array".to_string())?;
126 136
127 // 4. Verify array includes "GRASP-01" 137 // 4. Verify array includes "GRASP-01"
@@ -140,7 +150,7 @@ impl Nip11DocumentTests {
140 // 5. Verify format: each entry should match pattern "GRASP-\d{2}" 150 // 5. Verify format: each entry should match pattern "GRASP-\d{2}"
141 let grasp_pattern = regex::Regex::new(r"^GRASP-\d{2}$") 151 let grasp_pattern = regex::Regex::new(r"^GRASP-\d{2}$")
142 .map_err(|e| format!("Failed to compile regex: {}", e))?; 152 .map_err(|e| format!("Failed to compile regex: {}", e))?;
143 153
144 for grasp in &grasp_strings { 154 for grasp in &grasp_strings {
145 if !grasp_pattern.is_match(grasp) { 155 if !grasp_pattern.is_match(grasp) {
146 return Err(format!( 156 return Err(format!(
@@ -167,7 +177,9 @@ impl Nip11DocumentTests {
167 ) 177 )
168 .run(|| async { 178 .run(|| async {
169 // 1. Fetch NIP-11 document 179 // 1. Fetch NIP-11 document
170 let ws_url = client.relay_url().await 180 let ws_url = client
181 .relay_url()
182 .await
171 .map_err(|e| format!("Failed to get relay URL: {}", e))?; 183 .map_err(|e| format!("Failed to get relay URL: {}", e))?;
172 let http_url = AuditClient::ws_to_http_url(&ws_url) 184 let http_url = AuditClient::ws_to_http_url(&ws_url)
173 .map_err(|e| format!("Failed to convert WebSocket URL to HTTP: {}", e))?; 185 .map_err(|e| format!("Failed to convert WebSocket URL to HTTP: {}", e))?;
@@ -180,18 +192,22 @@ impl Nip11DocumentTests {
180 .await 192 .await
181 .map_err(|e| format!("Failed to fetch NIP-11 document: {}", e))?; 193 .map_err(|e| format!("Failed to fetch NIP-11 document: {}", e))?;
182 194
183 let json_text = response.text().await 195 let json_text = response
196 .text()
197 .await
184 .map_err(|e| format!("Failed to read response body: {}", e))?; 198 .map_err(|e| format!("Failed to read response body: {}", e))?;
185 199
186 let doc: serde_json::Value = serde_json::from_str(&json_text) 200 let doc: serde_json::Value = serde_json::from_str(&json_text)
187 .map_err(|e| format!("Response is not valid JSON: {}", e))?; 201 .map_err(|e| format!("Response is not valid JSON: {}", e))?;
188 202
189 // 2. Verify `repo_acceptance_criteria` field exists 203 // 2. Verify `repo_acceptance_criteria` field exists
190 let criteria = doc.get("repo_acceptance_criteria") 204 let criteria = doc
205 .get("repo_acceptance_criteria")
191 .ok_or_else(|| "Missing required field: repo_acceptance_criteria".to_string())?; 206 .ok_or_else(|| "Missing required field: repo_acceptance_criteria".to_string())?;
192 207
193 // 3. Verify it's a string 208 // 3. Verify it's a string
194 let criteria_str = criteria.as_str() 209 let criteria_str = criteria
210 .as_str()
195 .ok_or_else(|| "repo_acceptance_criteria must be a string".to_string())?; 211 .ok_or_else(|| "repo_acceptance_criteria must be a string".to_string())?;
196 212
197 // 4. Verify non-empty 213 // 4. Verify non-empty
@@ -216,7 +232,9 @@ impl Nip11DocumentTests {
216 ) 232 )
217 .run(|| async { 233 .run(|| async {
218 // 1. Fetch NIP-11 document 234 // 1. Fetch NIP-11 document
219 let ws_url = client.relay_url().await 235 let ws_url = client
236 .relay_url()
237 .await
220 .map_err(|e| format!("Failed to get relay URL: {}", e))?; 238 .map_err(|e| format!("Failed to get relay URL: {}", e))?;
221 let http_url = AuditClient::ws_to_http_url(&ws_url) 239 let http_url = AuditClient::ws_to_http_url(&ws_url)
222 .map_err(|e| format!("Failed to convert WebSocket URL to HTTP: {}", e))?; 240 .map_err(|e| format!("Failed to convert WebSocket URL to HTTP: {}", e))?;
@@ -229,16 +247,19 @@ impl Nip11DocumentTests {
229 .await 247 .await
230 .map_err(|e| format!("Failed to fetch NIP-11 document: {}", e))?; 248 .map_err(|e| format!("Failed to fetch NIP-11 document: {}", e))?;
231 249
232 let json_text = response.text().await 250 let json_text = response
251 .text()
252 .await
233 .map_err(|e| format!("Failed to read response body: {}", e))?; 253 .map_err(|e| format!("Failed to read response body: {}", e))?;
234 254
235 let doc: serde_json::Value = serde_json::from_str(&json_text) 255 let doc: serde_json::Value = serde_json::from_str(&json_text)
236 .map_err(|e| format!("Response is not valid JSON: {}", e))?; 256 .map_err(|e| format!("Response is not valid JSON: {}", e))?;
237 257
238 // 2. Check if `curation` field exists 258 // 2. Check if `curation` field exists
239 if let Some(curation) = doc.get("curation") { 259 if let Some(curation) = doc.get("curation") {
240 // 3. If present: verify it's a non-empty string 260 // 3. If present: verify it's a non-empty string
241 let curation_str = curation.as_str() 261 let curation_str = curation
262 .as_str()
242 .ok_or_else(|| "curation field must be a string when present".to_string())?; 263 .ok_or_else(|| "curation field must be a string when present".to_string())?;
243 264
244 if curation_str.trim().is_empty() { 265 if curation_str.trim().is_empty() {
@@ -284,4 +305,4 @@ mod tests {
284 // Don't assert all passed yet - tests not implemented 305 // Don't assert all passed yet - tests not implemented
285 // assert!(results.all_passed(), "Some GRASP-01 NIP-11 document tests failed"); 306 // assert!(results.all_passed(), "Some GRASP-01 NIP-11 document tests failed");
286 } 307 }
287} \ No newline at end of file 308}
diff --git a/grasp-audit/src/specs/grasp01/push_authorization.rs b/grasp-audit/src/specs/grasp01/push_authorization.rs
index d8652ae..24eae1d 100644
--- a/grasp-audit/src/specs/grasp01/push_authorization.rs
+++ b/grasp-audit/src/specs/grasp01/push_authorization.rs
@@ -351,10 +351,7 @@ async fn setup_repo_with_wrong_commit_pushed(
351/// IMPORTANT: We must publish the EXACT same event that was used during setup, 351/// IMPORTANT: We must publish the EXACT same event that was used during setup,
352/// otherwise the event ID won't match the refs/nostr/<event-id> ref that was pushed. 352/// otherwise the event ID won't match the refs/nostr/<event-id> ref that was pushed.
353#[allow(dead_code)] 353#[allow(dead_code)]
354async fn publish_pr_event_and_wait( 354async fn publish_pr_event_and_wait(ctx: &TestContext<'_>, pr_event: &Event) -> Result<(), String> {
355 ctx: &TestContext<'_>,
356 pr_event: &Event,
357) -> Result<(), String> {
358 // Publish the exact same PR event that was created during setup 355 // Publish the exact same PR event that was created during setup
359 ctx.client() 356 ctx.client()
360 .send_event(pr_event.clone()) 357 .send_event(pr_event.clone())
@@ -1892,11 +1889,6 @@ impl PushAuthorizationTests {
1892mod tests { 1889mod tests {
1893 use super::*; 1890 use super::*;
1894 1891
1895 #[test]
1896 fn test_module_exists() {
1897 assert!(true);
1898 }
1899
1900 /// Test to discover the PR test commit hash 1892 /// Test to discover the PR test commit hash
1901 /// 1893 ///
1902 /// This test creates a deterministic commit with PR-specific parameters 1894 /// This test creates a deterministic commit with PR-specific parameters
diff --git a/grasp-audit/src/specs/grasp01/repository_creation.rs b/grasp-audit/src/specs/grasp01/repository_creation.rs
index 63b3dee..0b3eed5 100644
--- a/grasp-audit/src/specs/grasp01/repository_creation.rs
+++ b/grasp-audit/src/specs/grasp01/repository_creation.rs
@@ -23,10 +23,7 @@ pub struct RepositoryCreationTests;
23 23
24impl RepositoryCreationTests { 24impl RepositoryCreationTests {
25 /// Run all repository creation tests 25 /// Run all repository creation tests
26 pub async fn run_all( 26 pub async fn run_all(client: &AuditClient, relay_domain: &str) -> crate::AuditResult {
27 client: &AuditClient,
28 relay_domain: &str,
29 ) -> crate::AuditResult {
30 let mut results = crate::AuditResult::new("GRASP-01 Repository Creation Tests"); 27 let mut results = crate::AuditResult::new("GRASP-01 Repository Creation Tests");
31 28
32 results.add(Self::test_bare_repo_created_on_announcement(client, relay_domain).await); 29 results.add(Self::test_bare_repo_created_on_announcement(client, relay_domain).await);
@@ -58,7 +55,7 @@ impl RepositoryCreationTests {
58 "GRASP-01", 55 "GRASP-01",
59 "Bare repository must be created and accessible via Smart HTTP when announcement is accepted", 56 "Bare repository must be created and accessible via Smart HTTP when announcement is accepted",
60 ) 57 )
61 .fail(&format!("Failed to create repo fixture: {}", e)) 58 .fail(format!("Failed to create repo fixture: {}", e))
62 } 59 }
63 }; 60 };
64 61
@@ -91,7 +88,7 @@ impl RepositoryCreationTests {
91 "GRASP-01", 88 "GRASP-01",
92 "Bare repository must be created and accessible via Smart HTTP when announcement is accepted", 89 "Bare repository must be created and accessible via Smart HTTP when announcement is accepted",
93 ) 90 )
94 .fail(&format!("Failed to convert pubkey to npub: {}", e)) 91 .fail(format!("Failed to convert pubkey to npub: {}", e))
95 } 92 }
96 }; 93 };
97 94
@@ -102,7 +99,7 @@ impl RepositoryCreationTests {
102 "GRASP-01", 99 "GRASP-01",
103 "Bare repository must be created and accessible via Smart HTTP when announcement is accepted", 100 "Bare repository must be created and accessible via Smart HTTP when announcement is accepted",
104 ) 101 )
105 .fail(&format!("Repository not accessible via HTTP: {}", e)); 102 .fail(format!("Repository not accessible via HTTP: {}", e));
106 } 103 }
107 104
108 TestResult::new( 105 TestResult::new(
@@ -159,12 +156,3 @@ async fn check_repo_accessible_via_http(
159 156
160 Ok(()) 157 Ok(())
161} 158}
162
163#[cfg(test)]
164mod tests {
165 #[test]
166 fn test_module_exists() {
167 // Simple compilation test
168 assert!(true);
169 }
170}