subscriptions_test.go raw

   1  //go:build integration
   2  // +build integration
   3  
   4  package neo4j
   5  
   6  import (
   7  	"testing"
   8  
   9  	"next.orly.dev/pkg/nostr/interfaces/signer/p8k"
  10  )
  11  
  12  // Note: WebSocket subscription management (AddSubscription, GetSubscriptionCount,
  13  // RemoveSubscription, ClearSubscriptions) is handled at the app layer, not the
  14  // database layer. Tests for those methods have been removed.
  15  
  16  // All tests in this file use the shared testDB instance from testmain_test.go
  17  // to avoid Neo4j authentication rate limiting from too many connections.
  18  
  19  func TestMarkers_SetGetDelete(t *testing.T) {
  20  	if testDB == nil {
  21  		t.Skip("Neo4j not available")
  22  	}
  23  
  24  	cleanTestDatabase()
  25  
  26  	// Set a marker
  27  	key := "test-marker"
  28  	value := []byte("test-value-123")
  29  	if err := testDB.SetMarker(key, value); err != nil {
  30  		t.Fatalf("Failed to set marker: %v", err)
  31  	}
  32  
  33  	// Get the marker
  34  	retrieved, err := testDB.GetMarker(key)
  35  	if err != nil {
  36  		t.Fatalf("Failed to get marker: %v", err)
  37  	}
  38  	if string(retrieved) != string(value) {
  39  		t.Fatalf("Marker value mismatch: got %s, expected %s", string(retrieved), string(value))
  40  	}
  41  
  42  	// Update the marker
  43  	newValue := []byte("updated-value")
  44  	if err := testDB.SetMarker(key, newValue); err != nil {
  45  		t.Fatalf("Failed to update marker: %v", err)
  46  	}
  47  
  48  	retrieved, err = testDB.GetMarker(key)
  49  	if err != nil {
  50  		t.Fatalf("Failed to get updated marker: %v", err)
  51  	}
  52  	if string(retrieved) != string(newValue) {
  53  		t.Fatalf("Updated marker value mismatch")
  54  	}
  55  
  56  	// Delete the marker
  57  	if err := testDB.DeleteMarker(key); err != nil {
  58  		t.Fatalf("Failed to delete marker: %v", err)
  59  	}
  60  
  61  	// Verify marker is deleted
  62  	_, err = testDB.GetMarker(key)
  63  	if err == nil {
  64  		t.Fatal("Expected error when getting deleted marker")
  65  	}
  66  
  67  	t.Logf("✓ Markers set/get/delete works correctly")
  68  }
  69  
  70  func TestMarkers_GetNonExistent(t *testing.T) {
  71  	if testDB == nil {
  72  		t.Skip("Neo4j not available")
  73  	}
  74  
  75  	// Try to get non-existent marker (don't wipe - just test non-existent key)
  76  	_, err := testDB.GetMarker("non-existent-marker-unique-12345")
  77  	if err == nil {
  78  		t.Fatal("Expected error when getting non-existent marker")
  79  	}
  80  
  81  	t.Logf("✓ Getting non-existent marker returns error as expected")
  82  }
  83  
  84  func TestSerial_GetNextSerial(t *testing.T) {
  85  	if testDB == nil {
  86  		t.Skip("Neo4j not available")
  87  	}
  88  
  89  	// Get first serial
  90  	serial1, err := testDB.getNextSerial()
  91  	if err != nil {
  92  		t.Fatalf("Failed to get first serial: %v", err)
  93  	}
  94  
  95  	// Get second serial
  96  	serial2, err := testDB.getNextSerial()
  97  	if err != nil {
  98  		t.Fatalf("Failed to get second serial: %v", err)
  99  	}
 100  
 101  	// Serial should increment
 102  	if serial2 <= serial1 {
 103  		t.Fatalf("Expected serial to increment: serial1=%d, serial2=%d", serial1, serial2)
 104  	}
 105  
 106  	// Get multiple more serials and verify they're all unique and increasing
 107  	var serials []uint64
 108  	for i := 0; i < 10; i++ {
 109  		s, err := testDB.getNextSerial()
 110  		if err != nil {
 111  			t.Fatalf("Failed to get serial %d: %v", i, err)
 112  		}
 113  		serials = append(serials, s)
 114  	}
 115  
 116  	for i := 1; i < len(serials); i++ {
 117  		if serials[i] <= serials[i-1] {
 118  			t.Fatalf("Serials not increasing: %d <= %d", serials[i], serials[i-1])
 119  		}
 120  	}
 121  
 122  	t.Logf("✓ Serial generation works correctly (generated %d unique serials)", len(serials)+2)
 123  }
 124  
 125  func TestDatabaseReady(t *testing.T) {
 126  	if testDB == nil {
 127  		t.Skip("Neo4j not available")
 128  	}
 129  
 130  	// Database should already be ready (testDB is initialized in TestMain)
 131  	select {
 132  	case <-testDB.Ready():
 133  		t.Logf("✓ Database ready signal works correctly")
 134  	default:
 135  		t.Fatal("Expected database to be ready")
 136  	}
 137  }
 138  
 139  func TestIdentity(t *testing.T) {
 140  	if testDB == nil {
 141  		t.Skip("Neo4j not available")
 142  	}
 143  
 144  	cleanTestDatabase()
 145  
 146  	// Get identity (creates if not exists)
 147  	secret1, err := testDB.GetOrCreateRelayIdentitySecret()
 148  	if err != nil {
 149  		t.Fatalf("Failed to get identity: %v", err)
 150  	}
 151  	if secret1 == nil {
 152  		t.Fatal("Expected non-nil secret from GetOrCreateRelayIdentitySecret()")
 153  	}
 154  
 155  	// Get identity again (should return same one)
 156  	secret2, err := testDB.GetOrCreateRelayIdentitySecret()
 157  	if err != nil {
 158  		t.Fatalf("Failed to get identity second time: %v", err)
 159  	}
 160  	if secret2 == nil {
 161  		t.Fatal("Expected non-nil secret from second GetOrCreateRelayIdentitySecret() call")
 162  	}
 163  
 164  	// Secrets should match
 165  	if len(secret1) != len(secret2) {
 166  		t.Fatalf("Secret lengths don't match: %d vs %d", len(secret1), len(secret2))
 167  	}
 168  	for i := range secret1 {
 169  		if secret1[i] != secret2[i] {
 170  			t.Fatal("Identity secrets don't match across calls")
 171  		}
 172  	}
 173  
 174  	t.Logf("✓ Identity persistence works correctly")
 175  }
 176  
 177  func TestWipe(t *testing.T) {
 178  	if testDB == nil {
 179  		t.Skip("Neo4j not available")
 180  	}
 181  
 182  	signer, _ := p8k.New()
 183  	signer.Generate()
 184  
 185  	// Add some data
 186  	if err := testDB.AddNIP43Member(signer.Pub(), "test"); err != nil {
 187  		t.Fatalf("Failed to add member: %v", err)
 188  	}
 189  
 190  	// Wipe the database
 191  	if err := testDB.Wipe(); err != nil {
 192  		t.Fatalf("Failed to wipe database: %v", err)
 193  	}
 194  
 195  	// Verify data is gone
 196  	isMember, _ := testDB.IsNIP43Member(signer.Pub())
 197  	if isMember {
 198  		t.Fatal("Expected data to be wiped")
 199  	}
 200  
 201  	t.Logf("✓ Wipe clears database correctly")
 202  }
 203