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.

327 lines
6.0 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/iterator"
  12. )
  13. type IterAct int
  14. func (a IterAct) String() string {
  15. switch a {
  16. case IterNone:
  17. return "none"
  18. case IterFirst:
  19. return "first"
  20. case IterLast:
  21. return "last"
  22. case IterPrev:
  23. return "prev"
  24. case IterNext:
  25. return "next"
  26. case IterSeek:
  27. return "seek"
  28. case IterSOI:
  29. return "soi"
  30. case IterEOI:
  31. return "eoi"
  32. }
  33. return "unknown"
  34. }
  35. const (
  36. IterNone IterAct = iota
  37. IterFirst
  38. IterLast
  39. IterPrev
  40. IterNext
  41. IterSeek
  42. IterSOI
  43. IterEOI
  44. )
  45. type IteratorTesting struct {
  46. KeyValue
  47. Iter iterator.Iterator
  48. Rand *rand.Rand
  49. PostFn func(t *IteratorTesting)
  50. Pos int
  51. Act, LastAct IterAct
  52. once bool
  53. }
  54. func (t *IteratorTesting) init() {
  55. if !t.once {
  56. t.Pos = -1
  57. t.once = true
  58. }
  59. }
  60. func (t *IteratorTesting) post() {
  61. if t.PostFn != nil {
  62. t.PostFn(t)
  63. }
  64. }
  65. func (t *IteratorTesting) setAct(act IterAct) {
  66. t.LastAct, t.Act = t.Act, act
  67. }
  68. func (t *IteratorTesting) text() string {
  69. return fmt.Sprintf("at pos %d and last action was <%v> -> <%v>", t.Pos, t.LastAct, t.Act)
  70. }
  71. func (t *IteratorTesting) Text() string {
  72. return "IteratorTesting is " + t.text()
  73. }
  74. func (t *IteratorTesting) IsFirst() bool {
  75. t.init()
  76. return t.Len() > 0 && t.Pos == 0
  77. }
  78. func (t *IteratorTesting) IsLast() bool {
  79. t.init()
  80. return t.Len() > 0 && t.Pos == t.Len()-1
  81. }
  82. func (t *IteratorTesting) TestKV() {
  83. t.init()
  84. key, value := t.Index(t.Pos)
  85. Expect(t.Iter.Key()).NotTo(BeNil())
  86. Expect(t.Iter.Key()).Should(Equal(key), "Key is invalid, %s", t.text())
  87. Expect(t.Iter.Value()).Should(Equal(value), "Value for key %q, %s", key, t.text())
  88. }
  89. func (t *IteratorTesting) First() {
  90. t.init()
  91. t.setAct(IterFirst)
  92. ok := t.Iter.First()
  93. Expect(t.Iter.Error()).ShouldNot(HaveOccurred())
  94. if t.Len() > 0 {
  95. t.Pos = 0
  96. Expect(ok).Should(BeTrue(), t.Text())
  97. t.TestKV()
  98. } else {
  99. t.Pos = -1
  100. Expect(ok).ShouldNot(BeTrue(), t.Text())
  101. }
  102. t.post()
  103. }
  104. func (t *IteratorTesting) Last() {
  105. t.init()
  106. t.setAct(IterLast)
  107. ok := t.Iter.Last()
  108. Expect(t.Iter.Error()).ShouldNot(HaveOccurred())
  109. if t.Len() > 0 {
  110. t.Pos = t.Len() - 1
  111. Expect(ok).Should(BeTrue(), t.Text())
  112. t.TestKV()
  113. } else {
  114. t.Pos = 0
  115. Expect(ok).ShouldNot(BeTrue(), t.Text())
  116. }
  117. t.post()
  118. }
  119. func (t *IteratorTesting) Next() {
  120. t.init()
  121. t.setAct(IterNext)
  122. ok := t.Iter.Next()
  123. Expect(t.Iter.Error()).ShouldNot(HaveOccurred())
  124. if t.Pos < t.Len()-1 {
  125. t.Pos++
  126. Expect(ok).Should(BeTrue(), t.Text())
  127. t.TestKV()
  128. } else {
  129. t.Pos = t.Len()
  130. Expect(ok).ShouldNot(BeTrue(), t.Text())
  131. }
  132. t.post()
  133. }
  134. func (t *IteratorTesting) Prev() {
  135. t.init()
  136. t.setAct(IterPrev)
  137. ok := t.Iter.Prev()
  138. Expect(t.Iter.Error()).ShouldNot(HaveOccurred())
  139. if t.Pos > 0 {
  140. t.Pos--
  141. Expect(ok).Should(BeTrue(), t.Text())
  142. t.TestKV()
  143. } else {
  144. t.Pos = -1
  145. Expect(ok).ShouldNot(BeTrue(), t.Text())
  146. }
  147. t.post()
  148. }
  149. func (t *IteratorTesting) Seek(i int) {
  150. t.init()
  151. t.setAct(IterSeek)
  152. key, _ := t.Index(i)
  153. oldKey, _ := t.IndexOrNil(t.Pos)
  154. ok := t.Iter.Seek(key)
  155. Expect(t.Iter.Error()).ShouldNot(HaveOccurred())
  156. Expect(ok).Should(BeTrue(), fmt.Sprintf("Seek from key %q to %q, to pos %d, %s", oldKey, key, i, t.text()))
  157. t.Pos = i
  158. t.TestKV()
  159. t.post()
  160. }
  161. func (t *IteratorTesting) SeekInexact(i int) {
  162. t.init()
  163. t.setAct(IterSeek)
  164. var key0 []byte
  165. key1, _ := t.Index(i)
  166. if i > 0 {
  167. key0, _ = t.Index(i - 1)
  168. }
  169. key := BytesSeparator(key0, key1)
  170. oldKey, _ := t.IndexOrNil(t.Pos)
  171. ok := t.Iter.Seek(key)
  172. Expect(t.Iter.Error()).ShouldNot(HaveOccurred())
  173. Expect(ok).Should(BeTrue(), fmt.Sprintf("Seek from key %q to %q (%q), to pos %d, %s", oldKey, key, key1, i, t.text()))
  174. t.Pos = i
  175. t.TestKV()
  176. t.post()
  177. }
  178. func (t *IteratorTesting) SeekKey(key []byte) {
  179. t.init()
  180. t.setAct(IterSeek)
  181. oldKey, _ := t.IndexOrNil(t.Pos)
  182. i := t.Search(key)
  183. ok := t.Iter.Seek(key)
  184. Expect(t.Iter.Error()).ShouldNot(HaveOccurred())
  185. if i < t.Len() {
  186. key_, _ := t.Index(i)
  187. Expect(ok).Should(BeTrue(), fmt.Sprintf("Seek from key %q to %q (%q), to pos %d, %s", oldKey, key, key_, i, t.text()))
  188. t.Pos = i
  189. t.TestKV()
  190. } else {
  191. Expect(ok).ShouldNot(BeTrue(), fmt.Sprintf("Seek from key %q to %q, %s", oldKey, key, t.text()))
  192. }
  193. t.Pos = i
  194. t.post()
  195. }
  196. func (t *IteratorTesting) SOI() {
  197. t.init()
  198. t.setAct(IterSOI)
  199. Expect(t.Pos).Should(BeNumerically("<=", 0), t.Text())
  200. for i := 0; i < 3; i++ {
  201. t.Prev()
  202. }
  203. t.post()
  204. }
  205. func (t *IteratorTesting) EOI() {
  206. t.init()
  207. t.setAct(IterEOI)
  208. Expect(t.Pos).Should(BeNumerically(">=", t.Len()-1), t.Text())
  209. for i := 0; i < 3; i++ {
  210. t.Next()
  211. }
  212. t.post()
  213. }
  214. func (t *IteratorTesting) WalkPrev(fn func(t *IteratorTesting)) {
  215. t.init()
  216. for old := t.Pos; t.Pos > 0; old = t.Pos {
  217. fn(t)
  218. Expect(t.Pos).Should(BeNumerically("<", old), t.Text())
  219. }
  220. }
  221. func (t *IteratorTesting) WalkNext(fn func(t *IteratorTesting)) {
  222. t.init()
  223. for old := t.Pos; t.Pos < t.Len()-1; old = t.Pos {
  224. fn(t)
  225. Expect(t.Pos).Should(BeNumerically(">", old), t.Text())
  226. }
  227. }
  228. func (t *IteratorTesting) PrevAll() {
  229. t.WalkPrev(func(t *IteratorTesting) {
  230. t.Prev()
  231. })
  232. }
  233. func (t *IteratorTesting) NextAll() {
  234. t.WalkNext(func(t *IteratorTesting) {
  235. t.Next()
  236. })
  237. }
  238. func DoIteratorTesting(t *IteratorTesting) {
  239. if t.Rand == nil {
  240. t.Rand = NewRand()
  241. }
  242. t.SOI()
  243. t.NextAll()
  244. t.First()
  245. t.SOI()
  246. t.NextAll()
  247. t.EOI()
  248. t.PrevAll()
  249. t.Last()
  250. t.EOI()
  251. t.PrevAll()
  252. t.SOI()
  253. t.NextAll()
  254. t.PrevAll()
  255. t.NextAll()
  256. t.Last()
  257. t.PrevAll()
  258. t.First()
  259. t.NextAll()
  260. t.EOI()
  261. ShuffledIndex(t.Rand, t.Len(), 1, func(i int) {
  262. t.Seek(i)
  263. })
  264. ShuffledIndex(t.Rand, t.Len(), 1, func(i int) {
  265. t.SeekInexact(i)
  266. })
  267. ShuffledIndex(t.Rand, t.Len(), 1, func(i int) {
  268. t.Seek(i)
  269. if i%2 != 0 {
  270. t.PrevAll()
  271. t.SOI()
  272. } else {
  273. t.NextAll()
  274. t.EOI()
  275. }
  276. })
  277. for _, key := range []string{"", "foo", "bar", "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"} {
  278. t.SeekKey([]byte(key))
  279. }
  280. }