Switch to github.com/golang/dep for vendoring
Signed-off-by: Mrunal Patel <mrunalp@gmail.com>
This commit is contained in:
parent
d6ab91be27
commit
8e5b17cf13
15431 changed files with 3971413 additions and 8881 deletions
25
vendor/github.com/tchap/go-patricia/.gitignore
generated
vendored
Normal file
25
vendor/github.com/tchap/go-patricia/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
# Swap files.
|
||||
*.swp
|
||||
|
||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
3
vendor/github.com/tchap/go-patricia/AUTHORS
generated
vendored
Normal file
3
vendor/github.com/tchap/go-patricia/AUTHORS
generated
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
This is the complete list of go-patricia copyright holders:
|
||||
|
||||
Ondřej Kupka <ondra.cap@gmail.com>
|
123
vendor/github.com/tchap/go-patricia/README.md
generated
vendored
Normal file
123
vendor/github.com/tchap/go-patricia/README.md
generated
vendored
Normal file
|
@ -0,0 +1,123 @@
|
|||
# go-patricia #
|
||||
|
||||
**Documentation**: [GoDoc](http://godoc.org/github.com/tchap/go-patricia/patricia)<br />
|
||||
**Build Status**: [](https://drone.io/github.com/tchap/go-patricia/latest)<br />
|
||||
**Test Coverage**: [](https://coveralls.io/r/tchap/go-patricia)
|
||||
|
||||
## About ##
|
||||
|
||||
A generic patricia trie (also called radix tree) implemented in Go (Golang).
|
||||
|
||||
The patricia trie as implemented in this library enables fast visiting of items
|
||||
in some particular ways:
|
||||
|
||||
1. visit all items saved in the tree,
|
||||
2. visit all items matching particular prefix (visit subtree), or
|
||||
3. given a string, visit all items matching some prefix of that string.
|
||||
|
||||
`[]byte` type is used for keys, `interface{}` for values.
|
||||
|
||||
`Trie` is not thread safe. Synchronize the access yourself.
|
||||
|
||||
### State of the Project ###
|
||||
|
||||
Apparently some people are using this, so the API should not change often.
|
||||
Any ideas on how to make the library better are still welcome.
|
||||
|
||||
More (unit) testing would be cool as well...
|
||||
|
||||
## Usage ##
|
||||
|
||||
Import the package from GitHub first.
|
||||
|
||||
```go
|
||||
import "github.com/tchap/go-patricia/patricia"
|
||||
```
|
||||
|
||||
You can as well use gopkg.in thingie:
|
||||
|
||||
```go
|
||||
import "gopkg.in/tchap/go-patricia.v2/patricia"
|
||||
```
|
||||
|
||||
Then you can start having fun.
|
||||
|
||||
```go
|
||||
printItem := func(prefix patricia.Prefix, item patricia.Item) error {
|
||||
fmt.Printf("%q: %v\n", prefix, item)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create a new default trie (using the default parameter values).
|
||||
trie := NewTrie()
|
||||
|
||||
// Create a new custom trie.
|
||||
trie := NewTrie(MaxPrefixPerNode(16), MaxChildrenPerSparseNode(10))
|
||||
|
||||
// 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))
|
||||
// "Pepa Novak" present? true
|
||||
key = Prefix("Karel")
|
||||
fmt.Printf("Anybody called %q here? %v\n", key, trie.MatchSubtree(key))
|
||||
// Anybody called "Karel" here? true
|
||||
|
||||
// Walk the tree in alphabetical order.
|
||||
trie.Visit(printItem)
|
||||
// "Karel Hynek Macha": 4
|
||||
// "Karel Macha": 3
|
||||
// "Pepa Novak": 1
|
||||
// "Pepa Sindelar": 2
|
||||
|
||||
// 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)
|
||||
// "Karel Hynek Macha": 10
|
||||
// "Pepa Sindelar": 2
|
||||
|
||||
// Delete a subtree.
|
||||
trie.DeleteSubtree(Prefix("Pepa"))
|
||||
|
||||
// Print what is left.
|
||||
trie.Visit(printItem)
|
||||
// "Karel Hynek Macha": 10
|
||||
```
|
||||
|
||||
## License ##
|
||||
|
||||
MIT, check the `LICENSE` file.
|
||||
|
||||
[](https://www.gittip.com/tchap/
|
||||
"Gittip Badge")
|
||||
|
||||
[](https://bitdeli.com/free
|
||||
"Bitdeli Badge")
|
218
vendor/github.com/tchap/go-patricia/patricia/patricia_dense_test.go
generated
vendored
Normal file
218
vendor/github.com/tchap/go-patricia/patricia/patricia_dense_test.go
generated
vendored
Normal file
|
@ -0,0 +1,218 @@
|
|||
// 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 (
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/satori/go.uuid"
|
||||
)
|
||||
|
||||
// Tests -----------------------------------------------------------------------
|
||||
|
||||
// overhead is allowed tolerance for Go's runtime/GC to increase the allocated memory
|
||||
// (to avoid failing tests on insignificant growth amounts)
|
||||
const overhead = 4000
|
||||
|
||||
func TestTrie_InsertDense(t *testing.T) {
|
||||
trie := NewTrie()
|
||||
|
||||
data := []testData{
|
||||
{"aba", 0, success},
|
||||
{"abb", 1, success},
|
||||
{"abc", 2, success},
|
||||
{"abd", 3, success},
|
||||
{"abe", 4, success},
|
||||
{"abf", 5, success},
|
||||
{"abg", 6, success},
|
||||
{"abh", 7, success},
|
||||
{"abi", 8, success},
|
||||
{"abj", 9, success},
|
||||
{"abk", 0, success},
|
||||
{"abl", 1, success},
|
||||
{"abm", 2, success},
|
||||
{"abn", 3, success},
|
||||
{"abo", 4, success},
|
||||
{"abp", 5, success},
|
||||
{"abq", 6, success},
|
||||
{"abr", 7, success},
|
||||
{"abs", 8, success},
|
||||
{"abt", 9, success},
|
||||
{"abu", 0, success},
|
||||
{"abv", 1, success},
|
||||
{"abw", 2, success},
|
||||
{"abx", 3, success},
|
||||
{"aby", 4, success},
|
||||
{"abz", 5, 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_InsertDensePreceeding(t *testing.T) {
|
||||
trie := NewTrie()
|
||||
start := byte(70)
|
||||
// create a dense node
|
||||
for i := byte(0); i <= DefaultMaxChildrenPerSparseNode; i++ {
|
||||
if !trie.Insert(Prefix([]byte{start + i}), true) {
|
||||
t.Errorf("insert failed, prefix=%v", start+i)
|
||||
}
|
||||
}
|
||||
// insert some preceeding keys
|
||||
for i := byte(1); i < start; i *= i + 1 {
|
||||
if !trie.Insert(Prefix([]byte{start - i}), true) {
|
||||
t.Errorf("insert failed, prefix=%v", start-i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTrie_InsertDenseDuplicatePrefixes(t *testing.T) {
|
||||
trie := NewTrie()
|
||||
|
||||
data := []testData{
|
||||
{"aba", 0, success},
|
||||
{"abb", 1, success},
|
||||
{"abc", 2, success},
|
||||
{"abd", 3, success},
|
||||
{"abe", 4, success},
|
||||
{"abf", 5, success},
|
||||
{"abg", 6, success},
|
||||
{"abh", 7, success},
|
||||
{"abi", 8, success},
|
||||
{"abj", 9, success},
|
||||
{"abk", 0, success},
|
||||
{"abl", 1, success},
|
||||
{"abm", 2, success},
|
||||
{"abn", 3, success},
|
||||
{"abo", 4, success},
|
||||
{"abp", 5, success},
|
||||
{"abq", 6, success},
|
||||
{"abr", 7, success},
|
||||
{"abs", 8, success},
|
||||
{"abt", 9, success},
|
||||
{"abu", 0, success},
|
||||
{"abv", 1, success},
|
||||
{"abw", 2, success},
|
||||
{"abx", 3, success},
|
||||
{"aby", 4, success},
|
||||
{"abz", 5, success},
|
||||
{"aba", 0, failure},
|
||||
{"abb", 1, failure},
|
||||
{"abc", 2, failure},
|
||||
{"abd", 3, failure},
|
||||
{"abe", 4, 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_DeleteDense(t *testing.T) {
|
||||
trie := NewTrie()
|
||||
|
||||
data := []testData{
|
||||
{"aba", 0, success},
|
||||
{"abb", 1, success},
|
||||
{"abc", 2, success},
|
||||
{"abd", 3, success},
|
||||
{"abe", 4, success},
|
||||
{"abf", 5, success},
|
||||
{"abg", 6, success},
|
||||
{"abh", 7, success},
|
||||
{"abi", 8, success},
|
||||
{"abj", 9, success},
|
||||
{"abk", 0, success},
|
||||
{"abl", 1, success},
|
||||
{"abm", 2, success},
|
||||
{"abn", 3, success},
|
||||
{"abo", 4, success},
|
||||
{"abp", 5, success},
|
||||
{"abq", 6, success},
|
||||
{"abr", 7, success},
|
||||
{"abs", 8, success},
|
||||
{"abt", 9, success},
|
||||
{"abu", 0, success},
|
||||
{"abv", 1, success},
|
||||
{"abw", 2, success},
|
||||
{"abx", 3, success},
|
||||
{"aby", 4, success},
|
||||
{"abz", 5, 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("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 TestTrie_DeleteLeakageDense(t *testing.T) {
|
||||
trie := NewTrie()
|
||||
|
||||
genTestData := func() *testData {
|
||||
// Generate a random hash as a key.
|
||||
key := uuid.NewV4()
|
||||
return &testData{key: key.String(), value: "v", retVal: success}
|
||||
}
|
||||
|
||||
testSize := 100
|
||||
data := make([]*testData, 0, testSize)
|
||||
for i := 0; i < testSize; i++ {
|
||||
data = append(data, genTestData())
|
||||
}
|
||||
|
||||
oldBytes := heapAllocatedBytes()
|
||||
|
||||
// repeat insertion/deletion for 10K times to catch possible memory issues
|
||||
for i := 0; i < 10000; i++ {
|
||||
for _, v := range data {
|
||||
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 {
|
||||
if ok := trie.Delete([]byte(v.key)); ok != v.retVal {
|
||||
t.Errorf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if newBytes := heapAllocatedBytes(); newBytes > oldBytes+overhead {
|
||||
t.Logf("Size=%d, Total=%d, Trie state:\n%s\n", trie.size(), trie.total(), trie.dump())
|
||||
t.Errorf("Heap space leak, grew %d bytes (%d to %d)\n", newBytes-oldBytes, oldBytes, newBytes)
|
||||
}
|
||||
|
||||
if numChildren := trie.children.length(); numChildren != 0 {
|
||||
t.Errorf("Trie is not empty: %v children found", numChildren)
|
||||
}
|
||||
}
|
||||
|
||||
func heapAllocatedBytes() uint64 {
|
||||
runtime.GC()
|
||||
|
||||
ms := runtime.MemStats{}
|
||||
runtime.ReadMemStats(&ms)
|
||||
return ms.Alloc
|
||||
}
|
690
vendor/github.com/tchap/go-patricia/patricia/patricia_sparse_test.go
generated
vendored
Normal file
690
vendor/github.com/tchap/go-patricia/patricia/patricia_sparse_test.go
generated
vendored
Normal file
|
@ -0,0 +1,690 @@
|
|||
// 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, %v != 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) == 3 {
|
||||
return someErr
|
||||
}
|
||||
if item.(int) != 3 {
|
||||
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_DeleteLeakageSparse(t *testing.T) {
|
||||
trie := NewTrie()
|
||||
|
||||
data := []testData{
|
||||
{"Pepan", "Pepan Zdepan", success},
|
||||
{"Honza", "Honza Novak", success},
|
||||
{"Jenik", "Jenik Poustevnicek", success},
|
||||
}
|
||||
|
||||
oldBytes := heapAllocatedBytes()
|
||||
|
||||
for i := 0; i < 10000; i++ {
|
||||
for _, v := range data {
|
||||
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 {
|
||||
if ok := trie.Delete([]byte(v.key)); ok != v.retVal {
|
||||
t.Errorf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if newBytes := heapAllocatedBytes(); newBytes > oldBytes+overhead {
|
||||
t.Logf("Size=%d, Total=%d, Trie state:\n%s\n", trie.size(), trie.total(), trie.dump())
|
||||
t.Errorf("Heap space leak, grew %d bytes (from %d to %d)\n", newBytes-oldBytes, oldBytes, newBytes)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
// "Karel Hynek Macha": 4
|
||||
// "Karel Macha": 3
|
||||
// "Pepa Novak": 1
|
||||
// "Pepa Sindelar": 2
|
||||
|
||||
// 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)
|
||||
// "Karel Hynek Macha": 10
|
||||
// "Pepa Sindelar": 2
|
||||
|
||||
// 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
|
||||
// "Karel Hynek Macha": 4
|
||||
// "Karel Macha": 3
|
||||
// "Pepa Novak": 1
|
||||
// "Pepa Sindelar": 2
|
||||
// "Pepa Novak": 1
|
||||
// "Pepa Sindelar": 2
|
||||
// "Karel Hynek Macha": 10
|
||||
// "Karel Hynek Macha": 10
|
||||
// "Karel Hynek Macha": 10
|
||||
// "Pepa Sindelar": 2
|
||||
// "Karel Hynek Macha": 10
|
||||
}
|
||||
|
||||
// Helpers ---------------------------------------------------------------------
|
||||
|
||||
func printItem(prefix Prefix, item Item) error {
|
||||
fmt.Printf("%q: %v\n", prefix, item)
|
||||
return nil
|
||||
}
|
131
vendor/github.com/tchap/go-patricia/patricia/patricia_test.go
generated
vendored
Normal file
131
vendor/github.com/tchap/go-patricia/patricia/patricia_test.go
generated
vendored
Normal file
|
@ -0,0 +1,131 @@
|
|||
// 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 (
|
||||
"crypto/rand"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Tests -----------------------------------------------------------------------
|
||||
|
||||
func TestTrie_ConstructorOptions(t *testing.T) {
|
||||
trie := NewTrie(MaxPrefixPerNode(16), MaxChildrenPerSparseNode(10))
|
||||
|
||||
if trie.maxPrefixPerNode != 16 {
|
||||
t.Errorf("Unexpected trie.maxPrefixPerNode value, expected=%v, got=%v",
|
||||
16, trie.maxPrefixPerNode)
|
||||
}
|
||||
|
||||
if trie.maxChildrenPerSparseNode != 10 {
|
||||
t.Errorf("Unexpected trie.maxChildrenPerSparseNode value, expected=%v, got=%v",
|
||||
10, trie.maxChildrenPerSparseNode)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTrie_GetNonexistentPrefix(t *testing.T) {
|
||||
trie := NewTrie()
|
||||
|
||||
data := []testData{
|
||||
{"aba", 0, 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)
|
||||
}
|
||||
}
|
||||
|
||||
t.Logf("GET prefix=baa, expect item=nil")
|
||||
if item := trie.Get(Prefix("baa")); item != nil {
|
||||
t.Errorf("Unexpected return value, expected=<nil>, got=%v", item)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTrie_RandomKitchenSink(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip()
|
||||
}
|
||||
const count, size = 750000, 16
|
||||
b := make([]byte, count+size+1)
|
||||
if _, err := rand.Read(b); err != nil {
|
||||
t.Fatal("error generating random bytes", err)
|
||||
}
|
||||
m := make(map[string]string)
|
||||
for i := 0; i < count; i++ {
|
||||
m[string(b[i:i+size])] = string(b[i+1 : i+size+1])
|
||||
}
|
||||
trie := NewTrie()
|
||||
getAndDelete := func(k, v string) {
|
||||
i := trie.Get(Prefix(k))
|
||||
if i == nil {
|
||||
t.Fatalf("item not found, prefix=%v", []byte(k))
|
||||
} else if s, ok := i.(string); !ok {
|
||||
t.Fatalf("unexpected item type, expecting=%v, got=%v", reflect.TypeOf(k), reflect.TypeOf(i))
|
||||
} else if s != v {
|
||||
t.Fatalf("unexpected item, expecting=%v, got=%v", []byte(k), []byte(s))
|
||||
} else if !trie.Delete(Prefix(k)) {
|
||||
t.Fatalf("delete failed, prefix=%v", []byte(k))
|
||||
} else if i = trie.Get(Prefix(k)); i != nil {
|
||||
t.Fatalf("unexpected item, expecting=<nil>, got=%v", i)
|
||||
} else if trie.Delete(Prefix(k)) {
|
||||
t.Fatalf("extra delete succeeded, prefix=%v", []byte(k))
|
||||
}
|
||||
}
|
||||
for k, v := range m {
|
||||
if !trie.Insert(Prefix(k), v) {
|
||||
t.Fatalf("insert failed, prefix=%v", []byte(k))
|
||||
}
|
||||
if byte(k[size/2]) < 128 {
|
||||
getAndDelete(k, v)
|
||||
delete(m, k)
|
||||
}
|
||||
}
|
||||
for k, v := range m {
|
||||
getAndDelete(k, v)
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure Delete that affects the root node works.
|
||||
// This was panicking when Delete was broken.
|
||||
func TestTrie_DeleteRoot(t *testing.T) {
|
||||
trie := NewTrie()
|
||||
|
||||
v := testData{"aba", 0, success}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
t.Logf("DELETE prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal)
|
||||
if ok := trie.Delete(Prefix(v.key)); ok != v.retVal {
|
||||
t.Errorf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTrie_DeleteAbsentPrefix(t *testing.T) {
|
||||
trie := NewTrie()
|
||||
|
||||
v := testData{"a", 0, success}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
d := "ab"
|
||||
t.Logf("DELETE prefix=%v, success=%v", d, failure)
|
||||
if ok := trie.Delete(Prefix(d)); ok != failure {
|
||||
t.Errorf("Unexpected return value, expected=%v, got=%v", failure, ok)
|
||||
}
|
||||
t.Logf("GET prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal)
|
||||
if i := trie.Get(Prefix(v.key)); i != v.value {
|
||||
t.Errorf("Unexpected item, expected=%v, got=%v", v.value, i)
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue