Comprehensive test suite for the social event processor that manages NostrUser vertices and social graph relationships (FOLLOWS, MUTES, REPORTS) in Neo4j.
Complete integration test suite covering:
TestSocialEventProcessor - Main test with 8 sub-testsTestDiffComputation - Unit tests for diff algorithmTestExtractPTags - Unit tests for p-tag extractionBenchmarkDiffComputation - Performance test for 1000-element diffsComplete testing guide with:
testProfileMetadata(t, ctx, db, alice)
testContactListInitial(t, ctx, db, alice, bob, charlie)
testContactListUpdate(t, ctx, db, alice, bob, charlie, dave)
testContactListRemove(t, ctx, db, alice, bob, charlie, dave)
testContactListOlderRejected(t, ctx, db, alice, bob)
testMuteList(t, ctx, db, alice, eve)
testReports(t, ctx, db, alice, bob, eve)
verifyFinalGraphState(t, ctx, db, alice, bob, charlie, dave, eve)
generateTestKeypair(t, name) testKeypair
queryFollows(t, ctx, db, pubkey) []string
queryMutes(t, ctx, db, pubkey) []string
queryReports(t, ctx, db, pubkey) []reportInfo
diffStringSlices(old, new) (added, removed []string)
extractPTags(ev) []string
1. Generate test keypairs (Alice, Bob, Charlie, Dave, Eve)
└─> testKeypair struct with pubkey + signer
2. Create Kind 0 event (Alice's profile)
└─> Sign with Alice's signer
└─> SaveEvent()
└─> Query NostrUser node
└─> Assert: name="Alice", about="Test user"
3. Create Kind 3 event (Alice follows Bob, Charlie)
└─> Sign with Alice's signer
└─> SaveEvent()
└─> Query FOLLOWS relationships
└─> Assert: 2 relationships, correct targets
4. Update Kind 3 event (Alice adds Dave)
└─> Newer timestamp
└─> Sign and SaveEvent()
└─> Query FOLLOWS relationships
└─> Assert: 3 relationships (Bob, Charlie, Dave)
└─> Query ProcessedSocialEvent
└─> Assert: old event superseded
5. Update Kind 3 event (Alice unfollows Charlie)
└─> Even newer timestamp
└─> Sign and SaveEvent()
└─> Query FOLLOWS relationships
└─> Assert: 2 relationships (Bob, Dave only)
6. Create Kind 10000 event (Alice mutes Eve)
└─> Sign and SaveEvent()
└─> Query MUTES relationships
└─> Assert: 1 relationship to Eve
7. Create Kind 1984 events (Reports against Eve)
└─> Alice reports for "spam"
└─> Bob reports for "illegal"
└─> Sign and SaveEvent() for both
└─> Query REPORTS relationships
└─> Assert: 2 reports with correct types
8. Final verification
└─> Query all relationship types
└─> Assert: complete graph state correct
└─> Check: all relationships have created_by_event
# 1. Start Neo4j
docker run -d --name neo4j-test -p 7474:7474 -p 7687:7687 -e NEO4J_AUTH=neo4j/test neo4j:5.15
# 2. Download libsecp256k1.so
wget https://git.nostrdev.com/mleku/nostr/raw/branch/main/crypto/p8k/libsecp256k1.so -P /tmp/
export LD_LIBRARY_PATH="/tmp:$LD_LIBRARY_PATH"
# 3. Set environment
export ORLY_NEO4J_URI="bolt://localhost:7687"
export ORLY_NEO4J_USER="neo4j"
export ORLY_NEO4J_PASSWORD="test"
# All tests
cd pkg/neo4j && go test -v
# Specific test
go test -v -run TestSocialEventProcessor/Kind3_ContactList_Update_AddFollow
# Unit tests only
go test -v -run TestDiff
go test -v -run TestExtract
# Benchmarks
go test -bench=. -benchmem
=== 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
Verifying final graph state...
✓ 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, explore the graph at http://localhost:7474:
MATCH (n)
RETURN n
LIMIT 50
MATCH path = (u1:NostrUser)-[r:FOLLOWS|MUTES|REPORTS]->(u2:NostrUser)
RETURN path
MATCH (alice:NostrUser {name: "Alice"})-[r]->(other:NostrUser)
RETURN alice, type(r) as relationship, other
MATCH (evt:ProcessedSocialEvent)
RETURN evt.event_id as event,
evt.event_kind as kind,
evt.created_at as timestamp,
evt.relationship_count as count,
evt.superseded_by as superseded
ORDER BY evt.created_at ASC
MATCH (evt1:ProcessedSocialEvent {event_kind: 3, pubkey: $alice_pubkey})
WHERE evt1.superseded_by IS NOT NULL
OPTIONAL MATCH (evt2:ProcessedSocialEvent {event_id: evt1.superseded_by})
RETURN evt1.event_id, evt1.created_at, evt2.event_id, evt2.created_at
MATCH ()-[r:FOLLOWS|MUTES|REPORTS]->()
RETURN type(r) as rel_type,
COUNT(CASE WHEN r.created_by_event IS NULL THEN 1 END) as missing_traceability,
COUNT(*) as total
BenchmarkDiffComputation-8 50000 30000 ns/op 16384 B/op 20 allocs/op
(1000 elements, 800 common, 200 added, 200 removed)
Database logger set to "debug" in tests, showing all Cypher queries:
[DEBUG] Executing Cypher: MATCH (u:NostrUser {pubkey: $pubkey})...
[DEBUG] Query returned 1 result
// Count nodes by label
MATCH (n) RETURN labels(n), count(*)
// Count relationships by type
MATCH ()-[r]->() RETURN type(r), count(*)
// Find relationships without traceability
MATCH ()-[r:FOLLOWS|MUTES|REPORTS]->()
WHERE r.created_by_event IS NULL
RETURN r
MATCH (evt:ProcessedSocialEvent)
WHERE evt.superseded_by IS NOT NULL
RETURN evt
Tests skip gracefully if Neo4j not available:
if os.Getenv("ORLY_NEO4J_URI") == "" {
t.Skip("Skipping Neo4j test: ORLY_NEO4J_URI not set")
}
For CI with Neo4j:
services:
neo4j:
image: neo4j:5.15
ports:
- 7687:7687
env:
NEO4J_AUTH: neo4j/test
test:
script:
- export ORLY_NEO4J_URI="bolt://neo4j:7687"
- export ORLY_NEO4J_USER="neo4j"
- export ORLY_NEO4J_PASSWORD="test"
- go test ./pkg/neo4j/...
✅ Complete test coverage for social event processing ✅ Comprehensive documentation (TESTING.md) ✅ Integration tests with real Neo4j instance ✅ Unit tests for helper functions ✅ Benchmarks for performance monitoring ✅ Neo4j Browser queries for visual verification ✅ CI/CD ready (skips if Neo4j not available) ✅ Debug support with detailed logging ✅ Clear test output with checkmarks and summaries
The test suite validates that the event-driven vertex management system works correctly for all three social event types (follows, mutes, reports) with full event traceability and diff-based updates.