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.

326 lines
7.7 KiB

10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. package merkle
  2. import (
  3. "bytes"
  4. "fmt"
  5. "github.com/tendermint/tendermint/binary"
  6. . "github.com/tendermint/tendermint/common"
  7. . "github.com/tendermint/tendermint/common/test"
  8. "github.com/tendermint/tendermint/db"
  9. "runtime"
  10. "testing"
  11. )
  12. func randstr(length int) string {
  13. return RandStr(length)
  14. }
  15. // Convenience for a new node
  16. func N(l, r interface{}) *IAVLNode {
  17. var left, right *IAVLNode
  18. if _, ok := l.(*IAVLNode); ok {
  19. left = l.(*IAVLNode)
  20. } else {
  21. left = NewIAVLNode(l, "")
  22. }
  23. if _, ok := r.(*IAVLNode); ok {
  24. right = r.(*IAVLNode)
  25. } else {
  26. right = NewIAVLNode(r, "")
  27. }
  28. n := &IAVLNode{
  29. key: right.lmd(nil).key,
  30. value: "",
  31. leftNode: left,
  32. rightNode: right,
  33. }
  34. n.calcHeightAndSize(nil)
  35. return n
  36. }
  37. // Setup a deep node
  38. func T(n *IAVLNode) *IAVLTree {
  39. t := NewIAVLTree(binary.BasicCodec, binary.BasicCodec, 0, nil)
  40. n.hashWithCount(t)
  41. t.root = n
  42. return t
  43. }
  44. // Convenience for simple printing of keys & tree structure
  45. func P(n *IAVLNode) string {
  46. if n.height == 0 {
  47. return fmt.Sprintf("%v", n.key)
  48. } else {
  49. return fmt.Sprintf("(%v %v)", P(n.leftNode), P(n.rightNode))
  50. }
  51. }
  52. func TestUnit(t *testing.T) {
  53. expectHash := func(tree *IAVLTree, hashCount uint) {
  54. // ensure number of new hash calculations is as expected.
  55. hash, count := tree.HashWithCount()
  56. if count != hashCount {
  57. t.Fatalf("Expected %v new hashes, got %v", hashCount, count)
  58. }
  59. // nuke hashes and reconstruct hash, ensure it's the same.
  60. tree.root.traverse(tree, func(node *IAVLNode) bool {
  61. node.hash = nil
  62. return false
  63. })
  64. // ensure that the new hash after nuking is the same as the old.
  65. newHash, _ := tree.HashWithCount()
  66. if bytes.Compare(hash, newHash) != 0 {
  67. t.Fatalf("Expected hash %v but got %v after nuking", hash, newHash)
  68. }
  69. }
  70. expectSet := func(tree *IAVLTree, i int, repr string, hashCount uint) {
  71. origNode := tree.root
  72. updated := tree.Set(i, "")
  73. // ensure node was added & structure is as expected.
  74. if updated == true || P(tree.root) != repr {
  75. t.Fatalf("Adding %v to %v:\nExpected %v\nUnexpectedly got %v updated:%v",
  76. i, P(origNode), repr, P(tree.root), updated)
  77. }
  78. // ensure hash calculation requirements
  79. expectHash(tree, hashCount)
  80. tree.root = origNode
  81. }
  82. expectRemove := func(tree *IAVLTree, i int, repr string, hashCount uint) {
  83. origNode := tree.root
  84. value, removed := tree.Remove(i)
  85. // ensure node was added & structure is as expected.
  86. if value != "" || !removed || P(tree.root) != repr {
  87. t.Fatalf("Removing %v from %v:\nExpected %v\nUnexpectedly got %v value:%v removed:%v",
  88. i, P(origNode), repr, P(tree.root), value, removed)
  89. }
  90. // ensure hash calculation requirements
  91. expectHash(tree, hashCount)
  92. tree.root = origNode
  93. }
  94. //////// Test Set cases:
  95. // Case 1:
  96. t1 := T(N(4, 20))
  97. expectSet(t1, 8, "((4 8) 20)", 3)
  98. expectSet(t1, 25, "(4 (20 25))", 3)
  99. t2 := T(N(4, N(20, 25)))
  100. expectSet(t2, 8, "((4 8) (20 25))", 3)
  101. expectSet(t2, 30, "((4 20) (25 30))", 4)
  102. t3 := T(N(N(1, 2), 6))
  103. expectSet(t3, 4, "((1 2) (4 6))", 4)
  104. expectSet(t3, 8, "((1 2) (6 8))", 3)
  105. t4 := T(N(N(1, 2), N(N(5, 6), N(7, 9))))
  106. expectSet(t4, 8, "(((1 2) (5 6)) ((7 8) 9))", 5)
  107. expectSet(t4, 10, "(((1 2) (5 6)) (7 (9 10)))", 5)
  108. //////// Test Remove cases:
  109. t10 := T(N(N(1, 2), 3))
  110. expectRemove(t10, 2, "(1 3)", 1)
  111. expectRemove(t10, 3, "(1 2)", 0)
  112. t11 := T(N(N(N(1, 2), 3), N(4, 5)))
  113. expectRemove(t11, 4, "((1 2) (3 5))", 2)
  114. expectRemove(t11, 3, "((1 2) (4 5))", 1)
  115. }
  116. func TestIntegration(t *testing.T) {
  117. type record struct {
  118. key string
  119. value string
  120. }
  121. records := make([]*record, 400)
  122. var tree *IAVLTree = NewIAVLTree(binary.BasicCodec, binary.BasicCodec, 0, nil)
  123. randomRecord := func() *record {
  124. return &record{randstr(20), randstr(20)}
  125. }
  126. for i := range records {
  127. r := randomRecord()
  128. records[i] = r
  129. //t.Log("New record", r)
  130. //PrintIAVLNode(tree.root)
  131. updated := tree.Set(r.key, "")
  132. if updated {
  133. t.Error("should have not been updated")
  134. }
  135. updated = tree.Set(r.key, r.value)
  136. if !updated {
  137. t.Error("should have been updated")
  138. }
  139. if tree.Size() != uint(i+1) {
  140. t.Error("size was wrong", tree.Size(), i+1)
  141. }
  142. }
  143. for _, r := range records {
  144. if has := tree.Has(r.key); !has {
  145. t.Error("Missing key", r.key)
  146. }
  147. if has := tree.Has(randstr(12)); has {
  148. t.Error("Table has extra key")
  149. }
  150. if _, val := tree.Get(r.key); val.(string) != r.value {
  151. t.Error("wrong value")
  152. }
  153. }
  154. for i, x := range records {
  155. if val, removed := tree.Remove(x.key); !removed {
  156. t.Error("Wasn't removed")
  157. } else if val != x.value {
  158. t.Error("Wrong value")
  159. }
  160. for _, r := range records[i+1:] {
  161. if has := tree.Has(r.key); !has {
  162. t.Error("Missing key", r.key)
  163. }
  164. if has := tree.Has(randstr(12)); has {
  165. t.Error("Table has extra key")
  166. }
  167. _, val := tree.Get(r.key)
  168. if val != r.value {
  169. t.Error("wrong value")
  170. }
  171. }
  172. if tree.Size() != uint(len(records)-(i+1)) {
  173. t.Error("size was wrong", tree.Size(), (len(records) - (i + 1)))
  174. }
  175. }
  176. }
  177. func TestPersistence(t *testing.T) {
  178. db := db.NewMemDB()
  179. // Create some random key value pairs
  180. records := make(map[string]string)
  181. for i := 0; i < 10000; i++ {
  182. records[randstr(20)] = randstr(20)
  183. }
  184. // Construct some tree and save it
  185. t1 := NewIAVLTree(binary.BasicCodec, binary.BasicCodec, 0, db)
  186. for key, value := range records {
  187. t1.Set(key, value)
  188. }
  189. t1.Save()
  190. hash, _ := t1.HashWithCount()
  191. // Load a tree
  192. t2 := NewIAVLTree(binary.BasicCodec, binary.BasicCodec, 0, db)
  193. t2.Load(hash)
  194. for key, value := range records {
  195. _, t2value := t2.Get(key)
  196. if t2value != value {
  197. t.Fatalf("Invalid value. Expected %v, got %v", value, t2value)
  198. }
  199. }
  200. }
  201. func testProof(t *testing.T, proof *IAVLProof) {
  202. // Proof must verify.
  203. if !proof.Verify() {
  204. t.Errorf("Invalid proof. Verification failed.")
  205. return
  206. }
  207. // Write/Read then verify.
  208. proofBytes := binary.BinaryBytes(proof)
  209. n, err := int64(0), error(nil)
  210. proof2 := binary.ReadBinary(&IAVLProof{}, bytes.NewBuffer(proofBytes), &n, &err).(*IAVLProof)
  211. if err != nil {
  212. t.Errorf("Failed to read IAVLProof from bytes: %v", err)
  213. return
  214. }
  215. if !proof2.Verify() {
  216. t.Errorf("Invalid proof after write/read. Verification failed.")
  217. return
  218. }
  219. // Random mutations must not verify
  220. for i := 0; i < 3; i++ {
  221. badProofBytes := MutateByteSlice(proofBytes)
  222. n, err := int64(0), error(nil)
  223. badProof := binary.ReadBinary(&IAVLProof{}, bytes.NewBuffer(badProofBytes), &n, &err).(*IAVLProof)
  224. if err != nil {
  225. continue // This is fine.
  226. }
  227. if badProof.Verify() {
  228. t.Errorf("Proof was still valid after a random mutation:\n%X\n%X", proofBytes, badProofBytes)
  229. }
  230. }
  231. }
  232. func TestConstructProof(t *testing.T) {
  233. // Construct some random tree
  234. db := db.NewMemDB()
  235. var tree *IAVLTree = NewIAVLTree(binary.BasicCodec, binary.BasicCodec, 100, db)
  236. for i := 0; i < 1000; i++ {
  237. key, value := randstr(20), randstr(20)
  238. tree.Set(key, value)
  239. }
  240. // Persist the items so far
  241. tree.Save()
  242. // Add more items so it's not all persisted
  243. for i := 0; i < 100; i++ {
  244. key, value := randstr(20), randstr(20)
  245. tree.Set(key, value)
  246. }
  247. // Now for each item, construct a proof and verify
  248. tree.Iterate(func(key interface{}, value interface{}) bool {
  249. proof := tree.ConstructProof(key)
  250. if !bytes.Equal(proof.Root, tree.Hash()) {
  251. t.Errorf("Invalid proof. Expected root %X, got %X", tree.Hash(), proof.Root)
  252. }
  253. if !proof.Verify() {
  254. t.Errorf("Invalid proof. Verification failed.")
  255. }
  256. testProof(t, proof)
  257. return false
  258. })
  259. }
  260. func BenchmarkImmutableAvlTree(b *testing.B) {
  261. b.StopTimer()
  262. t := NewIAVLTree(binary.BasicCodec, binary.BasicCodec, 0, nil)
  263. // 23000ns/op, 43000ops/s
  264. // for i := 0; i < 10000000; i++ {
  265. for i := 0; i < 1000000; i++ {
  266. t.Set(RandUint64(), "")
  267. }
  268. fmt.Println("ok, starting")
  269. runtime.GC()
  270. b.StartTimer()
  271. for i := 0; i < b.N; i++ {
  272. ri := RandUint64()
  273. t.Set(ri, "")
  274. t.Remove(ri)
  275. }
  276. }