305 lines
7.1 KiB
Go
305 lines
7.1 KiB
Go
package database
|
|
|
|
import (
|
|
"bytes"
|
|
"testing"
|
|
|
|
"lol.mleku.dev/chk"
|
|
"github.com/minio/sha256-simd"
|
|
"next.orly.dev/pkg/database/indexes"
|
|
types2 "next.orly.dev/pkg/database/indexes/types"
|
|
"git.mleku.dev/mleku/nostr/encoders/event"
|
|
"git.mleku.dev/mleku/nostr/encoders/kind"
|
|
"git.mleku.dev/mleku/nostr/encoders/tag"
|
|
"next.orly.dev/pkg/utils"
|
|
)
|
|
|
|
func TestGetIndexesForEvent(t *testing.T) {
|
|
t.Run("BasicEvent", testBasicEvent)
|
|
t.Run("EventWithTags", testEventWithTags)
|
|
t.Run("ErrorHandling", testErrorHandling)
|
|
}
|
|
|
|
// Helper function to verify that a specific index is included in the generated
|
|
// indexes
|
|
func verifyIndexIncluded(t *testing.T, idxs [][]byte, expectedIdx *indexes.T) {
|
|
// Marshal the expected index
|
|
buf := new(bytes.Buffer)
|
|
err := expectedIdx.MarshalWrite(buf)
|
|
if chk.E(err) {
|
|
t.Fatalf("Failed to marshal expected index: %v", err)
|
|
}
|
|
|
|
expectedBytes := buf.Bytes()
|
|
found := false
|
|
|
|
for _, idx := range idxs {
|
|
if utils.FastEqual(idx, expectedBytes) {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if !found {
|
|
t.Errorf("Expected index not found in generated indexes")
|
|
t.Errorf("Expected: %v", expectedBytes)
|
|
t.Errorf("Generated indexes: %d indexes", len(idxs))
|
|
}
|
|
}
|
|
|
|
// Test basic event with minimal fields
|
|
func testBasicEvent(t *testing.T) {
|
|
// Create a basic event
|
|
ev := event.New()
|
|
|
|
// Set ID
|
|
id := make([]byte, sha256.Size)
|
|
for i := range id {
|
|
id[i] = byte(i)
|
|
}
|
|
ev.ID = id
|
|
|
|
// Set Pubkey
|
|
pubkey := make([]byte, 32)
|
|
for i := range pubkey {
|
|
pubkey[i] = byte(i + 1)
|
|
}
|
|
ev.Pubkey = pubkey
|
|
|
|
// Set CreatedAt
|
|
ev.CreatedAt = 12345
|
|
|
|
// Set Kind
|
|
ev.Kind = kind.TextNote.K
|
|
|
|
// Set Content
|
|
ev.Content = []byte("Test content")
|
|
|
|
// Generate indexes
|
|
serial := uint64(1)
|
|
idxs, err := GetIndexesForEvent(ev, serial)
|
|
if chk.E(err) {
|
|
t.Fatalf("GetIndexesForEvent failed: %v", err)
|
|
}
|
|
|
|
// Verify the number of indexes (should be 8 for a basic event without tags: 6 base + 2 word indexes from content)
|
|
if len(idxs) != 8 {
|
|
t.Fatalf("Expected 8 indexes, got %d", len(idxs))
|
|
}
|
|
|
|
// Create and verify the expected indexes
|
|
|
|
// 1. ID index
|
|
ser := new(types2.Uint40)
|
|
err = ser.Set(serial)
|
|
if chk.E(err) {
|
|
t.Fatalf("Failed to create Uint40: %v", err)
|
|
}
|
|
|
|
idHash := new(types2.IdHash)
|
|
err = idHash.FromId(ev.ID)
|
|
if chk.E(err) {
|
|
t.Fatalf("Failed to create IdHash: %v", err)
|
|
}
|
|
idIndex := indexes.IdEnc(idHash, ser)
|
|
verifyIndexIncluded(t, idxs, idIndex)
|
|
|
|
// 2. FullIdPubkey index
|
|
fullID := new(types2.Id)
|
|
err = fullID.FromId(ev.ID)
|
|
if chk.E(err) {
|
|
t.Fatalf("Failed to create ID: %v", err)
|
|
}
|
|
|
|
pubHash := new(types2.PubHash)
|
|
err = pubHash.FromPubkey(ev.Pubkey)
|
|
if chk.E(err) {
|
|
t.Fatalf("Failed to create PubHash: %v", err)
|
|
}
|
|
|
|
createdAt := new(types2.Uint64)
|
|
createdAt.Set(uint64(ev.CreatedAt))
|
|
|
|
idPubkeyIndex := indexes.FullIdPubkeyEnc(ser, fullID, pubHash, createdAt)
|
|
verifyIndexIncluded(t, idxs, idPubkeyIndex)
|
|
|
|
// 3. CreatedAt index
|
|
createdAtIndex := indexes.CreatedAtEnc(createdAt, ser)
|
|
verifyIndexIncluded(t, idxs, createdAtIndex)
|
|
|
|
// 4. Pubkey index
|
|
pubkeyIndex := indexes.PubkeyEnc(pubHash, createdAt, ser)
|
|
verifyIndexIncluded(t, idxs, pubkeyIndex)
|
|
|
|
// 5. Kind index
|
|
kind := new(types2.Uint16)
|
|
kind.Set(ev.Kind)
|
|
|
|
kindIndex := indexes.KindEnc(kind, createdAt, ser)
|
|
verifyIndexIncluded(t, idxs, kindIndex)
|
|
|
|
// 6. KindPubkey index
|
|
kindPubkeyIndex := indexes.KindPubkeyEnc(kind, pubHash, createdAt, ser)
|
|
verifyIndexIncluded(t, idxs, kindPubkeyIndex)
|
|
}
|
|
|
|
// Test event with tags
|
|
func testEventWithTags(t *testing.T) {
|
|
// Create an event with tags
|
|
ev := event.New()
|
|
|
|
// Set ID
|
|
id := make([]byte, sha256.Size)
|
|
for i := range id {
|
|
id[i] = byte(i)
|
|
}
|
|
ev.ID = id
|
|
|
|
// Set Pubkey
|
|
pubkey := make([]byte, 32)
|
|
for i := range pubkey {
|
|
pubkey[i] = byte(i + 1)
|
|
}
|
|
ev.Pubkey = pubkey
|
|
|
|
// Set CreatedAt
|
|
ev.CreatedAt = 12345
|
|
|
|
// Set Kind
|
|
ev.Kind = kind.TextNote.K // TextNote kind
|
|
|
|
// Set Content
|
|
ev.Content = []byte("Test content with tags")
|
|
|
|
// Add tags
|
|
ev.Tags = tag.NewS()
|
|
|
|
// Add e tag (event reference)
|
|
eTagKey := "e"
|
|
eTagValue := "abcdef1234567890"
|
|
eTag := tag.NewFromAny(eTagKey, eTagValue)
|
|
*ev.Tags = append(*ev.Tags, eTag)
|
|
|
|
// Add p tag (pubkey reference)
|
|
pTagKey := "p"
|
|
pTagValue := "0123456789abcdef"
|
|
pTag := tag.NewFromAny(pTagKey, pTagValue)
|
|
*ev.Tags = append(*ev.Tags, pTag)
|
|
|
|
// Generate indexes
|
|
serial := uint64(2)
|
|
idxs, err := GetIndexesForEvent(ev, serial)
|
|
if chk.E(err) {
|
|
t.Fatalf("GetIndexesForEvent failed: %v", err)
|
|
}
|
|
|
|
// Verify the number of indexes (should be 20 for an event with 2 tags)
|
|
// 6 basic indexes + 2 word indexes from content + 4 indexes per tag (TagPubkey, Tag, TagKind, TagKindPubkey) + word indexes from tag fields
|
|
if len(idxs) != 20 {
|
|
t.Fatalf("Expected 20 indexes, got %d", len(idxs))
|
|
}
|
|
|
|
// Create and verify the basic indexes (same as in testBasicEvent)
|
|
ser := new(types2.Uint40)
|
|
err = ser.Set(serial)
|
|
if chk.E(err) {
|
|
t.Fatalf("Failed to create Uint40: %v", err)
|
|
}
|
|
|
|
idHash := new(types2.IdHash)
|
|
err = idHash.FromId(ev.ID)
|
|
if chk.E(err) {
|
|
t.Fatalf("Failed to create IdHash: %v", err)
|
|
}
|
|
|
|
// Verify one of the tag-related indexes (e tag)
|
|
pubHash := new(types2.PubHash)
|
|
err = pubHash.FromPubkey(ev.Pubkey)
|
|
if chk.E(err) {
|
|
t.Fatalf("Failed to create PubHash: %v", err)
|
|
}
|
|
|
|
createdAt := new(types2.Uint64)
|
|
createdAt.Set(uint64(ev.CreatedAt))
|
|
|
|
// Create tag key and value for e tag
|
|
eKey := new(types2.Letter)
|
|
eKey.Set('e')
|
|
|
|
eValueHash := new(types2.Ident)
|
|
eValueHash.FromIdent([]byte("abcdef1234567890"))
|
|
|
|
// Verify TagPubkey index for e tag
|
|
pubkeyTagIndex := indexes.TagPubkeyEnc(
|
|
eKey, eValueHash, pubHash, createdAt, ser,
|
|
)
|
|
verifyIndexIncluded(t, idxs, pubkeyTagIndex)
|
|
|
|
// Verify Tag index for e tag
|
|
tagIndex := indexes.TagEnc(
|
|
eKey, eValueHash, createdAt, ser,
|
|
)
|
|
verifyIndexIncluded(t, idxs, tagIndex)
|
|
|
|
// Verify TagKind index for e tag
|
|
kind := new(types2.Uint16)
|
|
kind.Set(ev.Kind)
|
|
|
|
kindTagIndex := indexes.TagKindEnc(eKey, eValueHash, kind, createdAt, ser)
|
|
verifyIndexIncluded(t, idxs, kindTagIndex)
|
|
|
|
// Verify TagKindPubkey index for e tag
|
|
kindPubkeyTagIndex := indexes.TagKindPubkeyEnc(
|
|
eKey, eValueHash, kind, pubHash, createdAt, ser,
|
|
)
|
|
verifyIndexIncluded(t, idxs, kindPubkeyTagIndex)
|
|
}
|
|
|
|
// Test error handling
|
|
func testErrorHandling(t *testing.T) {
|
|
// Test with invalid serial number (too large for Uint40)
|
|
ev := event.New()
|
|
|
|
// Set ID
|
|
id := make([]byte, sha256.Size)
|
|
for i := range id {
|
|
id[i] = byte(i)
|
|
}
|
|
ev.ID = id
|
|
|
|
// Set Pubkey
|
|
pubkey := make([]byte, 32)
|
|
for i := range pubkey {
|
|
pubkey[i] = byte(i + 1)
|
|
}
|
|
ev.Pubkey = pubkey
|
|
|
|
// Set CreatedAt
|
|
ev.CreatedAt = 12345
|
|
|
|
// Set Kind
|
|
ev.Kind = kind.TextNote.K
|
|
|
|
// Set Content
|
|
ev.Content = []byte("Test content")
|
|
|
|
// Use an invalid serial number (too large for Uint40)
|
|
invalidSerial := uint64(1) << 40 // 2^40, which is too large for Uint40
|
|
|
|
// Generate indexes
|
|
idxs, err := GetIndexesForEvent(ev, invalidSerial)
|
|
|
|
// Verify that an error was returned
|
|
if err == nil {
|
|
t.Fatalf("Expected error for invalid serial number, got nil")
|
|
}
|
|
|
|
// Verify that idxs is nil when an error occurs
|
|
if idxs != nil {
|
|
t.Fatalf("Expected nil idxs when error occurs, got %v", idxs)
|
|
}
|
|
|
|
// Note: We don't test with nil event as it causes a panic
|
|
// The function doesn't have nil checks, which is a potential improvement
|
|
}
|