106 lines
3.1 KiB
Go
106 lines
3.1 KiB
Go
|
package truncindex
|
||
|
|
||
|
import "testing"
|
||
|
|
||
|
// Test the behavior of TruncIndex, an index for querying IDs from a non-conflicting prefix.
|
||
|
func TestTruncIndex(t *testing.T) {
|
||
|
ids := []string{}
|
||
|
index := NewTruncIndex(ids)
|
||
|
// Get on an empty index
|
||
|
if _, err := index.Get("foobar"); err == nil {
|
||
|
t.Fatal("Get on an empty index should return an error")
|
||
|
}
|
||
|
|
||
|
// Spaces should be illegal in an id
|
||
|
if err := index.Add("I have a space"); err == nil {
|
||
|
t.Fatalf("Adding an id with ' ' should return an error")
|
||
|
}
|
||
|
|
||
|
id := "99b36c2c326ccc11e726eee6ee78a0baf166ef96"
|
||
|
// Add an id
|
||
|
if err := index.Add(id); err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
// Get a non-existing id
|
||
|
assertIndexGet(t, index, "abracadabra", "", true)
|
||
|
// Get the exact id
|
||
|
assertIndexGet(t, index, id, id, false)
|
||
|
// The first letter should match
|
||
|
assertIndexGet(t, index, id[:1], id, false)
|
||
|
// The first half should match
|
||
|
assertIndexGet(t, index, id[:len(id)/2], id, false)
|
||
|
// The second half should NOT match
|
||
|
assertIndexGet(t, index, id[len(id)/2:], "", true)
|
||
|
|
||
|
id2 := id[:6] + "blabla"
|
||
|
// Add an id
|
||
|
if err := index.Add(id2); err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
// Both exact IDs should work
|
||
|
assertIndexGet(t, index, id, id, false)
|
||
|
assertIndexGet(t, index, id2, id2, false)
|
||
|
|
||
|
// 6 characters or less should conflict
|
||
|
assertIndexGet(t, index, id[:6], "", true)
|
||
|
assertIndexGet(t, index, id[:4], "", true)
|
||
|
assertIndexGet(t, index, id[:1], "", true)
|
||
|
|
||
|
// 7 characters should NOT conflict
|
||
|
assertIndexGet(t, index, id[:7], id, false)
|
||
|
assertIndexGet(t, index, id2[:7], id2, false)
|
||
|
|
||
|
// Deleting a non-existing id should return an error
|
||
|
if err := index.Delete("non-existing"); err == nil {
|
||
|
t.Fatalf("Deleting a non-existing id should return an error")
|
||
|
}
|
||
|
|
||
|
// Deleting id2 should remove conflicts
|
||
|
if err := index.Delete(id2); err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
// id2 should no longer work
|
||
|
assertIndexGet(t, index, id2, "", true)
|
||
|
assertIndexGet(t, index, id2[:7], "", true)
|
||
|
assertIndexGet(t, index, id2[:11], "", true)
|
||
|
|
||
|
// conflicts between id and id2 should be gone
|
||
|
assertIndexGet(t, index, id[:6], id, false)
|
||
|
assertIndexGet(t, index, id[:4], id, false)
|
||
|
assertIndexGet(t, index, id[:1], id, false)
|
||
|
|
||
|
// non-conflicting substrings should still not conflict
|
||
|
assertIndexGet(t, index, id[:7], id, false)
|
||
|
assertIndexGet(t, index, id[:15], id, false)
|
||
|
assertIndexGet(t, index, id, id, false)
|
||
|
}
|
||
|
|
||
|
func assertIndexGet(t *testing.T, index *TruncIndex, input, expectedResult string, expectError bool) {
|
||
|
if result, err := index.Get(input); err != nil && !expectError {
|
||
|
t.Fatalf("Unexpected error getting '%s': %s", input, err)
|
||
|
} else if err == nil && expectError {
|
||
|
t.Fatalf("Getting '%s' should return an error", input)
|
||
|
} else if result != expectedResult {
|
||
|
t.Fatalf("Getting '%s' returned '%s' instead of '%s'", input, result, expectedResult)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func BenchmarkTruncIndexAdd(b *testing.B) {
|
||
|
ids := []string{"banana", "bananaa", "bananab"}
|
||
|
b.ResetTimer()
|
||
|
for i := 0; i < b.N; i++ {
|
||
|
index := NewTruncIndex([]string{})
|
||
|
for _, id := range ids {
|
||
|
index.Add(id)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func BenchmarkTruncIndexNew(b *testing.B) {
|
||
|
ids := []string{"banana", "bananaa", "bananab"}
|
||
|
b.ResetTimer()
|
||
|
for i := 0; i < b.N; i++ {
|
||
|
NewTruncIndex(ids)
|
||
|
}
|
||
|
}
|