You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

226 lines
6.2 KiB

#!/bin/bash
#
# Negentropy Interop Test Script
# Tests NIP-77 negentropy sync between strfry and orly
#
# Usage:
# ./test-sync.sh
#
# Prerequisites:
# - docker compose up -d (containers running)
# - websocat and jq installed (for event generation)
#
set -e
STRFRY_URL="ws://localhost:7777"
ORLY_URL="ws://localhost:3334"
TEST_EVENTS=10
PASSED=0
FAILED=0
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
log_info() {
echo -e "${YELLOW}[INFO]${NC} $1"
}
log_pass() {
echo -e "${GREEN}[PASS]${NC} $1"
((PASSED++))
}
log_fail() {
echo -e "${RED}[FAIL]${NC} $1"
((FAILED++))
}
# Generate a test private key (for signing events)
# This is a fixed test key - DO NOT use in production
TEST_PRIVKEY="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
TEST_PUBKEY="a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1"
# Check if services are running
check_services() {
log_info "Checking if services are running..."
if ! curl -s http://localhost:7777 > /dev/null 2>&1; then
log_fail "strfry is not running on port 7777"
exit 1
fi
log_pass "strfry is running"
if ! curl -s http://localhost:3334 > /dev/null 2>&1; then
log_fail "orly is not running on port 3334"
exit 1
fi
log_pass "orly is running"
}
# Generate and send a test event to a relay
# Uses websocat if available, otherwise uses netcat
send_event() {
local relay_url=$1
local kind=$2
local content=$3
local timestamp=$(date +%s)
# Create a simple unsigned event (strfry will accept it in test mode)
# For real testing, we'd need proper signing
local event_json=$(cat <<EOF
["EVENT", {
"id": "$(echo -n "${timestamp}${content}" | sha256sum | cut -d' ' -f1)",
"pubkey": "${TEST_PUBKEY}",
"created_at": ${timestamp},
"kind": ${kind},
"tags": [],
"content": "${content}",
"sig": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
}]
EOF
)
echo "$event_json" | websocat -n1 "$relay_url" 2>/dev/null || true
}
# Count events on a relay matching a filter
count_events() {
local relay_url=$1
local filter=$2
# Send REQ and count EVENT responses before EOSE
local count=$(echo "[\"REQ\", \"count\", $filter]" | \
timeout 5 websocat -n "$relay_url" 2>/dev/null | \
grep -c '"EVENT"' || echo "0")
echo "$count"
}
# Test 1: Seed strfry with events
test_seed_strfry() {
log_info "Test 1: Seeding strfry with $TEST_EVENTS test events..."
for i in $(seq 1 $TEST_EVENTS); do
send_event "$STRFRY_URL" 1 "Test event $i from strfry seed"
sleep 0.1
done
sleep 2 # Wait for events to be processed
local count=$(count_events "$STRFRY_URL" '{"kinds": [1], "limit": 100}')
log_info "strfry event count: $count"
if [ "$count" -ge "$TEST_EVENTS" ]; then
log_pass "strfry seeded with $count events"
else
log_fail "strfry only has $count events (expected >= $TEST_EVENTS)"
fi
}
# Test 2: Run orly sync to pull from strfry
test_orly_sync_from_strfry() {
log_info "Test 2: Running orly sync from strfry (strfry -> orly)..."
# Use the sync-runner container to run sync
docker compose exec -T sync-runner /app/orly sync ws://strfry:7777 --filter '{"kinds": [1]}' --dir down -v
sleep 3 # Wait for sync to complete
local orly_count=$(count_events "$ORLY_URL" '{"kinds": [1], "limit": 100}')
log_info "orly event count after sync: $orly_count"
if [ "$orly_count" -ge "$TEST_EVENTS" ]; then
log_pass "orly synced $orly_count events from strfry"
else
log_fail "orly only synced $orly_count events (expected >= $TEST_EVENTS)"
fi
}
# Test 3: Seed orly with new events and sync back to strfry
test_orly_sync_to_strfry() {
log_info "Test 3: Seeding orly and syncing back to strfry (orly -> strfry)..."
local new_events=5
for i in $(seq 1 $new_events); do
send_event "$ORLY_URL" 1 "Test event $i from orly for reverse sync"
sleep 0.1
done
sleep 2
# Check orly has the new events
local orly_count=$(count_events "$ORLY_URL" '{"kinds": [1], "limit": 100}')
log_info "orly event count: $orly_count"
# Run strfry sync from orly (using strfry's sync command)
# Note: strfry sync command format is: strfry sync <url> --filter <filter> --dir down
docker compose exec -T strfry /app/strfry sync ws://orly:3334 --filter '{"kinds": [1]}' --dir down || true
sleep 3
local strfry_count=$(count_events "$STRFRY_URL" '{"kinds": [1], "limit": 100}')
log_info "strfry event count after reverse sync: $strfry_count"
local expected=$((TEST_EVENTS + new_events))
if [ "$strfry_count" -ge "$expected" ]; then
log_pass "strfry has $strfry_count events after bidirectional sync"
else
log_fail "strfry only has $strfry_count events (expected >= $expected)"
fi
}
# Test 4: Verify event consistency
test_event_consistency() {
log_info "Test 4: Verifying event consistency between relays..."
local strfry_count=$(count_events "$STRFRY_URL" '{"kinds": [1], "limit": 100}')
local orly_count=$(count_events "$ORLY_URL" '{"kinds": [1], "limit": 100}')
log_info "strfry: $strfry_count events, orly: $orly_count events"
# After bidirectional sync, both should have similar counts
local diff=$((strfry_count - orly_count))
if [ "${diff#-}" -le 2 ]; then # Allow small difference
log_pass "Event counts are consistent (diff: $diff)"
else
log_fail "Event counts differ by $diff"
fi
}
# Run all tests
main() {
echo "========================================"
echo "Negentropy Interop Test Suite"
echo "strfry <-> orly (NIP-77)"
echo "========================================"
echo
check_services
echo
test_seed_strfry
echo
test_orly_sync_from_strfry
echo
test_orly_sync_to_strfry
echo
test_event_consistency
echo
echo "========================================"
echo "Results: $PASSED passed, $FAILED failed"
echo "========================================"
if [ "$FAILED" -gt 0 ]; then
exit 1
fi
}
main "$@"