You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
304 lines
7.0 KiB
304 lines
7.0 KiB
package database |
|
|
|
import ( |
|
"bytes" |
|
"testing" |
|
|
|
"lol.mleku.dev/chk" |
|
"next.orly.dev/pkg/crypto/sha256" |
|
"next.orly.dev/pkg/database/indexes" |
|
types2 "next.orly.dev/pkg/database/indexes/types" |
|
"next.orly.dev/pkg/encoders/event" |
|
"next.orly.dev/pkg/encoders/kind" |
|
"next.orly.dev/pkg/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 6 for a basic event without tags) |
|
if len(idxs) != 6 { |
|
t.Fatalf("Expected 6 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 14 for an event with 2 tags) |
|
// 6 basic indexes + 4 indexes per tag (TagPubkey, Tag, TagKind, TagKindPubkey) |
|
if len(idxs) != 14 { |
|
t.Fatalf("Expected 14 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 |
|
}
|
|
|