summaryrefslogtreecommitdiff
path: root/vendor/src/github.com/tchap/go-patricia/patricia/patricia_sparse_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/src/github.com/tchap/go-patricia/patricia/patricia_sparse_test.go')
-rw-r--r--vendor/src/github.com/tchap/go-patricia/patricia/patricia_sparse_test.go659
1 files changed, 659 insertions, 0 deletions
diff --git a/vendor/src/github.com/tchap/go-patricia/patricia/patricia_sparse_test.go b/vendor/src/github.com/tchap/go-patricia/patricia/patricia_sparse_test.go
new file mode 100644
index 0000000000..27f3c878b5
--- /dev/null
+++ b/vendor/src/github.com/tchap/go-patricia/patricia/patricia_sparse_test.go
@@ -0,0 +1,659 @@
+// Copyright (c) 2014 The go-patricia AUTHORS
+//
+// Use of this source code is governed by The MIT License
+// that can be found in the LICENSE file.
+
+package patricia
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "strings"
+ "testing"
+)
+
+const (
+ success = true
+ failure = false
+)
+
+type testData struct {
+ key string
+ value interface{}
+ retVal bool
+}
+
+// Tests -----------------------------------------------------------------------
+
+func TestTrie_InsertDifferentPrefixes(t *testing.T) {
+ trie := NewTrie()
+
+ data := []testData{
+ {"Pepaneeeeeeeeeeeeee", "Pepan Zdepan", success},
+ {"Honzooooooooooooooo", "Honza Novak", success},
+ {"Jenikuuuuuuuuuuuuuu", "Jenik Poustevnicek", success},
+ }
+
+ for _, v := range data {
+ t.Logf("INSERT prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal)
+ if ok := trie.Insert(Prefix(v.key), v.value); ok != v.retVal {
+ t.Errorf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
+ }
+ }
+}
+
+func TestTrie_InsertDuplicatePrefixes(t *testing.T) {
+ trie := NewTrie()
+
+ data := []testData{
+ {"Pepan", "Pepan Zdepan", success},
+ {"Pepan", "Pepan Zdepan", failure},
+ }
+
+ for _, v := range data {
+ t.Logf("INSERT prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal)
+ if ok := trie.Insert(Prefix(v.key), v.value); ok != v.retVal {
+ t.Errorf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
+ }
+ }
+}
+
+func TestTrie_InsertVariousPrefixes(t *testing.T) {
+ trie := NewTrie()
+
+ data := []testData{
+ {"Pepan", "Pepan Zdepan", success},
+ {"Pepin", "Pepin Omacka", success},
+ {"Honza", "Honza Novak", success},
+ {"Jenik", "Jenik Poustevnicek", success},
+ {"Pepan", "Pepan Dupan", failure},
+ {"Karel", "Karel Pekar", success},
+ {"Jenik", "Jenik Poustevnicek", failure},
+ {"Pepanek", "Pepanek Zemlicka", success},
+ }
+
+ for _, v := range data {
+ t.Logf("INSERT prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal)
+ if ok := trie.Insert(Prefix(v.key), v.value); ok != v.retVal {
+ t.Errorf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
+ }
+ }
+}
+
+func TestTrie_InsertAndMatchPrefix(t *testing.T) {
+ trie := NewTrie()
+ t.Log("INSERT prefix=by week")
+ trie.Insert(Prefix("by week"), 2)
+ t.Log("INSERT prefix=by")
+ trie.Insert(Prefix("by"), 1)
+
+ if !trie.Match(Prefix("by")) {
+ t.Error("MATCH prefix=by, expected=true, got=false")
+ }
+}
+
+func TestTrie_SetGet(t *testing.T) {
+ trie := NewTrie()
+
+ data := []testData{
+ {"Pepan", "Pepan Zdepan", success},
+ {"Pepin", "Pepin Omacka", success},
+ {"Honza", "Honza Novak", success},
+ {"Jenik", "Jenik Poustevnicek", success},
+ {"Pepan", "Pepan Dupan", failure},
+ {"Karel", "Karel Pekar", success},
+ {"Jenik", "Jenik Poustevnicek", failure},
+ {"Pepanek", "Pepanek Zemlicka", success},
+ }
+
+ for _, v := range data {
+ t.Logf("INSERT prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal)
+ if ok := trie.Insert(Prefix(v.key), v.value); ok != v.retVal {
+ t.Errorf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
+ }
+ }
+
+ for _, v := range data {
+ t.Logf("SET %q to 10", v.key)
+ trie.Set(Prefix(v.key), 10)
+ }
+
+ for _, v := range data {
+ value := trie.Get(Prefix(v.key))
+ t.Logf("GET %q => %v", v.key, value)
+ if value.(int) != 10 {
+ t.Errorf("Unexpected return value, != 10", value)
+ }
+ }
+
+ if value := trie.Get(Prefix("random crap")); value != nil {
+ t.Errorf("Unexpected return value, %v != <nil>", value)
+ }
+}
+
+func TestTrie_Match(t *testing.T) {
+ trie := NewTrie()
+
+ data := []testData{
+ {"Pepan", "Pepan Zdepan", success},
+ {"Pepin", "Pepin Omacka", success},
+ {"Honza", "Honza Novak", success},
+ {"Jenik", "Jenik Poustevnicek", success},
+ {"Pepan", "Pepan Dupan", failure},
+ {"Karel", "Karel Pekar", success},
+ {"Jenik", "Jenik Poustevnicek", failure},
+ {"Pepanek", "Pepanek Zemlicka", success},
+ }
+
+ for _, v := range data {
+ t.Logf("INSERT prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal)
+ if ok := trie.Insert(Prefix(v.key), v.value); ok != v.retVal {
+ t.Errorf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
+ }
+ }
+
+ for _, v := range data {
+ matched := trie.Match(Prefix(v.key))
+ t.Logf("MATCH %q => %v", v.key, matched)
+ if !matched {
+ t.Errorf("Inserted key %q was not matched", v.key)
+ }
+ }
+
+ if trie.Match(Prefix("random crap")) {
+ t.Errorf("Key that was not inserted matched: %q", "random crap")
+ }
+}
+
+func TestTrie_MatchFalsePositive(t *testing.T) {
+ trie := NewTrie()
+
+ if ok := trie.Insert(Prefix("A"), 1); !ok {
+ t.Fatal("INSERT prefix=A, item=1 not ok")
+ }
+
+ resultMatchSubtree := trie.MatchSubtree(Prefix("A extra"))
+ resultMatch := trie.Match(Prefix("A extra"))
+
+ if resultMatchSubtree != false {
+ t.Error("MatchSubtree returned false positive")
+ }
+
+ if resultMatch != false {
+ t.Error("Match returned false positive")
+ }
+}
+
+func TestTrie_MatchSubtree(t *testing.T) {
+ trie := NewTrie()
+
+ data := []testData{
+ {"Pepan", "Pepan Zdepan", success},
+ {"Pepin", "Pepin Omacka", success},
+ {"Honza", "Honza Novak", success},
+ {"Jenik", "Jenik Poustevnicek", success},
+ {"Pepan", "Pepan Dupan", failure},
+ {"Karel", "Karel Pekar", success},
+ {"Jenik", "Jenik Poustevnicek", failure},
+ {"Pepanek", "Pepanek Zemlicka", success},
+ }
+
+ for _, v := range data {
+ t.Logf("INSERT prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal)
+ if ok := trie.Insert(Prefix(v.key), v.value); ok != v.retVal {
+ t.Errorf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
+ }
+ }
+
+ for _, v := range data {
+ key := Prefix(v.key[:3])
+ matched := trie.MatchSubtree(key)
+ t.Logf("MATCH_SUBTREE %q => %v", key, matched)
+ if !matched {
+ t.Errorf("Subtree %q was not matched", v.key)
+ }
+ }
+}
+
+func TestTrie_Visit(t *testing.T) {
+ trie := NewTrie()
+
+ data := []testData{
+ {"Pepa", 0, success},
+ {"Pepa Zdepa", 1, success},
+ {"Pepa Kuchar", 2, success},
+ {"Honza", 3, success},
+ {"Jenik", 4, success},
+ }
+
+ for _, v := range data {
+ t.Logf("INSERT prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal)
+ if ok := trie.Insert([]byte(v.key), v.value); ok != v.retVal {
+ t.Fatalf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
+ }
+ }
+
+ if err := trie.Visit(func(prefix Prefix, item Item) error {
+ name := data[item.(int)].key
+ t.Logf("VISITING prefix=%q, item=%v", prefix, item)
+ if !strings.HasPrefix(string(prefix), name) {
+ t.Errorf("Unexpected prefix encountered, %q not a prefix of %q", prefix, name)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestTrie_VisitSkipSubtree(t *testing.T) {
+ trie := NewTrie()
+
+ data := []testData{
+ {"Pepa", 0, success},
+ {"Pepa Zdepa", 1, success},
+ {"Pepa Kuchar", 2, success},
+ {"Honza", 3, success},
+ {"Jenik", 4, success},
+ }
+
+ for _, v := range data {
+ t.Logf("INSERT prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal)
+ if ok := trie.Insert([]byte(v.key), v.value); ok != v.retVal {
+ t.Fatalf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
+ }
+ }
+
+ if err := trie.Visit(func(prefix Prefix, item Item) error {
+ t.Logf("VISITING prefix=%q, item=%v", prefix, item)
+ if item.(int) == 0 {
+ t.Logf("SKIP %q", prefix)
+ return SkipSubtree
+ }
+ if strings.HasPrefix(string(prefix), "Pepa") {
+ t.Errorf("Unexpected prefix encountered, %q", prefix)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestTrie_VisitReturnError(t *testing.T) {
+ trie := NewTrie()
+
+ data := []testData{
+ {"Pepa", 0, success},
+ {"Pepa Zdepa", 1, success},
+ {"Pepa Kuchar", 2, success},
+ {"Honza", 3, success},
+ {"Jenik", 4, success},
+ }
+
+ for _, v := range data {
+ t.Logf("INSERT prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal)
+ if ok := trie.Insert([]byte(v.key), v.value); ok != v.retVal {
+ t.Fatalf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
+ }
+ }
+
+ someErr := errors.New("Something exploded")
+ if err := trie.Visit(func(prefix Prefix, item Item) error {
+ t.Logf("VISITING prefix=%q, item=%v", prefix, item)
+ if item.(int) == 0 {
+ return someErr
+ }
+ if item.(int) != 0 {
+ t.Errorf("Unexpected prefix encountered, %q", prefix)
+ }
+ return nil
+ }); err != nil && err != someErr {
+ t.Fatal(err)
+ }
+}
+
+func TestTrie_VisitSubtree(t *testing.T) {
+ trie := NewTrie()
+
+ data := []testData{
+ {"Pepa", 0, success},
+ {"Pepa Zdepa", 1, success},
+ {"Pepa Kuchar", 2, success},
+ {"Honza", 3, success},
+ {"Jenik", 4, success},
+ }
+
+ for _, v := range data {
+ t.Logf("INSERT prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal)
+ if ok := trie.Insert([]byte(v.key), v.value); ok != v.retVal {
+ t.Fatalf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
+ }
+ }
+
+ var counter int
+ subtreePrefix := []byte("Pep")
+ t.Log("VISIT Pep")
+ if err := trie.VisitSubtree(subtreePrefix, func(prefix Prefix, item Item) error {
+ t.Logf("VISITING prefix=%q, item=%v", prefix, item)
+ if !bytes.HasPrefix(prefix, subtreePrefix) {
+ t.Errorf("Unexpected prefix encountered, %q does not extend %q",
+ prefix, subtreePrefix)
+ }
+ if len(prefix) > len(data[item.(int)].key) {
+ t.Fatalf("Something is rather fishy here, prefix=%q", prefix)
+ }
+ counter++
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ if counter != 3 {
+ t.Error("Unexpected number of nodes visited")
+ }
+}
+
+func TestTrie_VisitPrefixes(t *testing.T) {
+ trie := NewTrie()
+
+ data := []testData{
+ {"P", 0, success},
+ {"Pe", 1, success},
+ {"Pep", 2, success},
+ {"Pepa", 3, success},
+ {"Pepa Zdepa", 4, success},
+ {"Pepa Kuchar", 5, success},
+ {"Honza", 6, success},
+ {"Jenik", 7, success},
+ }
+
+ for _, v := range data {
+ t.Logf("INSERT prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal)
+ if ok := trie.Insert([]byte(v.key), v.value); ok != v.retVal {
+ t.Fatalf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
+ }
+ }
+
+ var counter int
+ word := []byte("Pepa")
+ if err := trie.VisitPrefixes(word, func(prefix Prefix, item Item) error {
+ t.Logf("VISITING prefix=%q, item=%v", prefix, item)
+ if !bytes.HasPrefix(word, prefix) {
+ t.Errorf("Unexpected prefix encountered, %q is not a prefix of %q",
+ prefix, word)
+ }
+ counter++
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ if counter != 4 {
+ t.Error("Unexpected number of nodes visited")
+ }
+}
+
+func TestParticiaTrie_Delete(t *testing.T) {
+ trie := NewTrie()
+
+ data := []testData{
+ {"Pepan", "Pepan Zdepan", success},
+ {"Honza", "Honza Novak", success},
+ {"Jenik", "Jenik Poustevnicek", success},
+ }
+
+ for _, v := range data {
+ t.Logf("INSERT prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal)
+ if ok := trie.Insert([]byte(v.key), v.value); ok != v.retVal {
+ t.Fatalf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
+ }
+ }
+
+ for _, v := range data {
+ t.Logf("DELETE word=%v, success=%v", v.key, v.retVal)
+ if ok := trie.Delete([]byte(v.key)); ok != v.retVal {
+ t.Errorf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
+ }
+ }
+}
+
+func TestParticiaTrie_DeleteNonExistent(t *testing.T) {
+ trie := NewTrie()
+
+ insertData := []testData{
+ {"Pepan", "Pepan Zdepan", success},
+ {"Honza", "Honza Novak", success},
+ {"Jenik", "Jenik Poustevnicek", success},
+ }
+ deleteData := []testData{
+ {"Pepan", "Pepan Zdepan", success},
+ {"Honza", "Honza Novak", success},
+ {"Pepan", "Pepan Zdepan", failure},
+ {"Jenik", "Jenik Poustevnicek", success},
+ {"Honza", "Honza Novak", failure},
+ }
+
+ for _, v := range insertData {
+ t.Logf("INSERT prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal)
+ if ok := trie.Insert([]byte(v.key), v.value); ok != v.retVal {
+ t.Fatalf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
+ }
+ }
+
+ for _, v := range deleteData {
+ t.Logf("DELETE word=%v, success=%v", v.key, v.retVal)
+ if ok := trie.Delete([]byte(v.key)); ok != v.retVal {
+ t.Errorf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
+ }
+ }
+}
+
+func TestParticiaTrie_DeleteSubtree(t *testing.T) {
+ trie := NewTrie()
+
+ insertData := []testData{
+ {"P", 0, success},
+ {"Pe", 1, success},
+ {"Pep", 2, success},
+ {"Pepa", 3, success},
+ {"Pepa Zdepa", 4, success},
+ {"Pepa Kuchar", 5, success},
+ {"Honza", 6, success},
+ {"Jenik", 7, success},
+ }
+ deleteData := []testData{
+ {"Pe", -1, success},
+ {"Pe", -1, failure},
+ {"Honzik", -1, failure},
+ {"Honza", -1, success},
+ {"Honza", -1, failure},
+ {"Pep", -1, failure},
+ {"P", -1, success},
+ {"Nobody", -1, failure},
+ {"", -1, success},
+ }
+
+ for _, v := range insertData {
+ t.Logf("INSERT prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal)
+ if ok := trie.Insert([]byte(v.key), v.value); ok != v.retVal {
+ t.Fatalf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
+ }
+ }
+
+ for _, v := range deleteData {
+ t.Logf("DELETE_SUBTREE prefix=%v, success=%v", v.key, v.retVal)
+ if ok := trie.DeleteSubtree([]byte(v.key)); ok != v.retVal {
+ t.Errorf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
+ }
+ }
+}
+
+/*
+func TestTrie_Dump(t *testing.T) {
+ trie := NewTrie()
+
+ data := []testData{
+ {"Honda", nil, success},
+ {"Honza", nil, success},
+ {"Jenik", nil, success},
+ {"Pepan", nil, success},
+ {"Pepin", nil, success},
+ }
+
+ for i, v := range data {
+ if _, ok := trie.Insert([]byte(v.key), v.value); ok != v.retVal {
+ t.Logf("INSERT %v %v", v.key, v.value)
+ t.Fatalf("Unexpected return value, expected=%v, got=%v", i, ok)
+ }
+ }
+
+ dump := `
++--+--+ Hon +--+--+ da
+ | |
+ | +--+ za
+ |
+ +--+ Jenik
+ |
+ +--+ Pep +--+--+ an
+ |
+ +--+ in
+`
+
+ var buf bytes.Buffer
+ trie.Dump(buf)
+
+ if !bytes.Equal(buf.Bytes(), dump) {
+ t.Logf("DUMP")
+ t.Fatalf("Unexpected dump generated, expected\n\n%v\ngot\n\n%v", dump, buf.String())
+ }
+}
+*/
+
+func TestTrie_compact(t *testing.T) {
+ trie := NewTrie()
+
+ trie.Insert(Prefix("a"), 0)
+ trie.Insert(Prefix("ab"), 0)
+ trie.Insert(Prefix("abc"), 0)
+ trie.Insert(Prefix("abcd"), 0)
+ trie.Insert(Prefix("abcde"), 0)
+ trie.Insert(Prefix("abcdef"), 0)
+ trie.Insert(Prefix("abcdefg"), 0)
+ trie.Insert(Prefix("abcdefgi"), 0)
+ trie.Insert(Prefix("abcdefgij"), 0)
+ trie.Insert(Prefix("abcdefgijk"), 0)
+
+ trie.Delete(Prefix("abcdef"))
+ trie.Delete(Prefix("abcde"))
+ trie.Delete(Prefix("abcdefg"))
+
+ trie.Delete(Prefix("a"))
+ trie.Delete(Prefix("abc"))
+ trie.Delete(Prefix("ab"))
+
+ trie.Visit(func(prefix Prefix, item Item) error {
+ // 97 ~~ 'a',
+ for ch := byte(97); ch <= 107; ch++ {
+ if c := bytes.Count(prefix, []byte{ch}); c > 1 {
+ t.Errorf("%q appeared in %q %v times", ch, prefix, c)
+ }
+ }
+ return nil
+ })
+}
+
+func TestTrie_longestCommonPrefixLenght(t *testing.T) {
+ trie := NewTrie()
+ trie.prefix = []byte("1234567890")
+
+ switch {
+ case trie.longestCommonPrefixLength([]byte("")) != 0:
+ t.Fail()
+ case trie.longestCommonPrefixLength([]byte("12345")) != 5:
+ t.Fail()
+ case trie.longestCommonPrefixLength([]byte("123789")) != 3:
+ t.Fail()
+ case trie.longestCommonPrefixLength([]byte("12345678901")) != 10:
+ t.Fail()
+ }
+}
+
+// Examples --------------------------------------------------------------------
+
+func ExampleTrie() {
+ // Create a new tree.
+ trie := NewTrie()
+
+ // Insert some items.
+ trie.Insert(Prefix("Pepa Novak"), 1)
+ trie.Insert(Prefix("Pepa Sindelar"), 2)
+ trie.Insert(Prefix("Karel Macha"), 3)
+ trie.Insert(Prefix("Karel Hynek Macha"), 4)
+
+ // Just check if some things are present in the tree.
+ key := Prefix("Pepa Novak")
+ fmt.Printf("%q present? %v\n", key, trie.Match(key))
+ key = Prefix("Karel")
+ fmt.Printf("Anybody called %q here? %v\n", key, trie.MatchSubtree(key))
+
+ // Walk the tree.
+ trie.Visit(printItem)
+ // "Pepa Novak": 1
+ // "Pepa Sindelar": 2
+ // "Karel Macha": 3
+ // "Karel Hynek Macha": 4
+
+ // Walk a subtree.
+ trie.VisitSubtree(Prefix("Pepa"), printItem)
+ // "Pepa Novak": 1
+ // "Pepa Sindelar": 2
+
+ // Modify an item, then fetch it from the tree.
+ trie.Set(Prefix("Karel Hynek Macha"), 10)
+ key = Prefix("Karel Hynek Macha")
+ fmt.Printf("%q: %v\n", key, trie.Get(key))
+ // "Karel Hynek Macha": 10
+
+ // Walk prefixes.
+ prefix := Prefix("Karel Hynek Macha je kouzelnik")
+ trie.VisitPrefixes(prefix, printItem)
+ // "Karel Hynek Macha": 10
+
+ // Delete some items.
+ trie.Delete(Prefix("Pepa Novak"))
+ trie.Delete(Prefix("Karel Macha"))
+
+ // Walk again.
+ trie.Visit(printItem)
+ // "Pepa Sindelar": 2
+ // "Karel Hynek Macha": 10
+
+ // Delete a subtree.
+ trie.DeleteSubtree(Prefix("Pepa"))
+
+ // Print what is left.
+ trie.Visit(printItem)
+ // "Karel Hynek Macha": 10
+
+ // Output:
+ // "Pepa Novak" present? true
+ // Anybody called "Karel" here? true
+ // "Pepa Novak": 1
+ // "Pepa Sindelar": 2
+ // "Karel Macha": 3
+ // "Karel Hynek Macha": 4
+ // "Pepa Novak": 1
+ // "Pepa Sindelar": 2
+ // "Karel Hynek Macha": 10
+ // "Karel Hynek Macha": 10
+ // "Pepa Sindelar": 2
+ // "Karel Hynek Macha": 10
+ // "Karel Hynek Macha": 10
+}
+
+// Helpers ---------------------------------------------------------------------
+
+func printItem(prefix Prefix, item Item) error {
+ fmt.Printf("%q: %v\n", prefix, item)
+ return nil
+}