fetch-event_test.go raw

   1  //go:build integration
   2  // +build integration
   3  
   4  package neo4j
   5  
   6  import (
   7  	"context"
   8  	"testing"
   9  
  10  	"next.orly.dev/pkg/nostr/encoders/event"
  11  	"next.orly.dev/pkg/nostr/encoders/filter"
  12  	"next.orly.dev/pkg/nostr/encoders/hex"
  13  	"next.orly.dev/pkg/nostr/encoders/tag"
  14  	"next.orly.dev/pkg/nostr/encoders/timestamp"
  15  	"next.orly.dev/pkg/nostr/interfaces/signer/p8k"
  16  	"next.orly.dev/pkg/database/indexes/types"
  17  )
  18  
  19  // All tests in this file use the shared testDB instance from testmain_test.go
  20  // to avoid Neo4j authentication rate limiting from too many connections.
  21  
  22  func TestFetchEventBySerial(t *testing.T) {
  23  	if testDB == nil {
  24  		t.Skip("Neo4j not available")
  25  	}
  26  
  27  	cleanTestDatabase()
  28  
  29  	ctx := context.Background()
  30  
  31  	signer, err := p8k.New()
  32  	if err != nil {
  33  		t.Fatalf("Failed to create signer: %v", err)
  34  	}
  35  	if err := signer.Generate(); err != nil {
  36  		t.Fatalf("Failed to generate keypair: %v", err)
  37  	}
  38  
  39  	// Create and save a test event
  40  	ev := event.New()
  41  	ev.Pubkey = signer.Pub()
  42  	ev.CreatedAt = timestamp.Now().V
  43  	ev.Kind = 1
  44  	ev.Content = []byte("Test event for fetch by serial")
  45  
  46  	if err := ev.Sign(signer); err != nil {
  47  		t.Fatalf("Failed to sign event: %v", err)
  48  	}
  49  
  50  	if _, err := testDB.SaveEvent(ctx, ev); err != nil {
  51  		t.Fatalf("Failed to save event: %v", err)
  52  	}
  53  
  54  	// Get the serial for this event
  55  	serial, err := testDB.GetSerialById(ev.ID[:])
  56  	if err != nil {
  57  		t.Fatalf("Failed to get serial by ID: %v", err)
  58  	}
  59  
  60  	// Fetch event by serial
  61  	fetchedEvent, err := testDB.FetchEventBySerial(serial)
  62  	if err != nil {
  63  		t.Fatalf("Failed to fetch event by serial: %v", err)
  64  	}
  65  
  66  	if fetchedEvent == nil {
  67  		t.Fatal("Expected fetched event to be non-nil")
  68  	}
  69  
  70  	// Verify event properties
  71  	if hex.Enc(fetchedEvent.ID[:]) != hex.Enc(ev.ID[:]) {
  72  		t.Fatalf("Event ID mismatch: got %s, expected %s",
  73  			hex.Enc(fetchedEvent.ID[:]), hex.Enc(ev.ID[:]))
  74  	}
  75  
  76  	if fetchedEvent.Kind != ev.Kind {
  77  		t.Fatalf("Kind mismatch: got %d, expected %d", fetchedEvent.Kind, ev.Kind)
  78  	}
  79  
  80  	if hex.Enc(fetchedEvent.Pubkey[:]) != hex.Enc(ev.Pubkey[:]) {
  81  		t.Fatalf("Pubkey mismatch")
  82  	}
  83  
  84  	if fetchedEvent.CreatedAt != ev.CreatedAt {
  85  		t.Fatalf("CreatedAt mismatch: got %d, expected %d",
  86  			fetchedEvent.CreatedAt, ev.CreatedAt)
  87  	}
  88  
  89  	t.Logf("✓ FetchEventBySerial returned correct event")
  90  }
  91  
  92  func TestFetchEventBySerial_NonExistent(t *testing.T) {
  93  	if testDB == nil {
  94  		t.Skip("Neo4j not available")
  95  	}
  96  
  97  	// Try to fetch with non-existent serial
  98  	nonExistentSerial := &types.Uint40{}
  99  	nonExistentSerial.Set(0xFFFFFFFFFF) // Max value
 100  
 101  	_, err := testDB.FetchEventBySerial(nonExistentSerial)
 102  	if err == nil {
 103  		t.Fatal("Expected error for non-existent serial")
 104  	}
 105  
 106  	t.Logf("✓ FetchEventBySerial correctly returned error for non-existent serial")
 107  }
 108  
 109  func TestFetchEventsBySerials(t *testing.T) {
 110  	if testDB == nil {
 111  		t.Skip("Neo4j not available")
 112  	}
 113  
 114  	cleanTestDatabase()
 115  
 116  	ctx := context.Background()
 117  
 118  	signer, err := p8k.New()
 119  	if err != nil {
 120  		t.Fatalf("Failed to create signer: %v", err)
 121  	}
 122  	if err := signer.Generate(); err != nil {
 123  		t.Fatalf("Failed to generate keypair: %v", err)
 124  	}
 125  
 126  	// Create and save multiple events
 127  	var serials []*types.Uint40
 128  	eventIDs := make(map[uint64]string)
 129  
 130  	for i := 0; i < 5; i++ {
 131  		ev := event.New()
 132  		ev.Pubkey = signer.Pub()
 133  		ev.CreatedAt = timestamp.Now().V + int64(i)
 134  		ev.Kind = 1
 135  		ev.Content = []byte("Test event")
 136  
 137  		if err := ev.Sign(signer); err != nil {
 138  			t.Fatalf("Failed to sign event: %v", err)
 139  		}
 140  
 141  		if _, err := testDB.SaveEvent(ctx, ev); err != nil {
 142  			t.Fatalf("Failed to save event: %v", err)
 143  		}
 144  
 145  		serial, err := testDB.GetSerialById(ev.ID[:])
 146  		if err != nil {
 147  			t.Fatalf("Failed to get serial: %v", err)
 148  		}
 149  
 150  		serials = append(serials, serial)
 151  		eventIDs[serial.Get()] = hex.Enc(ev.ID[:])
 152  	}
 153  
 154  	// Fetch all events by serials
 155  	events, err := testDB.FetchEventsBySerials(serials)
 156  	if err != nil {
 157  		t.Fatalf("Failed to fetch events by serials: %v", err)
 158  	}
 159  
 160  	if len(events) != 5 {
 161  		t.Fatalf("Expected 5 events, got %d", len(events))
 162  	}
 163  
 164  	// Verify each event
 165  	for serial, expectedID := range eventIDs {
 166  		ev, exists := events[serial]
 167  		if !exists {
 168  			t.Fatalf("Event with serial %d not found", serial)
 169  		}
 170  		if hex.Enc(ev.ID[:]) != expectedID {
 171  			t.Fatalf("Event ID mismatch for serial %d", serial)
 172  		}
 173  	}
 174  
 175  	t.Logf("✓ FetchEventsBySerials returned %d correct events", len(events))
 176  }
 177  
 178  func TestGetSerialById(t *testing.T) {
 179  	if testDB == nil {
 180  		t.Skip("Neo4j not available")
 181  	}
 182  
 183  	cleanTestDatabase()
 184  
 185  	ctx := context.Background()
 186  
 187  	signer, err := p8k.New()
 188  	if err != nil {
 189  		t.Fatalf("Failed to create signer: %v", err)
 190  	}
 191  	if err := signer.Generate(); err != nil {
 192  		t.Fatalf("Failed to generate keypair: %v", err)
 193  	}
 194  
 195  	// Create and save event
 196  	ev := event.New()
 197  	ev.Pubkey = signer.Pub()
 198  	ev.CreatedAt = timestamp.Now().V
 199  	ev.Kind = 1
 200  	ev.Content = []byte("Test event")
 201  
 202  	if err := ev.Sign(signer); err != nil {
 203  		t.Fatalf("Failed to sign event: %v", err)
 204  	}
 205  
 206  	if _, err := testDB.SaveEvent(ctx, ev); err != nil {
 207  		t.Fatalf("Failed to save event: %v", err)
 208  	}
 209  
 210  	// Get serial by ID
 211  	serial, err := testDB.GetSerialById(ev.ID[:])
 212  	if err != nil {
 213  		t.Fatalf("Failed to get serial by ID: %v", err)
 214  	}
 215  
 216  	if serial == nil {
 217  		t.Fatal("Expected serial to be non-nil")
 218  	}
 219  
 220  	if serial.Get() == 0 {
 221  		t.Fatal("Expected non-zero serial")
 222  	}
 223  
 224  	t.Logf("✓ GetSerialById returned serial: %d", serial.Get())
 225  }
 226  
 227  func TestGetSerialById_NonExistent(t *testing.T) {
 228  	if testDB == nil {
 229  		t.Skip("Neo4j not available")
 230  	}
 231  
 232  	// Try to get serial for non-existent event
 233  	fakeID, _ := hex.Dec("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
 234  
 235  	_, err := testDB.GetSerialById(fakeID)
 236  	if err == nil {
 237  		t.Fatal("Expected error for non-existent event ID")
 238  	}
 239  
 240  	t.Logf("✓ GetSerialById correctly returned error for non-existent ID")
 241  }
 242  
 243  func TestGetSerialsByIds(t *testing.T) {
 244  	if testDB == nil {
 245  		t.Skip("Neo4j not available")
 246  	}
 247  
 248  	cleanTestDatabase()
 249  
 250  	ctx := context.Background()
 251  
 252  	signer, err := p8k.New()
 253  	if err != nil {
 254  		t.Fatalf("Failed to create signer: %v", err)
 255  	}
 256  	if err := signer.Generate(); err != nil {
 257  		t.Fatalf("Failed to generate keypair: %v", err)
 258  	}
 259  
 260  	// Create and save multiple events
 261  	ids := tag.New()
 262  	for i := 0; i < 3; i++ {
 263  		ev := event.New()
 264  		ev.Pubkey = signer.Pub()
 265  		ev.CreatedAt = timestamp.Now().V + int64(i)
 266  		ev.Kind = 1
 267  		ev.Content = []byte("Test event")
 268  
 269  		if err := ev.Sign(signer); err != nil {
 270  			t.Fatalf("Failed to sign event: %v", err)
 271  		}
 272  
 273  		if _, err := testDB.SaveEvent(ctx, ev); err != nil {
 274  			t.Fatalf("Failed to save event: %v", err)
 275  		}
 276  
 277  		// Append ID to the tag's T slice
 278  		ids.T = append(ids.T, []byte(hex.Enc(ev.ID[:])))
 279  	}
 280  
 281  	// Get serials by IDs
 282  	serials, err := testDB.GetSerialsByIds(ids)
 283  	if err != nil {
 284  		t.Fatalf("Failed to get serials by IDs: %v", err)
 285  	}
 286  
 287  	if len(serials) != 3 {
 288  		t.Fatalf("Expected 3 serials, got %d", len(serials))
 289  	}
 290  
 291  	t.Logf("✓ GetSerialsByIds returned %d serials", len(serials))
 292  }
 293  
 294  func TestGetFullIdPubkeyBySerial(t *testing.T) {
 295  	if testDB == nil {
 296  		t.Skip("Neo4j not available")
 297  	}
 298  
 299  	cleanTestDatabase()
 300  
 301  	ctx := context.Background()
 302  
 303  	signer, err := p8k.New()
 304  	if err != nil {
 305  		t.Fatalf("Failed to create signer: %v", err)
 306  	}
 307  	if err := signer.Generate(); err != nil {
 308  		t.Fatalf("Failed to generate keypair: %v", err)
 309  	}
 310  
 311  	// Create and save event
 312  	ev := event.New()
 313  	ev.Pubkey = signer.Pub()
 314  	ev.CreatedAt = timestamp.Now().V
 315  	ev.Kind = 1
 316  	ev.Content = []byte("Test event")
 317  
 318  	if err := ev.Sign(signer); err != nil {
 319  		t.Fatalf("Failed to sign event: %v", err)
 320  	}
 321  
 322  	if _, err := testDB.SaveEvent(ctx, ev); err != nil {
 323  		t.Fatalf("Failed to save event: %v", err)
 324  	}
 325  
 326  	// Get serial
 327  	serial, err := testDB.GetSerialById(ev.ID[:])
 328  	if err != nil {
 329  		t.Fatalf("Failed to get serial: %v", err)
 330  	}
 331  
 332  	// Get full ID and pubkey
 333  	idPkTs, err := testDB.GetFullIdPubkeyBySerial(serial)
 334  	if err != nil {
 335  		t.Fatalf("Failed to get full ID and pubkey: %v", err)
 336  	}
 337  
 338  	if idPkTs == nil {
 339  		t.Fatal("Expected non-nil result")
 340  	}
 341  
 342  	if idPkTs.IDHex() != hex.Enc(ev.ID[:]) {
 343  		t.Fatalf("ID mismatch")
 344  	}
 345  
 346  	if idPkTs.PubHex() != hex.Enc(ev.Pubkey[:]) {
 347  		t.Fatalf("Pubkey mismatch")
 348  	}
 349  
 350  	if idPkTs.Ts != ev.CreatedAt {
 351  		t.Fatalf("Timestamp mismatch")
 352  	}
 353  
 354  	t.Logf("✓ GetFullIdPubkeyBySerial returned correct data")
 355  }
 356  
 357  func TestQueryForSerials(t *testing.T) {
 358  	if testDB == nil {
 359  		t.Skip("Neo4j not available")
 360  	}
 361  
 362  	cleanTestDatabase()
 363  
 364  	ctx := context.Background()
 365  
 366  	signer, err := p8k.New()
 367  	if err != nil {
 368  		t.Fatalf("Failed to create signer: %v", err)
 369  	}
 370  	if err := signer.Generate(); err != nil {
 371  		t.Fatalf("Failed to generate keypair: %v", err)
 372  	}
 373  
 374  	// Create and save events
 375  	for i := 0; i < 5; i++ {
 376  		ev := event.New()
 377  		ev.Pubkey = signer.Pub()
 378  		ev.CreatedAt = timestamp.Now().V + int64(i)
 379  		ev.Kind = 1
 380  		ev.Content = []byte("Test event")
 381  
 382  		if err := ev.Sign(signer); err != nil {
 383  			t.Fatalf("Failed to sign event: %v", err)
 384  		}
 385  
 386  		if _, err := testDB.SaveEvent(ctx, ev); err != nil {
 387  			t.Fatalf("Failed to save event: %v", err)
 388  		}
 389  	}
 390  
 391  	// Query for serials
 392  	serials, err := testDB.QueryForSerials(ctx, &filter.F{
 393  		Authors: tag.NewFromBytesSlice(signer.Pub()),
 394  	})
 395  	if err != nil {
 396  		t.Fatalf("Failed to query for serials: %v", err)
 397  	}
 398  
 399  	if len(serials) != 5 {
 400  		t.Fatalf("Expected 5 serials, got %d", len(serials))
 401  	}
 402  
 403  	t.Logf("✓ QueryForSerials returned %d serials", len(serials))
 404  }
 405