c65gm/internal/utils/multiindex_test.go

202 lines
4.4 KiB
Go

package utils
import (
"testing"
)
type TestUser struct {
ID string
Name string
Email string
}
func TestMultiIndex_AddAndFind(t *testing.T) {
idx := NewMultiIndex[TestUser](2)
user := TestUser{"1", "John Doe", "john@example.com"}
idx.AddItem(user, [][]string{
{"john@example.com"},
{"john", "doe"},
})
found, ok := idx.FindItem(0, []string{"john@example.com"})
if !ok {
t.Fatal("expected to find user by email")
}
if found.ID != "1" {
t.Errorf("got ID %s, want 1", found.ID)
}
found, ok = idx.FindItem(1, []string{"john", "doe"})
if !ok {
t.Fatal("expected to find user by name")
}
if found.Name != "John Doe" {
t.Errorf("got Name %s, want John Doe", found.Name)
}
}
func TestMultiIndex_NotFound(t *testing.T) {
idx := NewMultiIndex[TestUser](1)
idx.AddItem(TestUser{"1", "John", "john@example.com"}, [][]string{
{"john@example.com"},
})
_, ok := idx.FindItem(0, []string{"jane@example.com"})
if ok {
t.Error("expected not found")
}
}
func TestMultiIndex_WrongCompositeKey(t *testing.T) {
idx := NewMultiIndex[TestUser](1)
idx.AddItem(TestUser{"1", "John Doe", "john@example.com"}, [][]string{
{"john", "doe"},
})
_, ok := idx.FindItem(0, []string{"john", "smith"})
if ok {
t.Error("expected not found with wrong composite key")
}
_, ok = idx.FindItem(0, []string{"john"})
if ok {
t.Error("expected not found with partial key")
}
}
func TestMultiIndex_KeyCollisionHandling(t *testing.T) {
idx := NewMultiIndex[TestUser](1)
idx.AddItem(TestUser{"1", "User1", "user1@example.com"}, [][]string{
{"ab", "cd"},
})
idx.AddItem(TestUser{"2", "User2", "user2@example.com"}, [][]string{
{"abc", "d"},
})
found, ok := idx.FindItem(0, []string{"ab", "cd"})
if !ok || found.ID != "1" {
t.Error("collision: wrong user for ['ab', 'cd']")
}
found, ok = idx.FindItem(0, []string{"abc", "d"})
if !ok || found.ID != "2" {
t.Error("collision: wrong user for ['abc', 'd']")
}
}
func TestMultiIndex_InvalidIndex(t *testing.T) {
idx := NewMultiIndex[TestUser](2)
idx.AddItem(TestUser{"1", "John", "john@example.com"}, [][]string{
{"john@example.com"},
{"john"},
})
_, ok := idx.FindItem(-1, []string{"john@example.com"})
if ok {
t.Error("expected not found for negative index")
}
_, ok = idx.FindItem(5, []string{"john@example.com"})
if ok {
t.Error("expected not found for out of range index")
}
}
func TestMultiIndex_Items(t *testing.T) {
idx := NewMultiIndex[TestUser](1)
users := []TestUser{
{"1", "John", "john@example.com"},
{"2", "Jane", "jane@example.com"},
{"3", "Bob", "bob@example.com"},
}
for _, u := range users {
idx.AddItem(u, [][]string{{u.Email}})
}
items := idx.Items()
if len(items) != 3 {
t.Fatalf("got %d items, want 3", len(items))
}
for i, u := range users {
if items[i].ID != u.ID {
t.Errorf("item %d: got ID %s, want %s", i, items[i].ID, u.ID)
}
}
}
func TestMultiIndex_ItemsIsCopy(t *testing.T) {
idx := NewMultiIndex[TestUser](1)
idx.AddItem(TestUser{"1", "John", "john@example.com"}, [][]string{
{"john@example.com"},
})
items := idx.Items()
items[0].Name = "Modified"
original, _ := idx.FindItem(0, []string{"john@example.com"})
if original.Name != "John" {
t.Error("Items() should return a copy, not affect internal state")
}
}
func TestMultiIndex_PanicOnWrongKeysLength(t *testing.T) {
defer func() {
if r := recover(); r == nil {
t.Error("expected panic on wrong searchKeys length")
}
}()
idx := NewMultiIndex[TestUser](2)
idx.AddItem(TestUser{"1", "John", "john@example.com"}, [][]string{
{"john@example.com"},
// missing second index key
})
}
func TestMultiIndex_MultipleItemsSameIndex(t *testing.T) {
idx := NewMultiIndex[TestUser](2)
idx.AddItem(TestUser{"1", "John Doe", "john@example.com"}, [][]string{
{"john@example.com"},
{"john", "doe"},
})
idx.AddItem(TestUser{"2", "Jane Doe", "jane@example.com"}, [][]string{
{"jane@example.com"},
{"jane", "doe"},
})
john, ok := idx.FindItem(1, []string{"john", "doe"})
if !ok || john.ID != "1" {
t.Error("failed to find John by name")
}
jane, ok := idx.FindItem(1, []string{"jane", "doe"})
if !ok || jane.ID != "2" {
t.Error("failed to find Jane by name")
}
}
func TestMultiIndex_EmptyIndex(t *testing.T) {
idx := NewMultiIndex[TestUser](1)
_, ok := idx.FindItem(0, []string{"anything"})
if ok {
t.Error("expected not found in empty index")
}
items := idx.Items()
if len(items) != 0 {
t.Errorf("expected 0 items, got %d", len(items))
}
}