mirror of
https://github.com/fluencelabs/tendermint
synced 2025-04-26 07:12:16 +00:00
201 lines
4.8 KiB
Go
201 lines
4.8 KiB
Go
|
package merkle
|
||
|
|
||
|
import "testing"
|
||
|
|
||
|
import (
|
||
|
"os"
|
||
|
"bytes"
|
||
|
"math/rand"
|
||
|
"encoding/binary"
|
||
|
)
|
||
|
|
||
|
|
||
|
func init() {
|
||
|
if urandom, err := os.Open("/dev/urandom"); err != nil {
|
||
|
return
|
||
|
} else {
|
||
|
buf := make([]byte, 8)
|
||
|
if _, err := urandom.Read(buf); err == nil {
|
||
|
buf_reader := bytes.NewReader(buf)
|
||
|
if seed, err := binary.ReadVarint(buf_reader); err == nil {
|
||
|
rand.Seed(seed)
|
||
|
}
|
||
|
}
|
||
|
urandom.Close()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func randstr(length int) String {
|
||
|
if urandom, err := os.Open("/dev/urandom"); err != nil {
|
||
|
panic(err)
|
||
|
} else {
|
||
|
slice := make([]byte, length)
|
||
|
if _, err := urandom.Read(slice); err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
urandom.Close()
|
||
|
return String(slice)
|
||
|
}
|
||
|
panic("unreachable")
|
||
|
}
|
||
|
|
||
|
func TestImmutableAvlPutHasGetRemove(t *testing.T) {
|
||
|
|
||
|
type record struct {
|
||
|
key String
|
||
|
value String
|
||
|
}
|
||
|
|
||
|
records := make([]*record, 400)
|
||
|
var tree *IAVLNode
|
||
|
var err error
|
||
|
var val interface{}
|
||
|
var updated bool
|
||
|
|
||
|
ranrec := func() *record {
|
||
|
return &record{ randstr(20), randstr(20) }
|
||
|
}
|
||
|
|
||
|
for i := range records {
|
||
|
r := ranrec()
|
||
|
records[i] = r
|
||
|
tree, updated = tree.Put(r.key, String(""))
|
||
|
if updated {
|
||
|
t.Error("should have not been updated")
|
||
|
}
|
||
|
tree, updated = tree.Put(r.key, r.value)
|
||
|
if !updated {
|
||
|
t.Error("should have been updated")
|
||
|
}
|
||
|
if tree.Size() != (i+1) {
|
||
|
t.Error("size was wrong", tree.Size(), i+1)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for _, r := range records {
|
||
|
if has := tree.Has(r.key); !has {
|
||
|
t.Error("Missing key")
|
||
|
}
|
||
|
if has := tree.Has(randstr(12)); has {
|
||
|
t.Error("Table has extra key")
|
||
|
}
|
||
|
if val, err := tree.Get(r.key); err != nil {
|
||
|
t.Error(err, val.(String), r.value)
|
||
|
} else if !(val.(String)).Equals(r.value) {
|
||
|
t.Error("wrong value")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for i, x := range records {
|
||
|
if tree, val, err = tree.Remove(x.key); err != nil {
|
||
|
t.Error(err)
|
||
|
} else if !(val.(String)).Equals(x.value) {
|
||
|
t.Error("wrong value")
|
||
|
}
|
||
|
for _, r := range records[i+1:] {
|
||
|
if has := tree.Has(r.key); !has {
|
||
|
t.Error("Missing key")
|
||
|
}
|
||
|
if has := tree.Has(randstr(12)); has {
|
||
|
t.Error("Table has extra key")
|
||
|
}
|
||
|
if val, err := tree.Get(r.key); err != nil {
|
||
|
t.Error(err)
|
||
|
} else if !(val.(String)).Equals(r.value) {
|
||
|
t.Error("wrong value")
|
||
|
}
|
||
|
}
|
||
|
if tree.Size() != (len(records) - (i+1)) {
|
||
|
t.Error("size was wrong", tree.Size(), (len(records) - (i+1)))
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
func BenchmarkImmutableAvlTree(b *testing.B) {
|
||
|
b.StopTimer()
|
||
|
|
||
|
type record struct {
|
||
|
key String
|
||
|
value String
|
||
|
}
|
||
|
|
||
|
records := make([]*record, 100)
|
||
|
|
||
|
ranrec := func() *record {
|
||
|
return &record{ randstr(20), randstr(20) }
|
||
|
}
|
||
|
|
||
|
for i := range records {
|
||
|
records[i] = ranrec()
|
||
|
}
|
||
|
|
||
|
b.StartTimer()
|
||
|
for i := 0; i < b.N; i++ {
|
||
|
t := NewIAVLTree()
|
||
|
for _, r := range records {
|
||
|
t.Put(r.key, r.value)
|
||
|
}
|
||
|
for _, r := range records {
|
||
|
t.Remove(r.key)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
func TestTraversals(t *testing.T) {
|
||
|
var data []int = []int{
|
||
|
1, 5, 7, 9, 12, 13, 17, 18, 19, 20,
|
||
|
}
|
||
|
var order []int = []int{
|
||
|
6, 1, 8, 2, 4 , 9 , 5 , 7 , 0 , 3 ,
|
||
|
}
|
||
|
/*
|
||
|
var preorder []int = []int {
|
||
|
17, 7, 5, 1, 12, 9, 13, 19, 18, 20,
|
||
|
}
|
||
|
var postorder []int = []int {
|
||
|
1, 5, 9, 13, 12, 7, 18, 20, 19, 17,
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
test := func(T Tree) {
|
||
|
t.Logf("%T", T)
|
||
|
for j := range order {
|
||
|
if err := T.Put(Int(data[order[j]]), order[j]); err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
j := 0
|
||
|
for
|
||
|
tn, next := Iterator(T.Root())();
|
||
|
next != nil;
|
||
|
tn, next = next () {
|
||
|
if int(tn.Key().(Int)) != data[j] {
|
||
|
t.Error("key in wrong spot in-order")
|
||
|
}
|
||
|
j += 1
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
j = 0
|
||
|
for tn, next := tree.TraverseTreePreOrder(T.Root())(); next != nil; tn, next = next () {
|
||
|
if int(tn.Key().(Int)) != preorder[j] {
|
||
|
t.Error("key in wrong spot pre-order")
|
||
|
}
|
||
|
j += 1
|
||
|
}
|
||
|
|
||
|
j = 0
|
||
|
for tn, next := tree.TraverseTreePostOrder(T.Root())(); next != nil; tn, next = next () {
|
||
|
if int(tn.Key().(Int)) != postorder[j] {
|
||
|
t.Error("key in wrong spot post-order")
|
||
|
}
|
||
|
j += 1
|
||
|
}
|
||
|
*/
|
||
|
}
|
||
|
test(NewIAVLTree())
|
||
|
}
|