1 package database
2 3 import (
4 "bytes"
5 "testing"
6 7 "next.orly.dev/pkg/nostr/encoders/filter"
8 "next.orly.dev/pkg/nostr/encoders/kind"
9 "next.orly.dev/pkg/nostr/encoders/tag"
10 "next.orly.dev/pkg/nostr/encoders/timestamp"
11 )
12 13 func TestQueryForIds(t *testing.T) {
14 // Use shared database (read-only test)
15 db, ctx := GetSharedDB(t)
16 events := GetSharedEvents(t)
17 18 if len(events) < 2 {
19 t.Fatalf("Need at least 2 saved events, got %d", len(events))
20 }
21 22 idTsPk, err := db.QueryForIds(
23 ctx, &filter.F{
24 Authors: tag.NewFromBytesSlice(events[1].Pubkey),
25 },
26 )
27 if err != nil {
28 t.Fatalf("Failed to query for authors: %v", err)
29 }
30 31 if len(idTsPk) < 1 {
32 t.Fatalf(
33 "got unexpected number of results, expect at least 1, got %d",
34 len(idTsPk),
35 )
36 }
37 // Verify that all returned events have the correct author
38 for i, result := range idTsPk {
39 // Find the event with this ID
40 var found bool
41 for _, ev := range events {
42 if bytes.Equal(result.Id[:], ev.ID[:]) {
43 found = true
44 if !bytes.Equal(ev.Pubkey[:], events[1].Pubkey[:]) {
45 t.Fatalf(
46 "result %d has incorrect author, got %x, expected %x",
47 i, ev.Pubkey, events[1].Pubkey,
48 )
49 }
50 break
51 }
52 }
53 if !found {
54 t.Fatalf("result %d with ID %x not found in events", i, result.Id)
55 }
56 }
57 58 // Test querying by kind
59 // Find an event with a specific kind
60 testKind := kind.New(1) // Kind 1 is typically text notes
61 kindFilter := kind.NewS(testKind)
62 63 idTsPk, err = db.QueryForIds(
64 ctx, &filter.F{
65 Kinds: kindFilter,
66 },
67 )
68 if err != nil {
69 t.Fatalf("Failed to query for kinds: %v", err)
70 }
71 72 // Verify we got results
73 if len(idTsPk) == 0 {
74 t.Fatal("did not find any events with the specified kind")
75 }
76 77 // Verify the results have the correct kind
78 for i, result := range idTsPk {
79 // Find the event with this ID
80 var found bool
81 for _, ev := range events {
82 if bytes.Equal(result.Id[:], ev.ID[:]) {
83 found = true
84 if ev.Kind != testKind.K {
85 t.Fatalf(
86 "result %d has incorrect kind, got %d, expected %d",
87 i, ev.Kind, testKind.K,
88 )
89 }
90 break
91 }
92 }
93 if !found {
94 t.Fatalf("result %d with ID %x not found in events", i, result.Id)
95 }
96 }
97 98 // Test querying by tag
99 // Find an event with tags to use for testing
100 var testTag *tag.T
101 var testEventForTag = findEventWithTag(events)
102 103 if testEventForTag != nil {
104 // Get the first tag with at least 2 elements and first element of length 1
105 for _, tg := range *testEventForTag.Tags {
106 if tg.Len() >= 2 && len(tg.Key()) == 1 {
107 testTag = tg
108 break
109 }
110 }
111 112 // Create a tags filter with the test tag
113 tagsFilter := tag.NewS(testTag)
114 115 idTsPk, err = db.QueryForIds(
116 ctx, &filter.F{
117 Tags: tagsFilter,
118 },
119 )
120 if err != nil {
121 t.Fatalf("Failed to query for tags: %v", err)
122 }
123 124 // Verify we got results
125 if len(idTsPk) == 0 {
126 t.Fatal("did not find any events with the specified tag")
127 }
128 129 // Verify the results have the correct tag
130 for i, result := range idTsPk {
131 // Find the event with this ID
132 var found bool
133 for _, ev := range events {
134 if bytes.Equal(result.Id[:], ev.ID[:]) {
135 found = true
136 137 // Check if the event has the tag we're looking for
138 var hasTag bool
139 for _, tg := range *ev.Tags {
140 if tg.Len() >= 2 && len(tg.Key()) == 1 {
141 if bytes.Equal(
142 tg.Key(), testTag.Key(),
143 ) && bytes.Equal(tg.Value(), testTag.Value()) {
144 hasTag = true
145 break
146 }
147 }
148 }
149 150 if !hasTag {
151 t.Fatalf(
152 "result %d does not have the expected tag",
153 i,
154 )
155 }
156 157 break
158 }
159 }
160 if !found {
161 t.Fatalf(
162 "result %d with ID %x not found in events", i, result.Id,
163 )
164 }
165 }
166 167 // Test querying by kind and author
168 idTsPk, err = db.QueryForIds(
169 ctx, &filter.F{
170 Kinds: kindFilter,
171 Authors: tag.NewFromBytesSlice(events[1].Pubkey),
172 },
173 )
174 if err != nil {
175 t.Fatalf("Failed to query for kinds and authors: %v", err)
176 }
177 178 // Verify we got results
179 if len(idTsPk) > 0 {
180 // Verify the results have the correct kind and author
181 for i, result := range idTsPk {
182 // Find the event with this ID
183 var found bool
184 for _, ev := range events {
185 if bytes.Equal(result.Id[:], ev.ID[:]) {
186 found = true
187 if ev.Kind != testKind.K {
188 t.Fatalf(
189 "result %d has incorrect kind, got %d, expected %d",
190 i, ev.Kind, testKind.K,
191 )
192 }
193 if !bytes.Equal(ev.Pubkey[:], events[1].Pubkey[:]) {
194 t.Fatalf(
195 "result %d has incorrect author, got %x, expected %x",
196 i, ev.Pubkey, events[1].Pubkey,
197 )
198 }
199 break
200 }
201 }
202 if !found {
203 t.Fatalf(
204 "result %d with ID %x not found in events", i,
205 result.Id,
206 )
207 }
208 }
209 }
210 211 // Test querying by kind and tag
212 idTsPk, err = db.QueryForIds(
213 ctx, &filter.F{
214 Kinds: kind.NewS(kind.New(testEventForTag.Kind)),
215 Tags: tagsFilter,
216 },
217 )
218 if err != nil {
219 t.Fatalf("Failed to query for kinds and tags: %v", err)
220 }
221 222 // Verify we got results
223 if len(idTsPk) == 0 {
224 t.Fatal("did not find any events with the specified kind and tag")
225 }
226 227 // Verify the results have the correct kind and tag
228 for i, result := range idTsPk {
229 // Find the event with this ID
230 var found bool
231 for _, ev := range events {
232 if bytes.Equal(result.Id[:], ev.ID[:]) {
233 found = true
234 if ev.Kind != testEventForTag.Kind {
235 t.Fatalf(
236 "result %d has incorrect kind, got %d, expected %d",
237 i, ev.Kind, testEventForTag.Kind,
238 )
239 }
240 241 // Check if the event has the tag we're looking for
242 var hasTag bool
243 for _, tg := range *ev.Tags {
244 if tg.Len() >= 2 && len(tg.Key()) == 1 {
245 if bytes.Equal(
246 tg.Key(), testTag.Key(),
247 ) && bytes.Equal(tg.Value(), testTag.Value()) {
248 hasTag = true
249 break
250 }
251 }
252 }
253 254 if !hasTag {
255 t.Fatalf(
256 "result %d does not have the expected tag",
257 i,
258 )
259 }
260 261 break
262 }
263 }
264 if !found {
265 t.Fatalf(
266 "result %d with ID %x not found in events", i, result.Id,
267 )
268 }
269 }
270 271 // Test querying by kind, author, and tag
272 idTsPk, err = db.QueryForIds(
273 ctx, &filter.F{
274 Kinds: kind.NewS(kind.New(testEventForTag.Kind)),
275 Authors: tag.NewFromBytesSlice(testEventForTag.Pubkey),
276 Tags: tagsFilter,
277 },
278 )
279 if err != nil {
280 t.Fatalf("Failed to query for kinds, authors, and tags: %v", err)
281 }
282 283 // Verify we got results
284 if len(idTsPk) == 0 {
285 t.Fatal("did not find any events with the specified kind, author, and tag")
286 }
287 288 // Verify the results have the correct kind, author, and tag
289 for i, result := range idTsPk {
290 // Find the event with this ID
291 var found bool
292 for _, ev := range events {
293 if bytes.Equal(result.Id[:], ev.ID[:]) {
294 found = true
295 if ev.Kind != testEventForTag.Kind {
296 t.Fatalf(
297 "result %d has incorrect kind, got %d, expected %d",
298 i, ev.Kind, testEventForTag.Kind,
299 )
300 }
301 302 if !bytes.Equal(ev.Pubkey[:], testEventForTag.Pubkey[:]) {
303 t.Fatalf(
304 "result %d has incorrect author, got %x, expected %x",
305 i, ev.Pubkey, testEventForTag.Pubkey,
306 )
307 }
308 309 // Check if the event has the tag we're looking for
310 var hasTag bool
311 for _, tg := range *ev.Tags {
312 if tg.Len() >= 2 && len(tg.Key()) == 1 {
313 if bytes.Equal(
314 tg.Key(), testTag.Key(),
315 ) && bytes.Equal(tg.Value(), testTag.Value()) {
316 hasTag = true
317 break
318 }
319 }
320 }
321 322 if !hasTag {
323 t.Fatalf(
324 "result %d does not have the expected tag",
325 i,
326 )
327 }
328 329 break
330 }
331 }
332 if !found {
333 t.Fatalf(
334 "result %d with ID %x not found in events", i, result.Id,
335 )
336 }
337 }
338 339 // Test querying by author and tag
340 idTsPk, err = db.QueryForIds(
341 ctx, &filter.F{
342 Authors: tag.NewFromBytesSlice(testEventForTag.Pubkey),
343 Tags: tagsFilter,
344 },
345 )
346 if err != nil {
347 t.Fatalf("Failed to query for authors and tags: %v", err)
348 }
349 350 // Verify we got results
351 if len(idTsPk) == 0 {
352 t.Fatal("did not find any events with the specified author and tag")
353 }
354 355 // Verify the results have the correct author and tag
356 for i, result := range idTsPk {
357 // Find the event with this ID
358 var found bool
359 for _, ev := range events {
360 if bytes.Equal(result.Id[:], ev.ID[:]) {
361 found = true
362 363 if !bytes.Equal(ev.Pubkey[:], testEventForTag.Pubkey[:]) {
364 t.Fatalf(
365 "result %d has incorrect author, got %x, expected %x",
366 i, ev.Pubkey, testEventForTag.Pubkey,
367 )
368 }
369 370 // Check if the event has the tag we're looking for
371 var hasTag bool
372 for _, tg := range *ev.Tags {
373 if tg.Len() >= 2 && len(tg.Key()) == 1 {
374 if bytes.Equal(
375 tg.Key(), testTag.Key(),
376 ) && bytes.Equal(tg.Value(), testTag.Value()) {
377 hasTag = true
378 break
379 }
380 }
381 }
382 383 if !hasTag {
384 t.Fatalf(
385 "result %d does not have the expected tag",
386 i,
387 )
388 }
389 390 break
391 }
392 }
393 if !found {
394 t.Fatalf(
395 "result %d with ID %x not found in events", i, result.Id,
396 )
397 }
398 }
399 }
400 401 // Test querying by created_at range
402 // Use the timestamp from the middle event as a reference
403 middleIndex := len(events) / 2
404 middleEvent := events[middleIndex]
405 406 // Create a timestamp range that includes events before and after the middle event
407 sinceTime := new(timestamp.T)
408 sinceTime.V = middleEvent.CreatedAt - 3600 // 1 hour before middle event
409 410 untilTime := new(timestamp.T)
411 untilTime.V = middleEvent.CreatedAt + 3600 // 1 hour after middle event
412 413 idTsPk, err = db.QueryForIds(
414 ctx, &filter.F{
415 Since: sinceTime,
416 Until: untilTime,
417 },
418 )
419 if err != nil {
420 t.Fatalf("Failed to query for created_at range: %v", err)
421 }
422 423 // Verify we got results
424 if len(idTsPk) == 0 {
425 t.Fatal("did not find any events in the specified time range")
426 }
427 428 // Verify the results exist in our events slice
429 for i, result := range idTsPk {
430 // Find the event with this ID
431 var found bool
432 for _, ev := range events {
433 if bytes.Equal(result.Id[:], ev.ID[:]) {
434 found = true
435 break
436 }
437 }
438 if !found {
439 t.Fatalf("result %d with ID %x not found in events", i, result.Id)
440 }
441 }
442 }
443