github.com/go-ego/cedar@v0.10.2/dict_test.go (about)

     1  package cedar
     2  
     3  import (
     4  	"bufio"
     5  	"fmt"
     6  	"io"
     7  	"log"
     8  	"os"
     9  	"testing"
    10  )
    11  
    12  type item struct {
    13  	key   []byte
    14  	value int
    15  }
    16  
    17  var (
    18  	dict []item
    19  
    20  	trie = New()
    21  )
    22  
    23  func loadDict() []item {
    24  	testFile := "testdata/dict.txt"
    25  	f, err := os.Open(testFile)
    26  	if err != nil {
    27  		log.Fatal("failed to open ", testFile)
    28  	}
    29  	defer f.Close()
    30  
    31  	in := bufio.NewReader(f)
    32  	added := make(map[string]struct{})
    33  
    34  	var (
    35  		key  string
    36  		freq int
    37  		pos  string
    38  	)
    39  
    40  	for {
    41  		_, err := fmt.Fscanln(in, &key, &freq, &pos)
    42  		if err == io.EOF {
    43  			break
    44  		}
    45  
    46  		if _, ok := added[string(key)]; !ok {
    47  			dict = append(dict, item{[]byte(key), freq})
    48  			added[string(key)] = struct{}{}
    49  		}
    50  	}
    51  
    52  	return dict
    53  }
    54  
    55  func exist(i int) {
    56  	item := dict[i]
    57  	// fmt.Println(i, string(item.key))
    58  	id, err := trie.Jump(item.key, 0)
    59  	failIfError(err)
    60  
    61  	key, err := trie.Key(id)
    62  	failIfError(err)
    63  
    64  	value, err := trie.Value(id)
    65  	failIfError(err)
    66  
    67  	if string(key) != string(item.key) || value != item.value {
    68  		v, _ := trie.Get(item.key)
    69  		fmt.Println("exist but no equal: ", i, string(key), string(item.key), value, item.value, v)
    70  		panic("large dict test fail: no equal")
    71  	}
    72  }
    73  
    74  func notExist(i int) {
    75  	_, err := trie.Get(dict[i].key)
    76  	// fmt.Println(i, err)
    77  	if err != ErrNoPath && err != ErrNoValue {
    78  		panic("large dict test fail: should not exist")
    79  	}
    80  }
    81  
    82  func checkSize(exp int) {
    83  	if keys, _, _, _ := trie.Status(); keys != exp {
    84  		panic("not correct status")
    85  	}
    86  }
    87  
    88  func insertDict(size int) {
    89  	// Insert the first half of the dict.
    90  	for i := 0; i < size/2; i++ {
    91  		item := dict[i]
    92  		if i%2 == 0 {
    93  			if err := trie.Insert(item.key, item.value); err != nil {
    94  				panic(err)
    95  			}
    96  		} else {
    97  			if err := trie.Update(item.key, item.value); err != nil {
    98  				panic(err)
    99  			}
   100  		}
   101  	}
   102  	checkSize(size / 2)
   103  }
   104  
   105  func checkDict(size int) {
   106  	// Check the first half of the dict.
   107  	for i := 0; i < size/2; i++ {
   108  		exist(i)
   109  	}
   110  	log.Println("first half OK")
   111  
   112  	// Delete even items in the first half.
   113  	for i := 0; i < size/2; i += 2 {
   114  		err := trie.Delete(dict[i].key)
   115  		failIfError(err)
   116  	}
   117  	checkSize(size / 2 / 2)
   118  
   119  	// Make sure even items were deleted, and the rest are fine.
   120  	for i := 0; i < size/2; i++ {
   121  		if i%2 == 0 {
   122  			notExist(i)
   123  		} else {
   124  			exist(i)
   125  		}
   126  	}
   127  	log.Println("first half odd OK")
   128  
   129  	// Insert the second half of the dict.
   130  	for i := size / 2; i < size; i++ {
   131  		item := dict[i]
   132  		trie.Insert(item.key, item.value)
   133  	}
   134  	checkSize(size/2/2 + (size - size/2))
   135  }
   136  
   137  func odd(size int) {
   138  	for i := 0; i < size/2; i++ {
   139  		if i%2 == 0 {
   140  			notExist(i)
   141  		} else {
   142  			exist(i)
   143  		}
   144  	}
   145  	log.Println("first half odd still OK")
   146  
   147  	// Delete even items in the second half.
   148  	half := size / 2
   149  	if half%2 == 1 {
   150  		half++
   151  	}
   152  
   153  	for i := half; i < size; i += 2 {
   154  		err := trie.Delete(dict[i].key)
   155  		failIfError(err)
   156  	}
   157  
   158  	// Make sure even items were deleted, and the rest are fine.
   159  	for i := 0; i < size; i++ {
   160  		if i%2 == 0 {
   161  			notExist(i)
   162  		} else {
   163  			exist(i)
   164  		}
   165  	}
   166  
   167  	log.Println("odd OK")
   168  }
   169  
   170  func even(size int) {
   171  	// Insert all even terms.
   172  	for i := 0; i < size; i += 2 {
   173  		item := dict[i]
   174  		notExist(i)
   175  		trie.Update([]byte(item.key), item.value)
   176  	}
   177  
   178  	for i := 0; i < size; i++ {
   179  		exist(i)
   180  	}
   181  	log.Println("all OK")
   182  
   183  	// Insert every item again, should be fine.
   184  	for i := 1; i < size; i++ {
   185  		item := dict[i]
   186  		trie.Insert([]byte(item.key), item.value)
   187  	}
   188  
   189  	for i := 1; i < size; i += 2 {
   190  		exist(i)
   191  	}
   192  	log.Println("still OK")
   193  }
   194  
   195  func TestLargeDict(t *testing.T) {
   196  	loadDict()
   197  	size := len(dict)
   198  	log.Println("dict size:", size)
   199  
   200  	insertDict(size)
   201  	checkDict(size)
   202  
   203  	odd(size)
   204  	even(size)
   205  }
   206  
   207  func failIfError(err error) {
   208  	if err != nil {
   209  		panic(err)
   210  	}
   211  }