test-sync.sh raw
1 #!/bin/bash
2 #
3 # Negentropy Interop Test Script
4 # Tests NIP-77 negentropy sync between strfry and orly
5 #
6 # Usage:
7 # ./test-sync.sh
8 #
9 # Prerequisites:
10 # - docker compose up -d (containers running)
11 # - websocat and jq installed (for event generation)
12 #
13
14 set -e
15
16 STRFRY_URL="ws://localhost:7777"
17 ORLY_URL="ws://localhost:3334"
18 TEST_EVENTS=10
19 PASSED=0
20 FAILED=0
21
22 # Colors for output
23 RED='\033[0;31m'
24 GREEN='\033[0;32m'
25 YELLOW='\033[1;33m'
26 NC='\033[0m' # No Color
27
28 log_info() {
29 echo -e "${YELLOW}[INFO]${NC} $1"
30 }
31
32 log_pass() {
33 echo -e "${GREEN}[PASS]${NC} $1"
34 ((PASSED++))
35 }
36
37 log_fail() {
38 echo -e "${RED}[FAIL]${NC} $1"
39 ((FAILED++))
40 }
41
42 # Generate a test private key (for signing events)
43 # This is a fixed test key - DO NOT use in production
44 TEST_PRIVKEY="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
45 TEST_PUBKEY="a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1"
46
47 # Check if services are running
48 check_services() {
49 log_info "Checking if services are running..."
50
51 if ! curl -s http://localhost:7777 > /dev/null 2>&1; then
52 log_fail "strfry is not running on port 7777"
53 exit 1
54 fi
55 log_pass "strfry is running"
56
57 if ! curl -s http://localhost:3334 > /dev/null 2>&1; then
58 log_fail "orly is not running on port 3334"
59 exit 1
60 fi
61 log_pass "orly is running"
62 }
63
64 # Generate and send a test event to a relay
65 # Uses websocat if available, otherwise uses netcat
66 send_event() {
67 local relay_url=$1
68 local kind=$2
69 local content=$3
70 local timestamp=$(date +%s)
71
72 # Create a simple unsigned event (strfry will accept it in test mode)
73 # For real testing, we'd need proper signing
74 local event_json=$(cat <<EOF
75 ["EVENT", {
76 "id": "$(echo -n "${timestamp}${content}" | sha256sum | cut -d' ' -f1)",
77 "pubkey": "${TEST_PUBKEY}",
78 "created_at": ${timestamp},
79 "kind": ${kind},
80 "tags": [],
81 "content": "${content}",
82 "sig": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
83 }]
84 EOF
85 )
86
87 echo "$event_json" | websocat -n1 "$relay_url" 2>/dev/null || true
88 }
89
90 # Count events on a relay matching a filter
91 count_events() {
92 local relay_url=$1
93 local filter=$2
94
95 # Send REQ and count EVENT responses before EOSE
96 local count=$(echo "[\"REQ\", \"count\", $filter]" | \
97 timeout 5 websocat -n "$relay_url" 2>/dev/null | \
98 grep -c '"EVENT"' || echo "0")
99
100 echo "$count"
101 }
102
103 # Test 1: Seed strfry with events
104 test_seed_strfry() {
105 log_info "Test 1: Seeding strfry with $TEST_EVENTS test events..."
106
107 for i in $(seq 1 $TEST_EVENTS); do
108 send_event "$STRFRY_URL" 1 "Test event $i from strfry seed"
109 sleep 0.1
110 done
111
112 sleep 2 # Wait for events to be processed
113
114 local count=$(count_events "$STRFRY_URL" '{"kinds": [1], "limit": 100}')
115 log_info "strfry event count: $count"
116
117 if [ "$count" -ge "$TEST_EVENTS" ]; then
118 log_pass "strfry seeded with $count events"
119 else
120 log_fail "strfry only has $count events (expected >= $TEST_EVENTS)"
121 fi
122 }
123
124 # Test 2: Run orly sync to pull from strfry
125 test_orly_sync_from_strfry() {
126 log_info "Test 2: Running orly sync from strfry (strfry -> orly)..."
127
128 # Use the sync-runner container to run sync
129 docker compose exec -T sync-runner /app/orly sync ws://strfry:7777 --filter '{"kinds": [1]}' --dir down -v
130
131 sleep 3 # Wait for sync to complete
132
133 local orly_count=$(count_events "$ORLY_URL" '{"kinds": [1], "limit": 100}')
134 log_info "orly event count after sync: $orly_count"
135
136 if [ "$orly_count" -ge "$TEST_EVENTS" ]; then
137 log_pass "orly synced $orly_count events from strfry"
138 else
139 log_fail "orly only synced $orly_count events (expected >= $TEST_EVENTS)"
140 fi
141 }
142
143 # Test 3: Seed orly with new events and sync back to strfry
144 test_orly_sync_to_strfry() {
145 log_info "Test 3: Seeding orly and syncing back to strfry (orly -> strfry)..."
146
147 local new_events=5
148 for i in $(seq 1 $new_events); do
149 send_event "$ORLY_URL" 1 "Test event $i from orly for reverse sync"
150 sleep 0.1
151 done
152
153 sleep 2
154
155 # Check orly has the new events
156 local orly_count=$(count_events "$ORLY_URL" '{"kinds": [1], "limit": 100}')
157 log_info "orly event count: $orly_count"
158
159 # Run strfry sync from orly (using strfry's sync command)
160 # Note: strfry sync command format is: strfry sync <url> --filter <filter> --dir down
161 docker compose exec -T strfry /app/strfry sync ws://orly:3334 --filter '{"kinds": [1]}' --dir down || true
162
163 sleep 3
164
165 local strfry_count=$(count_events "$STRFRY_URL" '{"kinds": [1], "limit": 100}')
166 log_info "strfry event count after reverse sync: $strfry_count"
167
168 local expected=$((TEST_EVENTS + new_events))
169 if [ "$strfry_count" -ge "$expected" ]; then
170 log_pass "strfry has $strfry_count events after bidirectional sync"
171 else
172 log_fail "strfry only has $strfry_count events (expected >= $expected)"
173 fi
174 }
175
176 # Test 4: Verify event consistency
177 test_event_consistency() {
178 log_info "Test 4: Verifying event consistency between relays..."
179
180 local strfry_count=$(count_events "$STRFRY_URL" '{"kinds": [1], "limit": 100}')
181 local orly_count=$(count_events "$ORLY_URL" '{"kinds": [1], "limit": 100}')
182
183 log_info "strfry: $strfry_count events, orly: $orly_count events"
184
185 # After bidirectional sync, both should have similar counts
186 local diff=$((strfry_count - orly_count))
187 if [ "${diff#-}" -le 2 ]; then # Allow small difference
188 log_pass "Event counts are consistent (diff: $diff)"
189 else
190 log_fail "Event counts differ by $diff"
191 fi
192 }
193
194 # Run all tests
195 main() {
196 echo "========================================"
197 echo "Negentropy Interop Test Suite"
198 echo "strfry <-> orly (NIP-77)"
199 echo "========================================"
200 echo
201
202 check_services
203 echo
204
205 test_seed_strfry
206 echo
207
208 test_orly_sync_from_strfry
209 echo
210
211 test_orly_sync_to_strfry
212 echo
213
214 test_event_consistency
215 echo
216
217 echo "========================================"
218 echo "Results: $PASSED passed, $FAILED failed"
219 echo "========================================"
220
221 if [ "$FAILED" -gt 0 ]; then
222 exit 1
223 fi
224 }
225
226 main "$@"
227