|
|
- package common
-
- import (
- "fmt"
- "runtime"
- "testing"
- )
-
- func init() {
- // TODO: seed rand?
- }
-
- func (self *IBBSTree) lmd() *IBBSTree {
- if self.height == 0 {
- return self
- }
- return self.left.lmd()
- }
-
- func TestUnit(t *testing.T) {
-
- // Convenience for a new node
- N := func(l, r interface{}) *IBBSTree {
- var left, right *IBBSTree
- if _, ok := l.(*IBBSTree); ok {
- left = l.(*IBBSTree)
- } else {
- left = NewIBBSTreeNode(uint64(l.(int)), nil)
- }
- if _, ok := r.(*IBBSTree); ok {
- right = r.(*IBBSTree)
- } else {
- right = NewIBBSTreeNode(uint64(r.(int)), nil)
- }
-
- n := &IBBSTree{
- key: right.lmd().key,
- left: left,
- right: right,
- }
- n.calcHeightAndSize()
- return n
- }
-
- // Convenience for simple printing of keys & tree structure
- var P func(*IBBSTree) string
- P = func(n *IBBSTree) string {
- if n.height == 0 {
- return fmt.Sprintf("%v", n.key)
- } else {
- return fmt.Sprintf("(%v %v)", P(n.left), P(n.right))
- }
- }
-
- expectSet := func(n *IBBSTree, i uint64, repr string) {
- n2, updated := n.Set(i, nil)
- // ensure node was added & structure is as expected.
- if updated == true || P(n2) != repr {
- t.Fatalf("Adding %v to %v:\nExpected %v\nUnexpectedly got %v updated:%v",
- i, P(n), repr, P(n2), updated)
- }
- }
-
- expectRemove := func(n *IBBSTree, i uint64, repr string) {
- n2, value, removed := n.Remove(i)
- // ensure node was removed & structure is as expected.
- if value != nil || P(n2) != repr || !removed {
- t.Fatalf("Removing %v from %v:\nExpected %v\nUnexpectedly got %v value:%v err:%v",
- i, P(n), repr, P(n2), value, removed)
- }
- }
-
- //////// Test Set cases:
-
- // Case 1:
- n1 := N(4, 20)
-
- expectSet(n1, 8, "((4 8) 20)")
- expectSet(n1, 25, "(4 (20 25))")
-
- n2 := N(4, N(20, 25))
-
- expectSet(n2, 8, "((4 8) (20 25))")
- expectSet(n2, 30, "((4 20) (25 30))")
-
- n3 := N(N(1, 2), 6)
-
- expectSet(n3, 4, "((1 2) (4 6))")
- expectSet(n3, 8, "((1 2) (6 8))")
-
- n4 := N(N(1, 2), N(N(5, 6), N(7, 9)))
-
- expectSet(n4, 8, "(((1 2) (5 6)) ((7 8) 9))")
- expectSet(n4, 10, "(((1 2) (5 6)) (7 (9 10)))")
-
- //////// Test Remove cases:
-
- n10 := N(N(1, 2), 3)
-
- expectRemove(n10, 2, "(1 3)")
- expectRemove(n10, 3, "(1 2)")
-
- n11 := N(N(N(1, 2), 3), N(4, 5))
-
- expectRemove(n11, 4, "((1 2) (3 5))")
- expectRemove(n11, 3, "((1 2) (4 5))")
-
- }
-
- func TestIntegration(t *testing.T) {
-
- type record struct {
- key uint64
- value string
- }
-
- records := make([]*record, 400)
- var tree *IBBSTree = NewIBBSTree()
- var val interface{}
- var removed bool
- var updated bool
-
- randomRecord := func() *record {
- return &record{RandUInt64(), RandStr(20)}
- }
-
- for i := range records {
- r := randomRecord()
- records[i] = r
- //t.Log("New record", r)
- //PrintIBBSTree(tree.root)
- tree, updated = tree.Set(r.key, "")
- if updated {
- t.Error("should have not been updated")
- }
- tree, updated = tree.Set(r.key, r.value)
- if !updated {
- t.Error("should have been updated")
- }
- if tree.Size() != uint64(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", r.key)
- }
- if val := tree.Get(r.key); val.(string) != r.value {
- t.Error("wrong value")
- }
- }
-
- for i, x := range records {
- if tree, val, removed = tree.Remove(x.key); !removed {
- t.Error("not removed")
- } else if val.(string) != x.value {
- t.Error("wrong value")
- }
- for _, r := range records[i+1:] {
- if has := tree.Has(r.key); !has {
- t.Error("Missing key", r.key)
- }
- val := tree.Get(r.key)
- if val.(string) != r.value {
- t.Error("wrong value")
- }
- }
- if tree.Size() != uint64(len(records)-(i+1)) {
- t.Error("size was wrong", tree.Size(), (len(records) - (i + 1)))
- }
- }
- }
-
- func BenchmarkIBBSTree(b *testing.B) {
- b.StopTimer()
-
- type record struct {
- key uint64
- value interface{}
- }
-
- randomRecord := func() *record {
- return &record{RandUInt64(), RandUInt64()}
- }
-
- t := NewIBBSTree()
- for i := 0; i < 1000000; i++ {
- r := randomRecord()
- t, _ = t.Set(r.key, r.value)
- }
-
- fmt.Println("ok, starting")
-
- runtime.GC()
-
- b.StartTimer()
- for i := 0; i < b.N; i++ {
- r := randomRecord()
- t, _ = t.Set(r.key, r.value)
- t, _, _ = t.Remove(r.key)
- }
- }
|