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)) } }