You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

203 lines
4.1 KiB

10 years ago
  1. package common
  2. import (
  3. "fmt"
  4. "runtime"
  5. "testing"
  6. )
  7. func init() {
  8. // TODO: seed rand?
  9. }
  10. func (self *IBBSTree) lmd() *IBBSTree {
  11. if self.height == 0 {
  12. return self
  13. }
  14. return self.left.lmd()
  15. }
  16. func TestUnit(t *testing.T) {
  17. // Convenience for a new node
  18. N := func(l, r interface{}) *IBBSTree {
  19. var left, right *IBBSTree
  20. if _, ok := l.(*IBBSTree); ok {
  21. left = l.(*IBBSTree)
  22. } else {
  23. left = NewIBBSTreeNode(uint64(l.(int)), nil)
  24. }
  25. if _, ok := r.(*IBBSTree); ok {
  26. right = r.(*IBBSTree)
  27. } else {
  28. right = NewIBBSTreeNode(uint64(r.(int)), nil)
  29. }
  30. n := &IBBSTree{
  31. key: right.lmd().key,
  32. left: left,
  33. right: right,
  34. }
  35. n.calcHeightAndSize()
  36. return n
  37. }
  38. // Convenience for simple printing of keys & tree structure
  39. var P func(*IBBSTree) string
  40. P = func(n *IBBSTree) string {
  41. if n.height == 0 {
  42. return fmt.Sprintf("%v", n.key)
  43. } else {
  44. return fmt.Sprintf("(%v %v)", P(n.left), P(n.right))
  45. }
  46. }
  47. expectSet := func(n *IBBSTree, i uint64, repr string) {
  48. n2, updated := n.Set(i, nil)
  49. // ensure node was added & structure is as expected.
  50. if updated == true || P(n2) != repr {
  51. t.Fatalf("Adding %v to %v:\nExpected %v\nUnexpectedly got %v updated:%v",
  52. i, P(n), repr, P(n2), updated)
  53. }
  54. }
  55. expectRemove := func(n *IBBSTree, i uint64, repr string) {
  56. n2, value, removed := n.Remove(i)
  57. // ensure node was removed & structure is as expected.
  58. if value != nil || P(n2) != repr || !removed {
  59. t.Fatalf("Removing %v from %v:\nExpected %v\nUnexpectedly got %v value:%v err:%v",
  60. i, P(n), repr, P(n2), value, removed)
  61. }
  62. }
  63. //////// Test Set cases:
  64. // Case 1:
  65. n1 := N(4, 20)
  66. expectSet(n1, 8, "((4 8) 20)")
  67. expectSet(n1, 25, "(4 (20 25))")
  68. n2 := N(4, N(20, 25))
  69. expectSet(n2, 8, "((4 8) (20 25))")
  70. expectSet(n2, 30, "((4 20) (25 30))")
  71. n3 := N(N(1, 2), 6)
  72. expectSet(n3, 4, "((1 2) (4 6))")
  73. expectSet(n3, 8, "((1 2) (6 8))")
  74. n4 := N(N(1, 2), N(N(5, 6), N(7, 9)))
  75. expectSet(n4, 8, "(((1 2) (5 6)) ((7 8) 9))")
  76. expectSet(n4, 10, "(((1 2) (5 6)) (7 (9 10)))")
  77. //////// Test Remove cases:
  78. n10 := N(N(1, 2), 3)
  79. expectRemove(n10, 2, "(1 3)")
  80. expectRemove(n10, 3, "(1 2)")
  81. n11 := N(N(N(1, 2), 3), N(4, 5))
  82. expectRemove(n11, 4, "((1 2) (3 5))")
  83. expectRemove(n11, 3, "((1 2) (4 5))")
  84. }
  85. func TestIntegration(t *testing.T) {
  86. type record struct {
  87. key uint64
  88. value string
  89. }
  90. records := make([]*record, 400)
  91. var tree *IBBSTree = NewIBBSTree()
  92. var val interface{}
  93. var removed bool
  94. var updated bool
  95. randomRecord := func() *record {
  96. return &record{RandUInt64(), RandStr(20)}
  97. }
  98. for i := range records {
  99. r := randomRecord()
  100. records[i] = r
  101. //t.Log("New record", r)
  102. //PrintIBBSTree(tree.root)
  103. tree, updated = tree.Set(r.key, "")
  104. if updated {
  105. t.Error("should have not been updated")
  106. }
  107. tree, updated = tree.Set(r.key, r.value)
  108. if !updated {
  109. t.Error("should have been updated")
  110. }
  111. if tree.Size() != uint64(i+1) {
  112. t.Error("size was wrong", tree.Size(), i+1)
  113. }
  114. }
  115. for _, r := range records {
  116. if has := tree.Has(r.key); !has {
  117. t.Error("Missing key", r.key)
  118. }
  119. if val := tree.Get(r.key); val.(string) != r.value {
  120. t.Error("wrong value")
  121. }
  122. }
  123. for i, x := range records {
  124. if tree, val, removed = tree.Remove(x.key); !removed {
  125. t.Error("not removed")
  126. } else if val.(string) != x.value {
  127. t.Error("wrong value")
  128. }
  129. for _, r := range records[i+1:] {
  130. if has := tree.Has(r.key); !has {
  131. t.Error("Missing key", r.key)
  132. }
  133. val := tree.Get(r.key)
  134. if val.(string) != r.value {
  135. t.Error("wrong value")
  136. }
  137. }
  138. if tree.Size() != uint64(len(records)-(i+1)) {
  139. t.Error("size was wrong", tree.Size(), (len(records) - (i + 1)))
  140. }
  141. }
  142. }
  143. func BenchmarkIBBSTree(b *testing.B) {
  144. b.StopTimer()
  145. type record struct {
  146. key uint64
  147. value interface{}
  148. }
  149. randomRecord := func() *record {
  150. return &record{RandUInt64(), RandUInt64()}
  151. }
  152. t := NewIBBSTree()
  153. for i := 0; i < 1000000; i++ {
  154. r := randomRecord()
  155. t, _ = t.Set(r.key, r.value)
  156. }
  157. fmt.Println("ok, starting")
  158. runtime.GC()
  159. b.StartTimer()
  160. for i := 0; i < b.N; i++ {
  161. r := randomRecord()
  162. t, _ = t.Set(r.key, r.value)
  163. t, _, _ = t.Remove(r.key)
  164. }
  165. }