github.com/sunvim/utils@v0.1.0/patricia/patricia_sparse_test.go (about)

     1  // Copyright (c) 2014 The go-patricia AUTHORS
     2  //
     3  // Use of this source code is governed by The MIT License
     4  // that can be found in the LICENSE file.
     5  
     6  package patricia
     7  
     8  import (
     9  	"bytes"
    10  	"errors"
    11  	"fmt"
    12  	"strings"
    13  	"testing"
    14  )
    15  
    16  const (
    17  	success = true
    18  	failure = false
    19  )
    20  
    21  type testData struct {
    22  	key    string
    23  	value  interface{}
    24  	retVal bool
    25  }
    26  
    27  // Tests -----------------------------------------------------------------------
    28  
    29  func TestTrie_InsertDifferentPrefixes(t *testing.T) {
    30  	trie := NewTrie()
    31  
    32  	data := []testData{
    33  		{"Pepaneeeeeeeeeeeeee", "Pepan Zdepan", success},
    34  		{"Honzooooooooooooooo", "Honza Novak", success},
    35  		{"Jenikuuuuuuuuuuuuuu", "Jenik Poustevnicek", success},
    36  	}
    37  
    38  	for _, v := range data {
    39  		t.Logf("INSERT prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal)
    40  		if ok := trie.Insert(Prefix(v.key), v.value); ok != v.retVal {
    41  			t.Errorf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
    42  		}
    43  	}
    44  }
    45  
    46  func TestTrie_InsertDuplicatePrefixes(t *testing.T) {
    47  	trie := NewTrie()
    48  
    49  	data := []testData{
    50  		{"Pepan", "Pepan Zdepan", success},
    51  		{"Pepan", "Pepan Zdepan", failure},
    52  	}
    53  
    54  	for _, v := range data {
    55  		t.Logf("INSERT prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal)
    56  		if ok := trie.Insert(Prefix(v.key), v.value); ok != v.retVal {
    57  			t.Errorf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
    58  		}
    59  	}
    60  }
    61  
    62  func TestTrie_InsertVariousPrefixes(t *testing.T) {
    63  	trie := NewTrie()
    64  
    65  	data := []testData{
    66  		{"Pepan", "Pepan Zdepan", success},
    67  		{"Pepin", "Pepin Omacka", success},
    68  		{"Honza", "Honza Novak", success},
    69  		{"Jenik", "Jenik Poustevnicek", success},
    70  		{"Pepan", "Pepan Dupan", failure},
    71  		{"Karel", "Karel Pekar", success},
    72  		{"Jenik", "Jenik Poustevnicek", failure},
    73  		{"Pepanek", "Pepanek Zemlicka", success},
    74  	}
    75  
    76  	for _, v := range data {
    77  		t.Logf("INSERT prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal)
    78  		if ok := trie.Insert(Prefix(v.key), v.value); ok != v.retVal {
    79  			t.Errorf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
    80  		}
    81  	}
    82  }
    83  
    84  func TestTrie_InsertAndMatchPrefix(t *testing.T) {
    85  	trie := NewTrie()
    86  	t.Log("INSERT prefix=by week")
    87  	trie.Insert(Prefix("by week"), 2)
    88  	t.Log("INSERT prefix=by")
    89  	trie.Insert(Prefix("by"), 1)
    90  
    91  	if !trie.Match(Prefix("by")) {
    92  		t.Error("MATCH prefix=by, expected=true, got=false")
    93  	}
    94  }
    95  
    96  func TestTrie_SetGet(t *testing.T) {
    97  	trie := NewTrie()
    98  
    99  	data := []testData{
   100  		{"Pepan", "Pepan Zdepan", success},
   101  		{"Pepin", "Pepin Omacka", success},
   102  		{"Honza", "Honza Novak", success},
   103  		{"Jenik", "Jenik Poustevnicek", success},
   104  		{"Pepan", "Pepan Dupan", failure},
   105  		{"Karel", "Karel Pekar", success},
   106  		{"Jenik", "Jenik Poustevnicek", failure},
   107  		{"Pepanek", "Pepanek Zemlicka", success},
   108  	}
   109  
   110  	for _, v := range data {
   111  		t.Logf("INSERT prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal)
   112  		if ok := trie.Insert(Prefix(v.key), v.value); ok != v.retVal {
   113  			t.Errorf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
   114  		}
   115  	}
   116  
   117  	for _, v := range data {
   118  		t.Logf("SET %q to 10", v.key)
   119  		trie.Set(Prefix(v.key), 10)
   120  	}
   121  
   122  	for _, v := range data {
   123  		value := trie.Get(Prefix(v.key))
   124  		t.Logf("GET %q => %v", v.key, value)
   125  		if value.(int) != 10 {
   126  			t.Errorf("Unexpected return value, %v != 10", value)
   127  		}
   128  	}
   129  
   130  	if value := trie.Get(Prefix("random crap")); value != nil {
   131  		t.Errorf("Unexpected return value, %v != <nil>", value)
   132  	}
   133  }
   134  
   135  func TestTrie_Match(t *testing.T) {
   136  	trie := NewTrie()
   137  
   138  	data := []testData{
   139  		{"Pepan", "Pepan Zdepan", success},
   140  		{"Pepin", "Pepin Omacka", success},
   141  		{"Honza", "Honza Novak", success},
   142  		{"Jenik", "Jenik Poustevnicek", success},
   143  		{"Pepan", "Pepan Dupan", failure},
   144  		{"Karel", "Karel Pekar", success},
   145  		{"Jenik", "Jenik Poustevnicek", failure},
   146  		{"Pepanek", "Pepanek Zemlicka", success},
   147  	}
   148  
   149  	for _, v := range data {
   150  		t.Logf("INSERT prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal)
   151  		if ok := trie.Insert(Prefix(v.key), v.value); ok != v.retVal {
   152  			t.Errorf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
   153  		}
   154  	}
   155  
   156  	for _, v := range data {
   157  		matched := trie.Match(Prefix(v.key))
   158  		t.Logf("MATCH %q => %v", v.key, matched)
   159  		if !matched {
   160  			t.Errorf("Inserted key %q was not matched", v.key)
   161  		}
   162  	}
   163  
   164  	if trie.Match(Prefix("random crap")) {
   165  		t.Errorf("Key that was not inserted matched: %q", "random crap")
   166  	}
   167  }
   168  
   169  func TestTrie_MatchFalsePositive(t *testing.T) {
   170  	trie := NewTrie()
   171  
   172  	if ok := trie.Insert(Prefix("A"), 1); !ok {
   173  		t.Fatal("INSERT prefix=A, item=1 not ok")
   174  	}
   175  
   176  	resultMatchSubtree := trie.MatchSubtree(Prefix("A extra"))
   177  	resultMatch := trie.Match(Prefix("A extra"))
   178  
   179  	if resultMatchSubtree != false {
   180  		t.Error("MatchSubtree returned false positive")
   181  	}
   182  
   183  	if resultMatch != false {
   184  		t.Error("Match returned false positive")
   185  	}
   186  }
   187  
   188  func TestTrie_MatchSubtree(t *testing.T) {
   189  	trie := NewTrie()
   190  
   191  	data := []testData{
   192  		{"Pepan", "Pepan Zdepan", success},
   193  		{"Pepin", "Pepin Omacka", success},
   194  		{"Honza", "Honza Novak", success},
   195  		{"Jenik", "Jenik Poustevnicek", success},
   196  		{"Pepan", "Pepan Dupan", failure},
   197  		{"Karel", "Karel Pekar", success},
   198  		{"Jenik", "Jenik Poustevnicek", failure},
   199  		{"Pepanek", "Pepanek Zemlicka", success},
   200  	}
   201  
   202  	for _, v := range data {
   203  		t.Logf("INSERT prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal)
   204  		if ok := trie.Insert(Prefix(v.key), v.value); ok != v.retVal {
   205  			t.Errorf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
   206  		}
   207  	}
   208  
   209  	for _, v := range data {
   210  		key := Prefix(v.key[:3])
   211  		matched := trie.MatchSubtree(key)
   212  		t.Logf("MATCH_SUBTREE %q => %v", key, matched)
   213  		if !matched {
   214  			t.Errorf("Subtree %q was not matched", v.key)
   215  		}
   216  	}
   217  }
   218  
   219  func TestTrie_Visit(t *testing.T) {
   220  	trie := NewTrie()
   221  
   222  	data := []testData{
   223  		{"Pepa", 0, success},
   224  		{"Pepa Zdepa", 1, success},
   225  		{"Pepa Kuchar", 2, success},
   226  		{"Honza", 3, success},
   227  		{"Jenik", 4, success},
   228  	}
   229  
   230  	for _, v := range data {
   231  		t.Logf("INSERT prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal)
   232  		if ok := trie.Insert([]byte(v.key), v.value); ok != v.retVal {
   233  			t.Fatalf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
   234  		}
   235  	}
   236  
   237  	if err := trie.Visit(func(prefix Prefix, item Item) error {
   238  		name := data[item.(int)].key
   239  		t.Logf("VISITING prefix=%q, item=%v", prefix, item)
   240  		if !strings.HasPrefix(string(prefix), name) {
   241  			t.Errorf("Unexpected prefix encountered, %q not a prefix of %q", prefix, name)
   242  		}
   243  		return nil
   244  	}); err != nil {
   245  		t.Fatal(err)
   246  	}
   247  }
   248  
   249  func TestTrie_VisitSkipSubtree(t *testing.T) {
   250  	trie := NewTrie()
   251  
   252  	data := []testData{
   253  		{"Pepa", 0, success},
   254  		{"Pepa Zdepa", 1, success},
   255  		{"Pepa Kuchar", 2, success},
   256  		{"Honza", 3, success},
   257  		{"Jenik", 4, success},
   258  	}
   259  
   260  	for _, v := range data {
   261  		t.Logf("INSERT prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal)
   262  		if ok := trie.Insert([]byte(v.key), v.value); ok != v.retVal {
   263  			t.Fatalf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
   264  		}
   265  	}
   266  
   267  	if err := trie.Visit(func(prefix Prefix, item Item) error {
   268  		t.Logf("VISITING prefix=%q, item=%v", prefix, item)
   269  		if item.(int) == 0 {
   270  			t.Logf("SKIP %q", prefix)
   271  			return SkipSubtree
   272  		}
   273  		if strings.HasPrefix(string(prefix), "Pepa") {
   274  			t.Errorf("Unexpected prefix encountered, %q", prefix)
   275  		}
   276  		return nil
   277  	}); err != nil {
   278  		t.Fatal(err)
   279  	}
   280  }
   281  
   282  func TestTrie_VisitReturnError(t *testing.T) {
   283  	trie := NewTrie()
   284  
   285  	data := []testData{
   286  		{"Pepa", 0, success},
   287  		{"Pepa Zdepa", 1, success},
   288  		{"Pepa Kuchar", 2, success},
   289  		{"Honza", 3, success},
   290  		{"Jenik", 4, success},
   291  	}
   292  
   293  	for _, v := range data {
   294  		t.Logf("INSERT prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal)
   295  		if ok := trie.Insert([]byte(v.key), v.value); ok != v.retVal {
   296  			t.Fatalf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
   297  		}
   298  	}
   299  
   300  	someErr := errors.New("Something exploded")
   301  	if err := trie.Visit(func(prefix Prefix, item Item) error {
   302  		t.Logf("VISITING prefix=%q, item=%v", prefix, item)
   303  		if item.(int) == 3 {
   304  			return someErr
   305  		}
   306  		if item.(int) != 3 {
   307  			t.Errorf("Unexpected prefix encountered, %q", prefix)
   308  		}
   309  		return nil
   310  	}); err != nil && err != someErr {
   311  		t.Fatal(err)
   312  	}
   313  }
   314  
   315  func TestTrie_VisitSubtree(t *testing.T) {
   316  	trie := NewTrie()
   317  
   318  	data := []testData{
   319  		{"Pepa", 0, success},
   320  		{"Pepa Zdepa", 1, success},
   321  		{"Pepa Kuchar", 2, success},
   322  		{"Honza", 3, success},
   323  		{"Jenik", 4, success},
   324  	}
   325  
   326  	for _, v := range data {
   327  		t.Logf("INSERT prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal)
   328  		if ok := trie.Insert([]byte(v.key), v.value); ok != v.retVal {
   329  			t.Fatalf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
   330  		}
   331  	}
   332  
   333  	var counter int
   334  	subtreePrefix := []byte("Pep")
   335  	t.Log("VISIT Pep")
   336  	if err := trie.VisitSubtree(subtreePrefix, func(prefix Prefix, item Item) error {
   337  		t.Logf("VISITING prefix=%q, item=%v", prefix, item)
   338  		if !bytes.HasPrefix(prefix, subtreePrefix) {
   339  			t.Errorf("Unexpected prefix encountered, %q does not extend %q",
   340  				prefix, subtreePrefix)
   341  		}
   342  		if len(prefix) > len(data[item.(int)].key) {
   343  			t.Fatalf("Something is rather fishy here, prefix=%q", prefix)
   344  		}
   345  		counter++
   346  		return nil
   347  	}); err != nil {
   348  		t.Fatal(err)
   349  	}
   350  
   351  	if counter != 3 {
   352  		t.Error("Unexpected number of nodes visited")
   353  	}
   354  }
   355  
   356  func TestTrie_VisitPrefixes(t *testing.T) {
   357  	trie := NewTrie()
   358  
   359  	data := []testData{
   360  		{"P", 0, success},
   361  		{"Pe", 1, success},
   362  		{"Pep", 2, success},
   363  		{"Pepa", 3, success},
   364  		{"Pepa Zdepa", 4, success},
   365  		{"Pepa Kuchar", 5, success},
   366  		{"Honza", 6, success},
   367  		{"Jenik", 7, success},
   368  	}
   369  
   370  	for _, v := range data {
   371  		t.Logf("INSERT prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal)
   372  		if ok := trie.Insert([]byte(v.key), v.value); ok != v.retVal {
   373  			t.Fatalf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
   374  		}
   375  	}
   376  
   377  	var counter int
   378  	word := []byte("Pepa")
   379  	if err := trie.VisitPrefixes(word, func(prefix Prefix, item Item) error {
   380  		t.Logf("VISITING prefix=%q, item=%v", prefix, item)
   381  		if !bytes.HasPrefix(word, prefix) {
   382  			t.Errorf("Unexpected prefix encountered, %q is not a prefix of %q",
   383  				prefix, word)
   384  		}
   385  		counter++
   386  		return nil
   387  	}); err != nil {
   388  		t.Fatal(err)
   389  	}
   390  
   391  	if counter != 4 {
   392  		t.Error("Unexpected number of nodes visited")
   393  	}
   394  }
   395  
   396  func TestPatriciaTrie_CloneSparse(t *testing.T) {
   397  	trie := NewTrie()
   398  
   399  	data := []testData{
   400  		{"Pepaneeeeeeeeeeeeee", "Pepan Zdepan", success},
   401  		{"Honzooooooooooooooo", "Honza Novak", success},
   402  		{"Jenikuuuuuuuuuuuuuu", "Jenik Poustevnicek", success},
   403  	}
   404  
   405  	for _, v := range data {
   406  		t.Logf("INSERT prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal)
   407  		if ok := trie.Insert(Prefix(v.key), v.value); ok != v.retVal {
   408  			t.Errorf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
   409  		}
   410  	}
   411  
   412  	t.Log("CLONE")
   413  	clone := trie.Clone()
   414  
   415  	for _, v := range data {
   416  		t.Logf("GET prefix=%v, item=%v", v.key, v.value)
   417  		if item := clone.Get(Prefix(v.key)); item != v.value {
   418  			t.Errorf("Unexpected return value, expected=%v, got=%v", v.value, item)
   419  		}
   420  	}
   421  
   422  	prefix := "xxx"
   423  	item := 666
   424  	t.Logf("INSERT prefix=%v, item=%v", prefix, item)
   425  	if ok := trie.Insert(Prefix(prefix), item); !ok {
   426  		t.Errorf("Unexpected return value, expected=true, got=%v", ok)
   427  	}
   428  	t.Logf("GET cloned prefix=%v", prefix)
   429  	if item := clone.Get(Prefix(prefix)); item != nil {
   430  		t.Errorf("Unexpected return value, expected=nil, got=%v", item)
   431  	}
   432  }
   433  
   434  func TestParticiaTrie_Delete(t *testing.T) {
   435  	trie := NewTrie()
   436  
   437  	data := []testData{
   438  		{"Pepan", "Pepan Zdepan", success},
   439  		{"Honza", "Honza Novak", success},
   440  		{"Jenik", "Jenik Poustevnicek", success},
   441  	}
   442  
   443  	for _, v := range data {
   444  		t.Logf("INSERT prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal)
   445  		if ok := trie.Insert([]byte(v.key), v.value); ok != v.retVal {
   446  			t.Fatalf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
   447  		}
   448  	}
   449  
   450  	for _, v := range data {
   451  		t.Logf("DELETE word=%v, success=%v", v.key, v.retVal)
   452  		if ok := trie.Delete([]byte(v.key)); ok != v.retVal {
   453  			t.Errorf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
   454  		}
   455  	}
   456  }
   457  
   458  func TestParticiaTrie_DeleteLeakageSparse(t *testing.T) {
   459  	trie := NewTrie()
   460  
   461  	data := []testData{
   462  		{"Pepan", "Pepan Zdepan", success},
   463  		{"Honza", "Honza Novak", success},
   464  		{"Jenik", "Jenik Poustevnicek", success},
   465  	}
   466  
   467  	oldBytes := heapAllocatedBytes()
   468  
   469  	for i := 0; i < 10000; i++ {
   470  		for _, v := range data {
   471  			if ok := trie.Insert([]byte(v.key), v.value); ok != v.retVal {
   472  				t.Fatalf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
   473  			}
   474  		}
   475  
   476  		for _, v := range data {
   477  			if ok := trie.Delete([]byte(v.key)); ok != v.retVal {
   478  				t.Errorf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
   479  			}
   480  		}
   481  	}
   482  
   483  	if newBytes := heapAllocatedBytes(); newBytes > oldBytes+overhead {
   484  		t.Logf("Size=%d, Total=%d, Trie state:\n%s\n", trie.size(), trie.total(), trie.dump())
   485  		t.Errorf("Heap space leak, grew %d bytes (from %d to %d)\n", newBytes-oldBytes, oldBytes, newBytes)
   486  	}
   487  }
   488  
   489  func TestParticiaTrie_DeleteNonExistent(t *testing.T) {
   490  	trie := NewTrie()
   491  
   492  	insertData := []testData{
   493  		{"Pepan", "Pepan Zdepan", success},
   494  		{"Honza", "Honza Novak", success},
   495  		{"Jenik", "Jenik Poustevnicek", success},
   496  	}
   497  	deleteData := []testData{
   498  		{"Pepan", "Pepan Zdepan", success},
   499  		{"Honza", "Honza Novak", success},
   500  		{"Pepan", "Pepan Zdepan", failure},
   501  		{"Jenik", "Jenik Poustevnicek", success},
   502  		{"Honza", "Honza Novak", failure},
   503  	}
   504  
   505  	for _, v := range insertData {
   506  		t.Logf("INSERT prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal)
   507  		if ok := trie.Insert([]byte(v.key), v.value); ok != v.retVal {
   508  			t.Fatalf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
   509  		}
   510  	}
   511  
   512  	for _, v := range deleteData {
   513  		t.Logf("DELETE word=%v, success=%v", v.key, v.retVal)
   514  		if ok := trie.Delete([]byte(v.key)); ok != v.retVal {
   515  			t.Errorf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
   516  		}
   517  	}
   518  }
   519  
   520  func TestParticiaTrie_DeleteSubtree(t *testing.T) {
   521  	trie := NewTrie()
   522  
   523  	insertData := []testData{
   524  		{"P", 0, success},
   525  		{"Pe", 1, success},
   526  		{"Pep", 2, success},
   527  		{"Pepa", 3, success},
   528  		{"Pepa Zdepa", 4, success},
   529  		{"Pepa Kuchar", 5, success},
   530  		{"Honza", 6, success},
   531  		{"Jenik", 7, success},
   532  	}
   533  	deleteData := []testData{
   534  		{"Pe", -1, success},
   535  		{"Pe", -1, failure},
   536  		{"Honzik", -1, failure},
   537  		{"Honza", -1, success},
   538  		{"Honza", -1, failure},
   539  		{"Pep", -1, failure},
   540  		{"P", -1, success},
   541  		{"Nobody", -1, failure},
   542  		{"", -1, success},
   543  	}
   544  
   545  	for _, v := range insertData {
   546  		t.Logf("INSERT prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal)
   547  		if ok := trie.Insert([]byte(v.key), v.value); ok != v.retVal {
   548  			t.Fatalf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
   549  		}
   550  	}
   551  
   552  	for _, v := range deleteData {
   553  		t.Logf("DELETE_SUBTREE prefix=%v, success=%v", v.key, v.retVal)
   554  		if ok := trie.DeleteSubtree([]byte(v.key)); ok != v.retVal {
   555  			t.Errorf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
   556  		}
   557  	}
   558  }
   559  
   560  /*
   561  func TestTrie_Dump(t *testing.T) {
   562  	trie := NewTrie()
   563  
   564  	data := []testData{
   565  		{"Honda", nil, success},
   566  		{"Honza", nil, success},
   567  		{"Jenik", nil, success},
   568  		{"Pepan", nil, success},
   569  		{"Pepin", nil, success},
   570  	}
   571  
   572  	for i, v := range data {
   573  		if _, ok := trie.Insert([]byte(v.key), v.value); ok != v.retVal {
   574  			t.Logf("INSERT %v %v", v.key, v.value)
   575  			t.Fatalf("Unexpected return value, expected=%v, got=%v", i, ok)
   576  		}
   577  	}
   578  
   579  	dump := `
   580  +--+--+ Hon +--+--+ da
   581     |           |
   582     |           +--+ za
   583     |
   584     +--+ Jenik
   585     |
   586     +--+ Pep +--+--+ an
   587                 |
   588                 +--+ in
   589  `
   590  
   591  	var buf bytes.Buffer
   592  	trie.Dump(buf)
   593  
   594  	if !bytes.Equal(buf.Bytes(), dump) {
   595  		t.Logf("DUMP")
   596  		t.Fatalf("Unexpected dump generated, expected\n\n%v\ngot\n\n%v", dump, buf.String())
   597  	}
   598  }
   599  */
   600  
   601  func TestTrie_compact(t *testing.T) {
   602  	trie := NewTrie()
   603  
   604  	trie.Insert(Prefix("a"), 0)
   605  	trie.Insert(Prefix("ab"), 0)
   606  	trie.Insert(Prefix("abc"), 0)
   607  	trie.Insert(Prefix("abcd"), 0)
   608  	trie.Insert(Prefix("abcde"), 0)
   609  	trie.Insert(Prefix("abcdef"), 0)
   610  	trie.Insert(Prefix("abcdefg"), 0)
   611  	trie.Insert(Prefix("abcdefgi"), 0)
   612  	trie.Insert(Prefix("abcdefgij"), 0)
   613  	trie.Insert(Prefix("abcdefgijk"), 0)
   614  
   615  	trie.Delete(Prefix("abcdef"))
   616  	trie.Delete(Prefix("abcde"))
   617  	trie.Delete(Prefix("abcdefg"))
   618  
   619  	trie.Delete(Prefix("a"))
   620  	trie.Delete(Prefix("abc"))
   621  	trie.Delete(Prefix("ab"))
   622  
   623  	trie.Visit(func(prefix Prefix, item Item) error {
   624  		// 97 ~~ 'a',
   625  		for ch := byte(97); ch <= 107; ch++ {
   626  			if c := bytes.Count(prefix, []byte{ch}); c > 1 {
   627  				t.Errorf("%q appeared in %q %v times", ch, prefix, c)
   628  			}
   629  		}
   630  		return nil
   631  	})
   632  }
   633  
   634  func TestTrie_longestCommonPrefixLenght(t *testing.T) {
   635  	trie := NewTrie()
   636  	trie.prefix = []byte("1234567890")
   637  
   638  	switch {
   639  	case trie.longestCommonPrefixLength([]byte("")) != 0:
   640  		t.Fail()
   641  	case trie.longestCommonPrefixLength([]byte("12345")) != 5:
   642  		t.Fail()
   643  	case trie.longestCommonPrefixLength([]byte("123789")) != 3:
   644  		t.Fail()
   645  	case trie.longestCommonPrefixLength([]byte("12345678901")) != 10:
   646  		t.Fail()
   647  	}
   648  }
   649  
   650  // Examples --------------------------------------------------------------------
   651  
   652  func ExampleTrie() {
   653  	// Create a new tree.
   654  	trie := NewTrie()
   655  
   656  	// Insert some items.
   657  	trie.Insert(Prefix("Pepa Novak"), 1)
   658  	trie.Insert(Prefix("Pepa Sindelar"), 2)
   659  	trie.Insert(Prefix("Karel Macha"), 3)
   660  	trie.Insert(Prefix("Karel Hynek Macha"), 4)
   661  
   662  	// Just check if some things are present in the tree.
   663  	key := Prefix("Pepa Novak")
   664  	fmt.Printf("%q present? %v\n", key, trie.Match(key))
   665  	key = Prefix("Karel")
   666  	fmt.Printf("Anybody called %q here? %v\n", key, trie.MatchSubtree(key))
   667  
   668  	// Walk the tree.
   669  	trie.Visit(printItem)
   670  	// "Karel Hynek Macha": 4
   671  	// "Karel Macha": 3
   672  	// "Pepa Novak": 1
   673  	// "Pepa Sindelar": 2
   674  
   675  	// Walk a subtree.
   676  	trie.VisitSubtree(Prefix("Pepa"), printItem)
   677  	// "Pepa Novak": 1
   678  	// "Pepa Sindelar": 2
   679  
   680  	// Modify an item, then fetch it from the tree.
   681  	trie.Set(Prefix("Karel Hynek Macha"), 10)
   682  	key = Prefix("Karel Hynek Macha")
   683  	fmt.Printf("%q: %v\n", key, trie.Get(key))
   684  	// "Karel Hynek Macha": 10
   685  
   686  	// Walk prefixes.
   687  	prefix := Prefix("Karel Hynek Macha je kouzelnik")
   688  	trie.VisitPrefixes(prefix, printItem)
   689  	// "Karel Hynek Macha": 10
   690  
   691  	// Delete some items.
   692  	trie.Delete(Prefix("Pepa Novak"))
   693  	trie.Delete(Prefix("Karel Macha"))
   694  
   695  	// Walk again.
   696  	trie.Visit(printItem)
   697  	// "Karel Hynek Macha": 10
   698  	// "Pepa Sindelar": 2
   699  
   700  	// Delete a subtree.
   701  	trie.DeleteSubtree(Prefix("Pepa"))
   702  
   703  	// Print what is left.
   704  	trie.Visit(printItem)
   705  	// "Karel Hynek Macha": 10
   706  
   707  	// Output:
   708  	// "Pepa Novak" present? true
   709  	// Anybody called "Karel" here? true
   710  	// "Karel Hynek Macha": 4
   711  	// "Karel Macha": 3
   712  	// "Pepa Novak": 1
   713  	// "Pepa Sindelar": 2
   714  	// "Pepa Novak": 1
   715  	// "Pepa Sindelar": 2
   716  	// "Karel Hynek Macha": 10
   717  	// "Karel Hynek Macha": 10
   718  	// "Karel Hynek Macha": 10
   719  	// "Pepa Sindelar": 2
   720  	// "Karel Hynek Macha": 10
   721  }
   722  
   723  // Helpers ---------------------------------------------------------------------
   724  
   725  func printItem(prefix Prefix, item Item) error {
   726  	fmt.Printf("%q: %v\n", prefix, item)
   727  	return nil
   728  }