upleb.uk

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

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AGENTS.md35
-rw-r--r--grasp-audit/src/client.rs22
-rw-r--r--grasp-audit/src/specs/grasp01_nostr_relay.rs53
3 files changed, 88 insertions, 22 deletions
diff --git a/AGENTS.md b/AGENTS.md
index ed9c97d..ec1ec60 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -33,8 +33,8 @@ nix-shell --run "cargo build"
33**Integration tests require relay running:** 33**Integration tests require relay running:**
34 34
35```bash 35```bash
36# Start ngit-relay first (choose any available port, example uses 18081) 36# Start ngit-relay first (use any available port to avoid conflicts)
37docker run --rm -p 18081:8081 -e NGIT_BIND_ADDRESS=0.0.0.0:8081 ghcr.io/danconwaydev/ngit-relay:latest 37docker run --rm -p 18081:8081 ghcr.io/danconwaydev/ngit-relay:latest
38 38
39# From grasp-audit directory, set RELAY_URL to match your port 39# From grasp-audit directory, set RELAY_URL to match your port
40RELAY_URL="ws://localhost:18081" nix develop -c cargo test --lib test_grasp01_nostr_relay_against_relay -- --ignored --nocapture 40RELAY_URL="ws://localhost:18081" nix develop -c cargo test --lib test_grasp01_nostr_relay_against_relay -- --ignored --nocapture
@@ -42,6 +42,8 @@ RELAY_URL="ws://localhost:18081" nix develop -c cargo test --lib test_grasp01_no
42 42
43Tests marked `#[ignore]` need relay - unit tests don't. 43Tests marked `#[ignore]` need relay - unit tests don't.
44 44
45**Note:** Always use a random available port for the relay to avoid conflicts with existing services.
46
45### Running Single Test 47### Running Single Test
46 48
47```bash 49```bash
@@ -49,6 +51,32 @@ Tests marked `#[ignore]` need relay - unit tests don't.
49nix develop -c cargo test --lib specific_test_name -- --nocapture 51nix develop -c cargo test --lib specific_test_name -- --nocapture
50``` 52```
51 53
54### Quick Test Verification
55
56To verify GRASP-01 compliance tests are working correctly:
57
58```bash
59cd grasp-audit && RELAY_URL="ws://localhost:18081" nix develop -c cargo test --lib test_grasp01_nostr_relay_against_relay -- --ignored --nocapture 2>&1 | tail -60
60```
61
62**Expected Output:**
63- 2-3 tests passing
64- 15 tests showing "Not implemented yet"
65
66### Troubleshooting
67
68**Buffer Size Errors:**
69If you see mpsc channel buffer size panics on first test run, this is usually transient. Simply run the tests again.
70
71**Verify Relay is Running:**
72Check if relay is accessible before running tests:
73```bash
74nak req -l 1 ws://localhost:18081 # Replace port with your chosen port
75```
76
77**Port Conflicts:**
78Always use a random available port to avoid conflicts with existing services. If a port is busy, choose a different one for docker.
79
52## Code Patterns 80## Code Patterns
53 81
54### nostr-sdk 0.43 Breaking Changes (vs 0.35) 82### nostr-sdk 0.43 Breaking Changes (vs 0.35)
@@ -133,6 +161,9 @@ cd grasp-audit && RELAY_URL="ws://localhost:18081" nix develop -c cargo test --i
133# Run single test 161# Run single test
134cd grasp-audit && nix develop -c cargo test --lib test_name -- --nocapture 162cd grasp-audit && nix develop -c cargo test --lib test_name -- --nocapture
135 163
164# Verify GRASP-01 tests (cleaner output)
165cd grasp-audit && RELAY_URL="ws://localhost:18081" nix develop -c cargo test --lib test_grasp01_nostr_relay_against_relay -- --ignored --nocapture 2>&1 | tail -60
166
136# Check session files 167# Check session files
137ls work/ # Should only have README.md when clean 168ls work/ # Should only have README.md when clean
138``` 169```
diff --git a/grasp-audit/src/client.rs b/grasp-audit/src/client.rs
index 4831d3f..b80b59f 100644
--- a/grasp-audit/src/client.rs
+++ b/grasp-audit/src/client.rs
@@ -24,11 +24,12 @@ impl AuditClient {
24 24
25 // Wait for connection to establish (with retries) 25 // Wait for connection to establish (with retries)
26 let mut attempts = 0; 26 let mut attempts = 0;
27 let mut connected = false;
27 while attempts < 20 { 28 while attempts < 20 {
28 tokio::time::sleep(Duration::from_millis(100)).await; 29 tokio::time::sleep(Duration::from_millis(100)).await;
29 30
30 let relays = client.relays().await; 31 let relays = client.relays().await;
31 let connected = relays.values().any(|r| r.is_connected()); 32 connected = relays.values().any(|r| r.is_connected());
32 33
33 if connected { 34 if connected {
34 break; 35 break;
@@ -37,6 +38,25 @@ impl AuditClient {
37 attempts += 1; 38 attempts += 1;
38 } 39 }
39 40
41 // Verify we actually connected
42 if !connected {
43 return Err(anyhow!(
44 "Failed to connect to relay at '{}'\n\
45 \n\
46 Possible causes:\n\
47 • Relay is not running at this address\n\
48 • Network connectivity issues\n\
49 • Incorrect URL or port\n\
50 \n\
51 To start ngit-relay for testing:\n\
52 docker run --rm -p 18081:8081 ghcr.io/danconwaydev/ngit-relay:latest\n\
53 \n\
54 Or use the test script:\n\
55 cd grasp-audit && ./test-ngit-relay.sh",
56 relay_url
57 ));
58 }
59
40 // Give it a bit more time to stabilize 60 // Give it a bit more time to stabilize
41 tokio::time::sleep(Duration::from_millis(200)).await; 61 tokio::time::sleep(Duration::from_millis(200)).await;
42 62
diff --git a/grasp-audit/src/specs/grasp01_nostr_relay.rs b/grasp-audit/src/specs/grasp01_nostr_relay.rs
index 7c4ef1e..5a93672 100644
--- a/grasp-audit/src/specs/grasp01_nostr_relay.rs
+++ b/grasp-audit/src/specs/grasp01_nostr_relay.rs
@@ -82,7 +82,7 @@ impl Grasp01NostrRelayTests {
82 82
83 // Get npub for clone URL 83 // Get npub for clone URL
84 let npub = client.public_key().to_bech32() 84 let npub = client.public_key().to_bech32()
85 .map_err(|e| format!("Failed to convert pubkey to npub: {}", e))?; 85 .map_err(|e| format!("Failed to convert public key to bech32 npub format: {}", e))?;
86 86
87 // Build kind 30617 repository announcement 87 // Build kind 30617 repository announcement
88 let event = client.event_builder(Kind::GitRepoAnnouncement, "") 88 let event = client.event_builder(Kind::GitRepoAnnouncement, "")
@@ -92,11 +92,11 @@ impl Grasp01NostrRelayTests {
92 .tag(Tag::custom(TagKind::Custom("clone".into()), vec![format!("{}/{}/{}.git", http_url, npub, repo_id)])) 92 .tag(Tag::custom(TagKind::Custom("clone".into()), vec![format!("{}/{}/{}.git", http_url, npub, repo_id)]))
93 .tag(Tag::custom(TagKind::Custom("relays".into()), vec![relay_url.clone()])) 93 .tag(Tag::custom(TagKind::Custom("relays".into()), vec![relay_url.clone()]))
94 .build(client.keys()) 94 .build(client.keys())
95 .map_err(|e| format!("Failed to build event: {}", e))?; 95 .map_err(|e| format!("Failed to build repository announcement event (kind 30617): {}", e))?;
96 96
97 // Send the event 97 // Send the event
98 let event_id = client.send_event(event.clone()).await 98 let event_id = client.send_event(event.clone()).await
99 .map_err(|e| format!("Failed to send event: {}", e))?; 99 .map_err(|e| format!("Failed to send repository announcement to relay: {}", e))?;
100 100
101 // Query back to verify it was accepted and stored 101 // Query back to verify it was accepted and stored
102 let filter = Filter::new() 102 let filter = Filter::new()
@@ -105,17 +105,23 @@ impl Grasp01NostrRelayTests {
105 .identifier(&repo_id); 105 .identifier(&repo_id);
106 106
107 let events = client.query(filter).await 107 let events = client.query(filter).await
108 .map_err(|e| format!("Failed to query events: {}", e))?; 108 .map_err(|e| format!("Failed to query events from relay: {}", e))?;
109 109
110 // Verify we got the event back 110 // Verify we got the event back
111 if events.is_empty() { 111 if events.is_empty() {
112 return Err("Event was not stored in relay (possibly rejected)".to_string()); 112 return Err(format!(
113 "Event was not stored in relay (possibly rejected). Event ID: {}, Repo ID: {}",
114 event_id, repo_id
115 ));
113 } 116 }
114 117
115 // Verify it's the same event 118 // Verify it's the same event
116 let stored_event = events.iter() 119 let stored_event = events.iter()
117 .find(|e| e.id == event_id) 120 .find(|e| e.id == event_id)
118 .ok_or("Stored event ID doesn't match sent event")?; 121 .ok_or(format!(
122 "Stored event ID doesn't match sent event. Expected: {}, Got {} events",
123 event_id, events.len()
124 ))?;
119 125
120 // Verify key tags are present 126 // Verify key tags are present
121 let has_clone_tag = stored_event.tags.iter() 127 let has_clone_tag = stored_event.tags.iter()
@@ -158,7 +164,7 @@ impl Grasp01NostrRelayTests {
158 let relay_url = client.client().relays().await 164 let relay_url = client.client().relays().await
159 .keys() 165 .keys()
160 .next() 166 .next()
161 .ok_or("No relay connected")? 167 .ok_or("No relay connected - client has no active relay connections")?
162 .to_string(); 168 .to_string();
163 169
164 // Create unique repository identifier 170 // Create unique repository identifier
@@ -186,11 +192,15 @@ impl Grasp01NostrRelayTests {
186 .identifier(&repo_id); 192 .identifier(&repo_id);
187 193
188 let events = client.query(filter).await 194 let events = client.query(filter).await
189 .map_err(|e| format!("Failed to query events: {}", e))?; 195 .map_err(|e| format!("Failed to query events from relay: {}", e))?;
190 196
191 // Verify event was rejected (not stored) 197 // Verify event was rejected (not stored)
192 if events.iter().any(|e| e.id == event_id) { 198 if events.iter().any(|e| e.id == event_id) {
193 return Err("Relay accepted announcement without service in clone tag - should reject".to_string()); 199 return Err(format!(
200 "Relay incorrectly accepted announcement without service in clone tag. \
201 Event ID: {}, Clone URL: https://github.com/user/repo.git (should require {})",
202 event_id, relay_url
203 ));
194 } 204 }
195 205
196 Ok(()) 206 Ok(())
@@ -650,16 +660,21 @@ mod tests {
650 use super::*; 660 use super::*;
651 use crate::AuditConfig; 661 use crate::AuditConfig;
652 662
653 #[tokio::test] 663#[tokio::test]
654 #[ignore] // Requires running relay 664#[ignore] // Requires running relay
655 async fn test_grasp01_nostr_relay_against_relay() { 665async fn test_grasp01_nostr_relay_against_relay() {
656 // Read relay URL from environment variable - must be supplied 666 // Read relay URL from environment variable - must be supplied
657 let relay_url = std::env::var("RELAY_URL")?; 667 let relay_url = std::env::var("RELAY_URL")
658 668 .expect("RELAY_URL environment variable must be set. Example: RELAY_URL=ws://localhost:18081");
659 let config = AuditConfig::ci(); 669
660 let client = AuditClient::new(&relay_url, config) 670 let config = AuditConfig::ci();
661 .await 671 let client = AuditClient::new(&relay_url, config)
662 .expect("Failed to connect to relay"); 672 .await
673 .expect(&format!(
674 "Failed to connect to relay at {}. Ensure relay is running and accessible. \
675 Try: docker run --rm -p 18081:8081 ghcr.io/danconwaydev/ngit-relay:latest",
676 relay_url
677 ));
663 678
664 let results = Grasp01NostrRelayTests::run_all(&client).await; 679 let results = Grasp01NostrRelayTests::run_all(&client).await;
665 results.print_report(); 680 results.print_report();