Added example usage code for MultiIndex. Added unit tests for MultiIndex
This commit is contained in:
parent
63e321fd20
commit
a962e4acb7
2 changed files with 244 additions and 0 deletions
202
internal/utils/multiindex_test.go
Normal file
202
internal/utils/multiindex_test.go
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
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))
|
||||
}
|
||||
}
|
||||
42
main.go
42
main.go
|
|
@ -2,6 +2,7 @@ package main
|
|||
|
||||
import (
|
||||
"c65gm/internal/preproc"
|
||||
"c65gm/internal/utils"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
|
@ -35,7 +36,48 @@ const (
|
|||
ShowLineView
|
||||
)
|
||||
|
||||
func testMultiIndex() {
|
||||
type User struct {
|
||||
ID string
|
||||
FirstName string
|
||||
LastName string
|
||||
Email string
|
||||
}
|
||||
|
||||
// 2 indexes: [0]=email only, [1]=firstname+lastname
|
||||
idx := utils.NewMultiIndex[User](2)
|
||||
|
||||
idx.AddItem(User{"1", "John", "Doe", "john@example.com"}, [][]string{
|
||||
{"john@example.com"},
|
||||
{"john", "doe"},
|
||||
})
|
||||
|
||||
idx.AddItem(User{"2", "Jane", "Smith", "jane@example.com"}, [][]string{
|
||||
{"jane@example.com"},
|
||||
{"jane", "smith"},
|
||||
})
|
||||
|
||||
// Search by email (index 0, single string)
|
||||
user, found := idx.FindItem(0, []string{"john@example.com"})
|
||||
fmt.Println(user, found) // {1 John Doe john@example.com} true
|
||||
|
||||
// Search by name (index 1, two strings)
|
||||
user, found = idx.FindItem(1, []string{"jane", "smith"})
|
||||
fmt.Println(user, found) // {2 Jane Smith jane@example.com} true
|
||||
|
||||
// Wrong composite key fails
|
||||
user, found = idx.FindItem(1, []string{"jane", "doe"})
|
||||
fmt.Println(found) // false
|
||||
|
||||
// All items
|
||||
fmt.Println(idx.Items()) // [{1 John Doe john@example.com} {2 Jane Smith jane@example.com}]
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
testMultiIndex()
|
||||
|
||||
os.Exit(1)
|
||||
fmt.Println("c65cm - A 6502 Cross-Compiler for the ACME Cross-Assembler.")
|
||||
fmt.Println("Copyright (C) 1999, 2025 Mattias Hansson. v0.7")
|
||||
fmt.Println("Distributed under GPL. External library github.com/armon/go-radix under MIT.")
|
||||
|
|
|
|||
Loading…
Reference in a new issue