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.

222 lines
4.3 KiB

  1. // Copyright (c) 2014, Suryandaru Triandana <syndtr@gmail.com>
  2. // All rights reserved.
  3. //
  4. // Use of this source code is governed by a BSD-style license that can be
  5. // found in the LICENSE file.
  6. package testutil
  7. import (
  8. "fmt"
  9. "math/rand"
  10. . "github.com/onsi/gomega"
  11. "github.com/syndtr/goleveldb/leveldb/errors"
  12. "github.com/syndtr/goleveldb/leveldb/iterator"
  13. "github.com/syndtr/goleveldb/leveldb/util"
  14. )
  15. type DB interface{}
  16. type Put interface {
  17. TestPut(key []byte, value []byte) error
  18. }
  19. type Delete interface {
  20. TestDelete(key []byte) error
  21. }
  22. type Find interface {
  23. TestFind(key []byte) (rkey, rvalue []byte, err error)
  24. }
  25. type Get interface {
  26. TestGet(key []byte) (value []byte, err error)
  27. }
  28. type Has interface {
  29. TestHas(key []byte) (ret bool, err error)
  30. }
  31. type NewIterator interface {
  32. TestNewIterator(slice *util.Range) iterator.Iterator
  33. }
  34. type DBAct int
  35. func (a DBAct) String() string {
  36. switch a {
  37. case DBNone:
  38. return "none"
  39. case DBPut:
  40. return "put"
  41. case DBOverwrite:
  42. return "overwrite"
  43. case DBDelete:
  44. return "delete"
  45. case DBDeleteNA:
  46. return "delete_na"
  47. }
  48. return "unknown"
  49. }
  50. const (
  51. DBNone DBAct = iota
  52. DBPut
  53. DBOverwrite
  54. DBDelete
  55. DBDeleteNA
  56. )
  57. type DBTesting struct {
  58. Rand *rand.Rand
  59. DB interface {
  60. Get
  61. Put
  62. Delete
  63. }
  64. PostFn func(t *DBTesting)
  65. Deleted, Present KeyValue
  66. Act, LastAct DBAct
  67. ActKey, LastActKey []byte
  68. }
  69. func (t *DBTesting) post() {
  70. if t.PostFn != nil {
  71. t.PostFn(t)
  72. }
  73. }
  74. func (t *DBTesting) setAct(act DBAct, key []byte) {
  75. t.LastAct, t.Act = t.Act, act
  76. t.LastActKey, t.ActKey = t.ActKey, key
  77. }
  78. func (t *DBTesting) text() string {
  79. return fmt.Sprintf("last action was <%v> %q, <%v> %q", t.LastAct, t.LastActKey, t.Act, t.ActKey)
  80. }
  81. func (t *DBTesting) Text() string {
  82. return "DBTesting " + t.text()
  83. }
  84. func (t *DBTesting) TestPresentKV(key, value []byte) {
  85. rvalue, err := t.DB.TestGet(key)
  86. Expect(err).ShouldNot(HaveOccurred(), "Get on key %q, %s", key, t.text())
  87. Expect(rvalue).Should(Equal(value), "Value for key %q, %s", key, t.text())
  88. }
  89. func (t *DBTesting) TestAllPresent() {
  90. t.Present.IterateShuffled(t.Rand, func(i int, key, value []byte) {
  91. t.TestPresentKV(key, value)
  92. })
  93. }
  94. func (t *DBTesting) TestDeletedKey(key []byte) {
  95. _, err := t.DB.TestGet(key)
  96. Expect(err).Should(Equal(errors.ErrNotFound), "Get on deleted key %q, %s", key, t.text())
  97. }
  98. func (t *DBTesting) TestAllDeleted() {
  99. t.Deleted.IterateShuffled(t.Rand, func(i int, key, value []byte) {
  100. t.TestDeletedKey(key)
  101. })
  102. }
  103. func (t *DBTesting) TestAll() {
  104. dn := t.Deleted.Len()
  105. pn := t.Present.Len()
  106. ShuffledIndex(t.Rand, dn+pn, 1, func(i int) {
  107. if i >= dn {
  108. key, value := t.Present.Index(i - dn)
  109. t.TestPresentKV(key, value)
  110. } else {
  111. t.TestDeletedKey(t.Deleted.KeyAt(i))
  112. }
  113. })
  114. }
  115. func (t *DBTesting) Put(key, value []byte) {
  116. if new := t.Present.PutU(key, value); new {
  117. t.setAct(DBPut, key)
  118. } else {
  119. t.setAct(DBOverwrite, key)
  120. }
  121. t.Deleted.Delete(key)
  122. err := t.DB.TestPut(key, value)
  123. Expect(err).ShouldNot(HaveOccurred(), t.Text())
  124. t.TestPresentKV(key, value)
  125. t.post()
  126. }
  127. func (t *DBTesting) PutRandom() bool {
  128. if t.Deleted.Len() > 0 {
  129. i := t.Rand.Intn(t.Deleted.Len())
  130. key, value := t.Deleted.Index(i)
  131. t.Put(key, value)
  132. return true
  133. }
  134. return false
  135. }
  136. func (t *DBTesting) Delete(key []byte) {
  137. if exist, value := t.Present.Delete(key); exist {
  138. t.setAct(DBDelete, key)
  139. t.Deleted.PutU(key, value)
  140. } else {
  141. t.setAct(DBDeleteNA, key)
  142. }
  143. err := t.DB.TestDelete(key)
  144. Expect(err).ShouldNot(HaveOccurred(), t.Text())
  145. t.TestDeletedKey(key)
  146. t.post()
  147. }
  148. func (t *DBTesting) DeleteRandom() bool {
  149. if t.Present.Len() > 0 {
  150. i := t.Rand.Intn(t.Present.Len())
  151. t.Delete(t.Present.KeyAt(i))
  152. return true
  153. }
  154. return false
  155. }
  156. func (t *DBTesting) RandomAct(round int) {
  157. for i := 0; i < round; i++ {
  158. if t.Rand.Int()%2 == 0 {
  159. t.PutRandom()
  160. } else {
  161. t.DeleteRandom()
  162. }
  163. }
  164. }
  165. func DoDBTesting(t *DBTesting) {
  166. if t.Rand == nil {
  167. t.Rand = NewRand()
  168. }
  169. t.DeleteRandom()
  170. t.PutRandom()
  171. t.DeleteRandom()
  172. t.DeleteRandom()
  173. for i := t.Deleted.Len() / 2; i >= 0; i-- {
  174. t.PutRandom()
  175. }
  176. t.RandomAct((t.Deleted.Len() + t.Present.Len()) * 10)
  177. // Additional iterator testing
  178. if db, ok := t.DB.(NewIterator); ok {
  179. iter := db.TestNewIterator(nil)
  180. Expect(iter.Error()).NotTo(HaveOccurred())
  181. it := IteratorTesting{
  182. KeyValue: t.Present,
  183. Iter: iter,
  184. }
  185. DoIteratorTesting(&it)
  186. iter.Release()
  187. }
  188. }