OSDN Git Service

new repo
[bytom/vapor.git] / vendor / github.com / syndtr / goleveldb / leveldb / testutil / db.go
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
7 package testutil
8
9 import (
10         "fmt"
11         "math/rand"
12
13         . "github.com/onsi/gomega"
14
15         "github.com/syndtr/goleveldb/leveldb/errors"
16         "github.com/syndtr/goleveldb/leveldb/iterator"
17         "github.com/syndtr/goleveldb/leveldb/util"
18 )
19
20 type DB interface{}
21
22 type Put interface {
23         TestPut(key []byte, value []byte) error
24 }
25
26 type Delete interface {
27         TestDelete(key []byte) error
28 }
29
30 type Find interface {
31         TestFind(key []byte) (rkey, rvalue []byte, err error)
32 }
33
34 type Get interface {
35         TestGet(key []byte) (value []byte, err error)
36 }
37
38 type Has interface {
39         TestHas(key []byte) (ret bool, err error)
40 }
41
42 type NewIterator interface {
43         TestNewIterator(slice *util.Range) iterator.Iterator
44 }
45
46 type DBAct int
47
48 func (a DBAct) String() string {
49         switch a {
50         case DBNone:
51                 return "none"
52         case DBPut:
53                 return "put"
54         case DBOverwrite:
55                 return "overwrite"
56         case DBDelete:
57                 return "delete"
58         case DBDeleteNA:
59                 return "delete_na"
60         }
61         return "unknown"
62 }
63
64 const (
65         DBNone DBAct = iota
66         DBPut
67         DBOverwrite
68         DBDelete
69         DBDeleteNA
70 )
71
72 type DBTesting struct {
73         Rand *rand.Rand
74         DB   interface {
75                 Get
76                 Put
77                 Delete
78         }
79         PostFn             func(t *DBTesting)
80         Deleted, Present   KeyValue
81         Act, LastAct       DBAct
82         ActKey, LastActKey []byte
83 }
84
85 func (t *DBTesting) post() {
86         if t.PostFn != nil {
87                 t.PostFn(t)
88         }
89 }
90
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
94 }
95
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)
98 }
99
100 func (t *DBTesting) Text() string {
101         return "DBTesting " + t.text()
102 }
103
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())
108 }
109
110 func (t *DBTesting) TestAllPresent() {
111         t.Present.IterateShuffled(t.Rand, func(i int, key, value []byte) {
112                 t.TestPresentKV(key, value)
113         })
114 }
115
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())
119 }
120
121 func (t *DBTesting) TestAllDeleted() {
122         t.Deleted.IterateShuffled(t.Rand, func(i int, key, value []byte) {
123                 t.TestDeletedKey(key)
124         })
125 }
126
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) {
131                 if i >= dn {
132                         key, value := t.Present.Index(i - dn)
133                         t.TestPresentKV(key, value)
134                 } else {
135                         t.TestDeletedKey(t.Deleted.KeyAt(i))
136                 }
137         })
138 }
139
140 func (t *DBTesting) Put(key, value []byte) {
141         if new := t.Present.PutU(key, value); new {
142                 t.setAct(DBPut, key)
143         } else {
144                 t.setAct(DBOverwrite, key)
145         }
146         t.Deleted.Delete(key)
147         err := t.DB.TestPut(key, value)
148         Expect(err).ShouldNot(HaveOccurred(), t.Text())
149         t.TestPresentKV(key, value)
150         t.post()
151 }
152
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)
157                 t.Put(key, value)
158                 return true
159         }
160         return false
161 }
162
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)
167         } else {
168                 t.setAct(DBDeleteNA, key)
169         }
170         err := t.DB.TestDelete(key)
171         Expect(err).ShouldNot(HaveOccurred(), t.Text())
172         t.TestDeletedKey(key)
173         t.post()
174 }
175
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))
180                 return true
181         }
182         return false
183 }
184
185 func (t *DBTesting) RandomAct(round int) {
186         for i := 0; i < round; i++ {
187                 if t.Rand.Int()%2 == 0 {
188                         t.PutRandom()
189                 } else {
190                         t.DeleteRandom()
191                 }
192         }
193 }
194
195 func DoDBTesting(t *DBTesting) {
196         if t.Rand == nil {
197                 t.Rand = NewRand()
198         }
199
200         t.DeleteRandom()
201         t.PutRandom()
202         t.DeleteRandom()
203         t.DeleteRandom()
204         for i := t.Deleted.Len() / 2; i >= 0; i-- {
205                 t.PutRandom()
206         }
207         t.RandomAct((t.Deleted.Len() + t.Present.Len()) * 10)
208
209         // Additional iterator testing
210         if db, ok := t.DB.(NewIterator); ok {
211                 iter := db.TestNewIterator(nil)
212                 Expect(iter.Error()).NotTo(HaveOccurred())
213
214                 it := IteratorTesting{
215                         KeyValue: t.Present,
216                         Iter:     iter,
217                 }
218
219                 DoIteratorTesting(&it)
220                 iter.Release()
221         }
222 }