1 // Copyright (c) 2014, Suryandaru Triandana <syndtr@gmail.com>
2 // All rights reserved.
4 // Use of this source code is governed by a BSD-style license that can be
5 // found in the LICENSE file.
13 . "github.com/onsi/gomega"
15 "github.com/syndtr/goleveldb/leveldb/errors"
16 "github.com/syndtr/goleveldb/leveldb/iterator"
17 "github.com/syndtr/goleveldb/leveldb/util"
23 TestPut(key []byte, value []byte) error
26 type Delete interface {
27 TestDelete(key []byte) error
31 TestFind(key []byte) (rkey, rvalue []byte, err error)
35 TestGet(key []byte) (value []byte, err error)
39 TestHas(key []byte) (ret bool, err error)
42 type NewIterator interface {
43 TestNewIterator(slice *util.Range) iterator.Iterator
48 func (a DBAct) String() string {
72 type DBTesting struct {
79 PostFn func(t *DBTesting)
80 Deleted, Present KeyValue
82 ActKey, LastActKey []byte
85 func (t *DBTesting) post() {
91 func (t *DBTesting) setAct(act DBAct, key []byte) {
92 t.LastAct, t.Act = t.Act, act
93 t.LastActKey, t.ActKey = t.ActKey, key
96 func (t *DBTesting) text() string {
97 return fmt.Sprintf("last action was <%v> %q, <%v> %q", t.LastAct, t.LastActKey, t.Act, t.ActKey)
100 func (t *DBTesting) Text() string {
101 return "DBTesting " + t.text()
104 func (t *DBTesting) TestPresentKV(key, value []byte) {
105 rvalue, err := t.DB.TestGet(key)
106 Expect(err).ShouldNot(HaveOccurred(), "Get on key %q, %s", key, t.text())
107 Expect(rvalue).Should(Equal(value), "Value for key %q, %s", key, t.text())
110 func (t *DBTesting) TestAllPresent() {
111 t.Present.IterateShuffled(t.Rand, func(i int, key, value []byte) {
112 t.TestPresentKV(key, value)
116 func (t *DBTesting) TestDeletedKey(key []byte) {
117 _, err := t.DB.TestGet(key)
118 Expect(err).Should(Equal(errors.ErrNotFound), "Get on deleted key %q, %s", key, t.text())
121 func (t *DBTesting) TestAllDeleted() {
122 t.Deleted.IterateShuffled(t.Rand, func(i int, key, value []byte) {
123 t.TestDeletedKey(key)
127 func (t *DBTesting) TestAll() {
128 dn := t.Deleted.Len()
129 pn := t.Present.Len()
130 ShuffledIndex(t.Rand, dn+pn, 1, func(i int) {
132 key, value := t.Present.Index(i - dn)
133 t.TestPresentKV(key, value)
135 t.TestDeletedKey(t.Deleted.KeyAt(i))
140 func (t *DBTesting) Put(key, value []byte) {
141 if new := t.Present.PutU(key, value); new {
144 t.setAct(DBOverwrite, key)
146 t.Deleted.Delete(key)
147 err := t.DB.TestPut(key, value)
148 Expect(err).ShouldNot(HaveOccurred(), t.Text())
149 t.TestPresentKV(key, value)
153 func (t *DBTesting) PutRandom() bool {
154 if t.Deleted.Len() > 0 {
155 i := t.Rand.Intn(t.Deleted.Len())
156 key, value := t.Deleted.Index(i)
163 func (t *DBTesting) Delete(key []byte) {
164 if exist, value := t.Present.Delete(key); exist {
165 t.setAct(DBDelete, key)
166 t.Deleted.PutU(key, value)
168 t.setAct(DBDeleteNA, key)
170 err := t.DB.TestDelete(key)
171 Expect(err).ShouldNot(HaveOccurred(), t.Text())
172 t.TestDeletedKey(key)
176 func (t *DBTesting) DeleteRandom() bool {
177 if t.Present.Len() > 0 {
178 i := t.Rand.Intn(t.Present.Len())
179 t.Delete(t.Present.KeyAt(i))
185 func (t *DBTesting) RandomAct(round int) {
186 for i := 0; i < round; i++ {
187 if t.Rand.Int()%2 == 0 {
195 func DoDBTesting(t *DBTesting) {
204 for i := t.Deleted.Len() / 2; i >= 0; i-- {
207 t.RandomAct((t.Deleted.Len() + t.Present.Len()) * 10)
209 // Additional iterator testing
210 if db, ok := t.DB.(NewIterator); ok {
211 iter := db.TestNewIterator(nil)
212 Expect(iter.Error()).NotTo(HaveOccurred())
214 it := IteratorTesting{
219 DoIteratorTesting(&it)