This document explains how to run tests for the social event processor that manages NostrUser vertices and social graph relationships.
You need a running Neo4j instance for integration tests. The easiest way is using Docker:
# Using docker-compose (recommended)
cd pkg/neo4j
docker-compose up -d
docker-compose logs -f neo4j # Wait for "Started."
# Or manually:
docker run -d --name neo4j-test \
-p 7474:7474 \
-p 7687:7687 \
-e NEO4J_AUTH=neo4j/testpass123 \
neo4j:5.15
# Wait for Neo4j to start (check logs)
docker logs -f neo4j-test
Access the Neo4j browser at http://localhost:7474 (credentials: neo4j/testpass123)
Set the Neo4j connection details:
export ORLY_NEO4J_URI="bolt://localhost:7687"
export ORLY_NEO4J_USER="neo4j"
export ORLY_NEO4J_PASSWORD="testpass123"
The tests require the secp256k1 library for signing events:
# Download from nostr repository
wget https://git.nostrdev.com/mleku/nostr/raw/branch/main/crypto/p8k/libsecp256k1.so -P /tmp/
# Add to library path
export LD_LIBRARY_PATH="/tmp:$LD_LIBRARY_PATH"
cd pkg/neo4j
go test -v
# Test profile metadata processing
go test -v -run TestSocialEventProcessor/Kind0_ProfileMetadata
# Test contact list initial creation
go test -v -run TestSocialEventProcessor/Kind3_ContactList_Initial
# Test contact list updates
go test -v -run TestSocialEventProcessor/Kind3_ContactList_Update
# Test mute list
go test -v -run TestSocialEventProcessor/Kind10000_MuteList
# Test reports
go test -v -run TestSocialEventProcessor/Kind1984_Reports
# Test diff computation
go test -v -run TestDiffComputation
# Test p-tag extraction
go test -v -run TestExtractPTags
# Benchmark diff computation with 1000-element lists
go test -bench=BenchmarkDiffComputation -benchmem
Comprehensive integration test that exercises the complete event processing flow:
- Creates a profile for Alice - Verifies NostrUser node has correct name, about, picture
- Alice follows Bob and Charlie - Verifies 2 FOLLOWS relationships created - Checks event traceability (createdbyevent property)
- Alice adds Dave to follows (now: Bob, Charlie, Dave) - Verifies diff-based update (only Dave relationship added) - Checks old event marked as superseded
- Alice unfollows Charlie (now: Bob, Dave) - Verifies Charlie's FOLLOWS relationship removed - Other relationships unchanged
- Attempts to save an old contact list event - Verifies it's rejected (follows list unchanged)
- Alice mutes Eve - Verifies MUTES relationship created
- Alice reports Eve for "spam" - Bob reports Eve for "illegal" - Verifies 2 REPORTS relationships created - Checks report types are correct
- Alice follows: Bob, Dave - Alice mutes: Eve - Eve has 2 reports (from Alice and Bob) - All relationships have event traceability
Successful test run:
=== RUN TestSocialEventProcessor
=== RUN TestSocialEventProcessor/Kind0_ProfileMetadata
✓ Profile metadata processed: name=Alice
=== RUN TestSocialEventProcessor/Kind3_ContactList_Initial
✓ Initial contact list created: Alice follows [Bob, Charlie]
=== RUN TestSocialEventProcessor/Kind3_ContactList_Update_AddFollow
✓ Contact list updated: Alice follows [Bob, Charlie, Dave]
=== RUN TestSocialEventProcessor/Kind3_ContactList_Update_RemoveFollow
✓ Contact list updated: Alice unfollowed Charlie
=== RUN TestSocialEventProcessor/Kind3_ContactList_OlderEventRejected
✓ Older contact list event rejected (follows unchanged)
=== RUN TestSocialEventProcessor/Kind10000_MuteList
✓ Mute list processed: Alice mutes Eve
=== RUN TestSocialEventProcessor/Kind1984_Reports
✓ Reports processed: Eve reported by Alice (spam) and Bob (illegal)
=== RUN TestSocialEventProcessor/VerifyGraphState
✓ Final graph state verified
- Alice follows: [bob_pubkey, dave_pubkey]
- Alice mutes: [eve_pubkey]
- Reports against Eve: 2
--- PASS: TestSocialEventProcessor (0.45s)
PASS
After running tests, you can explore the graph in Neo4j Browser (http://localhost:7474):
MATCH (u:NostrUser)
RETURN u
MATCH path = (u1:NostrUser)-[r:FOLLOWS|MUTES|REPORTS]->(u2:NostrUser)
RETURN path
MATCH (alice:NostrUser {name: "Alice"})-[:FOLLOWS]->(followed:NostrUser)
RETURN alice, followed
MATCH (evt:ProcessedSocialEvent)
RETURN evt.event_id, evt.event_kind, evt.created_at, evt.superseded_by
ORDER BY evt.created_at ASC
MATCH (u1:NostrUser)-[r:FOLLOWS]->(u2:NostrUser)
MATCH (evt:ProcessedSocialEvent {event_id: r.created_by_event})
RETURN u1.name, u2.name, evt.event_id, evt.created_at
// In Neo4j Browser
MATCH (n)
DETACH DELETE n
Or use the database wipe function:
# In Go test
db.Wipe() // Removes all data and reapplies schema
docker stop neo4j-test
docker rm neo4j-test
To run tests in CI without Neo4j:
# Tests will be skipped if ORLY_NEO4J_URI is not set
go test ./pkg/neo4j/...
Output:
? next.orly.dev/pkg/neo4j [no test files]
--- SKIP: TestSocialEventProcessor (0.00s)
testmain_test.go:14: Neo4j not available (set ORLY_NEO4J_URI to enable tests)
# Run with debug logs
go test -v -run TestSocialEventProcessor 2>&1 | tee test.log
The database logger is set to "debug" level in tests, showing all Cypher queries.
docker logs neo4j-test
After a failed test, connect to Neo4j Browser and run diagnostic queries:
// Count nodes by label
MATCH (n)
RETURN labels(n), count(*)
// Count relationships by type
MATCH ()-[r]->()
RETURN type(r), count(*)
// Find relationships without event traceability
MATCH ()-[r:FOLLOWS|MUTES|REPORTS]->()
WHERE r.created_by_event IS NULL
RETURN r
// Find superseded events
MATCH (evt:ProcessedSocialEvent)
WHERE evt.superseded_by IS NOT NULL
RETURN evt
Run benchmarks to measure diff computation performance:
go test -bench=. -benchmem
Expected output:
BenchmarkDiffComputation-8 50000 30000 ns/op 16384 B/op 20 allocs/op
This benchmarks diff computation with:
Generate coverage report:
go test -coverprofile=coverage.out
go tool cover -html=coverage.out
Target coverage:
Ensure Neo4j is running and environment variables are set:
docker ps | grep neo4j
echo $ORLY_NEO4J_URI
Check Neo4j authentication:
docker exec -it neo4j-test cypher-shell -u neo4j -p test
Download and set LDLIBRARYPATH:
wget https://git.nostrdev.com/mleku/nostr/raw/branch/main/crypto/p8k/libsecp256k1.so
export LD_LIBRARY_PATH="$(pwd):$LD_LIBRARY_PATH"
The database wasn't cleaned between tests. Restart Neo4j:
docker restart neo4j-test
For questions or issues with tests: