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.

283 lines
7.3 KiB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
  1. package merkle
  2. import (
  3. . "github.com/tendermint/tendermint/binary"
  4. "testing"
  5. "fmt"
  6. "os"
  7. "bytes"
  8. "math/rand"
  9. "encoding/binary"
  10. "github.com/tendermint/tendermint/db"
  11. "crypto/sha256"
  12. "runtime"
  13. )
  14. func init() {
  15. if urandom, err := os.Open("/dev/urandom"); err != nil {
  16. return
  17. } else {
  18. buf := make([]byte, 8)
  19. if _, err := urandom.Read(buf); err == nil {
  20. buf_reader := bytes.NewReader(buf)
  21. if seed, err := binary.ReadVarint(buf_reader); err == nil {
  22. rand.Seed(seed)
  23. }
  24. }
  25. urandom.Close()
  26. }
  27. }
  28. func TestUnit(t *testing.T) {
  29. // Convenience for a new node
  30. N := func(l, r interface{}) *IAVLNode {
  31. var left, right *IAVLNode
  32. if _, ok := l.(*IAVLNode); ok {
  33. left = l.(*IAVLNode)
  34. } else {
  35. left = NewIAVLNode(Int32(l.(int)), nil)
  36. }
  37. if _, ok := r.(*IAVLNode); ok {
  38. right = r.(*IAVLNode)
  39. } else {
  40. right = NewIAVLNode(Int32(r.(int)), nil)
  41. }
  42. n := &IAVLNode{
  43. key: right.lmd(nil).key,
  44. left: left,
  45. right: right,
  46. }
  47. n.calcHeightAndSize(nil)
  48. n.Hash()
  49. return n
  50. }
  51. // Convenience for simple printing of keys & tree structure
  52. var P func(*IAVLNode) string
  53. P = func(n *IAVLNode) string {
  54. if n.height == 0 {
  55. return fmt.Sprintf("%v", n.key)
  56. } else {
  57. return fmt.Sprintf("(%v %v)", P(n.left), P(n.right))
  58. }
  59. }
  60. expectHash := func(n2 *IAVLNode, hashCount uint64) {
  61. // ensure number of new hash calculations is as expected.
  62. hash, count := n2.Hash()
  63. if count != hashCount {
  64. t.Fatalf("Expected %v new hashes, got %v", hashCount, count)
  65. }
  66. // nuke hashes and reconstruct hash, ensure it's the same.
  67. (&IAVLTree{root:n2}).Traverse(func(node Node) bool {
  68. node.(*IAVLNode).hash = nil
  69. return false
  70. })
  71. // ensure that the new hash after nuking is the same as the old.
  72. newHash, _ := n2.Hash()
  73. if bytes.Compare(hash, newHash) != 0 {
  74. t.Fatalf("Expected hash %v but got %v after nuking", hash, newHash)
  75. }
  76. }
  77. expectPut := func(n *IAVLNode, i int, repr string, hashCount uint64) {
  78. n2, updated := n.put(nil, Int32(i), nil)
  79. // ensure node was added & structure is as expected.
  80. if updated == true || P(n2) != repr {
  81. t.Fatalf("Adding %v to %v:\nExpected %v\nUnexpectedly got %v updated:%v",
  82. i, P(n), repr, P(n2), updated)
  83. }
  84. // ensure hash calculation requirements
  85. expectHash(n2, hashCount)
  86. }
  87. expectRemove := func(n *IAVLNode, i int, repr string, hashCount uint64) {
  88. n2, _, value, err := n.remove(nil, Int32(i))
  89. // ensure node was added & structure is as expected.
  90. if value != nil || err != nil || P(n2) != repr {
  91. t.Fatalf("Removing %v from %v:\nExpected %v\nUnexpectedly got %v value:%v err:%v",
  92. i, P(n), repr, P(n2), value, err)
  93. }
  94. // ensure hash calculation requirements
  95. expectHash(n2, hashCount)
  96. }
  97. //////// Test Put cases:
  98. // Case 1:
  99. n1 := N(4, 20)
  100. expectPut(n1, 8, "((4 8) 20)", 3)
  101. expectPut(n1, 25, "(4 (20 25))", 3)
  102. n2 := N(4, N(20, 25))
  103. expectPut(n2, 8, "((4 8) (20 25))", 3)
  104. expectPut(n2, 30, "((4 20) (25 30))", 4)
  105. n3 := N(N(1, 2), 6)
  106. expectPut(n3, 4, "((1 2) (4 6))", 4)
  107. expectPut(n3, 8, "((1 2) (6 8))", 3)
  108. n4 := N(N(1, 2), N(N(5, 6), N(7, 9)))
  109. expectPut(n4, 8, "(((1 2) (5 6)) ((7 8) 9))", 5)
  110. expectPut(n4, 10, "(((1 2) (5 6)) (7 (9 10)))", 5)
  111. //////// Test Remove cases:
  112. n10 := N(N(1, 2), 3)
  113. expectRemove(n10, 2, "(1 3)", 1)
  114. expectRemove(n10, 3, "(1 2)", 0)
  115. n11 := N(N(N(1, 2), 3), N(4, 5))
  116. expectRemove(n11, 4, "((1 2) (3 5))", 2)
  117. expectRemove(n11, 3, "((1 2) (4 5))", 1)
  118. }
  119. func TestIntegration(t *testing.T) {
  120. type record struct {
  121. key String
  122. value String
  123. }
  124. records := make([]*record, 400)
  125. var tree *IAVLTree = NewIAVLTree(nil)
  126. var err error
  127. var val Value
  128. var updated bool
  129. randomRecord := func() *record {
  130. return &record{ randstr(20), randstr(20) }
  131. }
  132. for i := range records {
  133. r := randomRecord()
  134. records[i] = r
  135. //t.Log("New record", r)
  136. //PrintIAVLNode(tree.root)
  137. updated = tree.Put(r.key, String(""))
  138. if updated {
  139. t.Error("should have not been updated")
  140. }
  141. updated = tree.Put(r.key, r.value)
  142. if !updated {
  143. t.Error("should have been updated")
  144. }
  145. if tree.Size() != uint64(i+1) {
  146. t.Error("size was wrong", tree.Size(), i+1)
  147. }
  148. }
  149. for _, r := range records {
  150. if has := tree.Has(r.key); !has {
  151. t.Error("Missing key", r.key)
  152. }
  153. if has := tree.Has(randstr(12)); has {
  154. t.Error("Table has extra key")
  155. }
  156. if val := tree.Get(r.key); !(val.(String)).Equals(r.value) {
  157. t.Error("wrong value")
  158. }
  159. }
  160. for i, x := range records {
  161. if val, err = tree.Remove(x.key); err != nil {
  162. t.Error(err)
  163. } else if !(val.(String)).Equals(x.value) {
  164. t.Error("wrong value")
  165. }
  166. for _, r := range records[i+1:] {
  167. if has := tree.Has(r.key); !has {
  168. t.Error("Missing key", r.key)
  169. }
  170. if has := tree.Has(randstr(12)); has {
  171. t.Error("Table has extra key")
  172. }
  173. if val := tree.Get(r.key); !(val.(String)).Equals(r.value) {
  174. t.Error("wrong value")
  175. }
  176. }
  177. if tree.Size() != uint64(len(records) - (i+1)) {
  178. t.Error("size was wrong", tree.Size(), (len(records) - (i+1)))
  179. }
  180. }
  181. }
  182. func TestPersistence(t *testing.T) {
  183. db := db.NewMemDB()
  184. // Create some random key value pairs
  185. records := make(map[String]String)
  186. for i:=0; i<10000; i++ {
  187. records[String(randstr(20))] = String(randstr(20))
  188. }
  189. // Construct some tree and save it
  190. t1 := NewIAVLTree(db)
  191. for key, value := range records {
  192. t1.Put(key, value)
  193. }
  194. t1.Save()
  195. hash, _ := t1.Hash()
  196. // Load a tree
  197. t2 := NewIAVLTreeFromHash(db, hash)
  198. for key, value := range records {
  199. t2value := t2.Get(key)
  200. if !BinaryEqual(t2value, value) {
  201. t.Fatalf("Invalid value. Expected %v, got %v", value, t2value)
  202. }
  203. }
  204. }
  205. func BenchmarkHash(b *testing.B) {
  206. b.StopTimer()
  207. s := randstr(128)
  208. b.StartTimer()
  209. for i := 0; i < b.N; i++ {
  210. hasher := sha256.New()
  211. hasher.Write([]byte(s))
  212. hasher.Sum(nil)
  213. }
  214. }
  215. func BenchmarkImmutableAvlTree(b *testing.B) {
  216. b.StopTimer()
  217. type record struct {
  218. key String
  219. value String
  220. }
  221. randomRecord := func() *record {
  222. return &record{ randstr(32), randstr(32) }
  223. }
  224. t := NewIAVLTree(nil)
  225. for i:=0; i<1000000; i++ {
  226. r := randomRecord()
  227. t.Put(r.key, r.value)
  228. }
  229. fmt.Println("ok, starting")
  230. runtime.GC()
  231. b.StartTimer()
  232. for i := 0; i < b.N; i++ {
  233. r := randomRecord()
  234. t.Put(r.key, r.value)
  235. t.Remove(r.key)
  236. }
  237. }