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