Some checks failed
Go / build-and-release (push) Has been cancelled
Introduce comprehensive integration tests for Neo4j bug fixes covering batching, event relationships, and processing logic. Add rate-limiting to Neo4j queries using semaphores and retry policies to prevent authentication rate limiting and connection exhaustion, ensuring system stability under load.
203 lines
4.9 KiB
Go
203 lines
4.9 KiB
Go
//go:build integration
|
|
// +build integration
|
|
|
|
package neo4j
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"git.mleku.dev/mleku/nostr/interfaces/signer/p8k"
|
|
)
|
|
|
|
// Note: WebSocket subscription management (AddSubscription, GetSubscriptionCount,
|
|
// RemoveSubscription, ClearSubscriptions) is handled at the app layer, not the
|
|
// database layer. Tests for those methods have been removed.
|
|
|
|
// All tests in this file use the shared testDB instance from testmain_test.go
|
|
// to avoid Neo4j authentication rate limiting from too many connections.
|
|
|
|
func TestMarkers_SetGetDelete(t *testing.T) {
|
|
if testDB == nil {
|
|
t.Skip("Neo4j not available")
|
|
}
|
|
|
|
cleanTestDatabase()
|
|
|
|
// Set a marker
|
|
key := "test-marker"
|
|
value := []byte("test-value-123")
|
|
if err := testDB.SetMarker(key, value); err != nil {
|
|
t.Fatalf("Failed to set marker: %v", err)
|
|
}
|
|
|
|
// Get the marker
|
|
retrieved, err := testDB.GetMarker(key)
|
|
if err != nil {
|
|
t.Fatalf("Failed to get marker: %v", err)
|
|
}
|
|
if string(retrieved) != string(value) {
|
|
t.Fatalf("Marker value mismatch: got %s, expected %s", string(retrieved), string(value))
|
|
}
|
|
|
|
// Update the marker
|
|
newValue := []byte("updated-value")
|
|
if err := testDB.SetMarker(key, newValue); err != nil {
|
|
t.Fatalf("Failed to update marker: %v", err)
|
|
}
|
|
|
|
retrieved, err = testDB.GetMarker(key)
|
|
if err != nil {
|
|
t.Fatalf("Failed to get updated marker: %v", err)
|
|
}
|
|
if string(retrieved) != string(newValue) {
|
|
t.Fatalf("Updated marker value mismatch")
|
|
}
|
|
|
|
// Delete the marker
|
|
if err := testDB.DeleteMarker(key); err != nil {
|
|
t.Fatalf("Failed to delete marker: %v", err)
|
|
}
|
|
|
|
// Verify marker is deleted
|
|
_, err = testDB.GetMarker(key)
|
|
if err == nil {
|
|
t.Fatal("Expected error when getting deleted marker")
|
|
}
|
|
|
|
t.Logf("✓ Markers set/get/delete works correctly")
|
|
}
|
|
|
|
func TestMarkers_GetNonExistent(t *testing.T) {
|
|
if testDB == nil {
|
|
t.Skip("Neo4j not available")
|
|
}
|
|
|
|
// Try to get non-existent marker (don't wipe - just test non-existent key)
|
|
_, err := testDB.GetMarker("non-existent-marker-unique-12345")
|
|
if err == nil {
|
|
t.Fatal("Expected error when getting non-existent marker")
|
|
}
|
|
|
|
t.Logf("✓ Getting non-existent marker returns error as expected")
|
|
}
|
|
|
|
func TestSerial_GetNextSerial(t *testing.T) {
|
|
if testDB == nil {
|
|
t.Skip("Neo4j not available")
|
|
}
|
|
|
|
// Get first serial
|
|
serial1, err := testDB.getNextSerial()
|
|
if err != nil {
|
|
t.Fatalf("Failed to get first serial: %v", err)
|
|
}
|
|
|
|
// Get second serial
|
|
serial2, err := testDB.getNextSerial()
|
|
if err != nil {
|
|
t.Fatalf("Failed to get second serial: %v", err)
|
|
}
|
|
|
|
// Serial should increment
|
|
if serial2 <= serial1 {
|
|
t.Fatalf("Expected serial to increment: serial1=%d, serial2=%d", serial1, serial2)
|
|
}
|
|
|
|
// Get multiple more serials and verify they're all unique and increasing
|
|
var serials []uint64
|
|
for i := 0; i < 10; i++ {
|
|
s, err := testDB.getNextSerial()
|
|
if err != nil {
|
|
t.Fatalf("Failed to get serial %d: %v", i, err)
|
|
}
|
|
serials = append(serials, s)
|
|
}
|
|
|
|
for i := 1; i < len(serials); i++ {
|
|
if serials[i] <= serials[i-1] {
|
|
t.Fatalf("Serials not increasing: %d <= %d", serials[i], serials[i-1])
|
|
}
|
|
}
|
|
|
|
t.Logf("✓ Serial generation works correctly (generated %d unique serials)", len(serials)+2)
|
|
}
|
|
|
|
func TestDatabaseReady(t *testing.T) {
|
|
if testDB == nil {
|
|
t.Skip("Neo4j not available")
|
|
}
|
|
|
|
// Database should already be ready (testDB is initialized in TestMain)
|
|
select {
|
|
case <-testDB.Ready():
|
|
t.Logf("✓ Database ready signal works correctly")
|
|
default:
|
|
t.Fatal("Expected database to be ready")
|
|
}
|
|
}
|
|
|
|
func TestIdentity(t *testing.T) {
|
|
if testDB == nil {
|
|
t.Skip("Neo4j not available")
|
|
}
|
|
|
|
cleanTestDatabase()
|
|
|
|
// Get identity (creates if not exists)
|
|
secret1, err := testDB.GetOrCreateRelayIdentitySecret()
|
|
if err != nil {
|
|
t.Fatalf("Failed to get identity: %v", err)
|
|
}
|
|
if secret1 == nil {
|
|
t.Fatal("Expected non-nil secret from GetOrCreateRelayIdentitySecret()")
|
|
}
|
|
|
|
// Get identity again (should return same one)
|
|
secret2, err := testDB.GetOrCreateRelayIdentitySecret()
|
|
if err != nil {
|
|
t.Fatalf("Failed to get identity second time: %v", err)
|
|
}
|
|
if secret2 == nil {
|
|
t.Fatal("Expected non-nil secret from second GetOrCreateRelayIdentitySecret() call")
|
|
}
|
|
|
|
// Secrets should match
|
|
if len(secret1) != len(secret2) {
|
|
t.Fatalf("Secret lengths don't match: %d vs %d", len(secret1), len(secret2))
|
|
}
|
|
for i := range secret1 {
|
|
if secret1[i] != secret2[i] {
|
|
t.Fatal("Identity secrets don't match across calls")
|
|
}
|
|
}
|
|
|
|
t.Logf("✓ Identity persistence works correctly")
|
|
}
|
|
|
|
func TestWipe(t *testing.T) {
|
|
if testDB == nil {
|
|
t.Skip("Neo4j not available")
|
|
}
|
|
|
|
signer, _ := p8k.New()
|
|
signer.Generate()
|
|
|
|
// Add some data
|
|
if err := testDB.AddNIP43Member(signer.Pub(), "test"); err != nil {
|
|
t.Fatalf("Failed to add member: %v", err)
|
|
}
|
|
|
|
// Wipe the database
|
|
if err := testDB.Wipe(); err != nil {
|
|
t.Fatalf("Failed to wipe database: %v", err)
|
|
}
|
|
|
|
// Verify data is gone
|
|
isMember, _ := testDB.IsNIP43Member(signer.Pub())
|
|
if isMember {
|
|
t.Fatal("Expected data to be wiped")
|
|
}
|
|
|
|
t.Logf("✓ Wipe clears database correctly")
|
|
}
|