asmt/db/db_test.go
db/db_test.goRaw
1/**
2 * @file
3 * @copyright defined in aergo/LICENSE.txt
4 */
5package db
6
7import (
8 "fmt"
9 "io/ioutil"
10 "log"
11 "os"
12 "strconv"
13 "testing"
14
15 "github.com/stretchr/testify/assert"
16)
17
18const (
19 tmpDbTestKey1 = "tempkey1"
20 tmpDbTestKey2 = "tempkey2"
21 tmpDbTestStrVal1 = "val1"
22 tmpDbTestStrVal2 = "val2"
23 tmpDbTestIntVal1 = 1
24 tmpDbTestIntVal2 = 2
25)
26
27func createTmpDB(key ImplType) (dir string, db DB) {
28 dir, err := ioutil.TempDir("", string(key))
29 if err != nil {
30 log.Fatal(err)
31 }
32
33 db = NewDB(key, dir)
34
35 return
36}
37
38func setInitData(db DB) {
39 tx := db.NewTx()
40
41 tx.Set([]byte("1"), []byte("1"))
42 tx.Set([]byte("2"), []byte("2"))
43 tx.Set([]byte("3"), []byte("3"))
44 tx.Set([]byte("4"), []byte("4"))
45 tx.Set([]byte("5"), []byte("5"))
46 tx.Set([]byte("6"), []byte("6"))
47 tx.Set([]byte("7"), []byte("7"))
48
49 tx.Commit()
50}
51
52func TestGetSetDeleteExist(t *testing.T) {
53 // for each db implementation
54 for key := range dbImpls {
55 dir, db := createTmpDB(key)
56
57 // initial value of empty key must be empty byte
58 assert.Empty(t, db.Get([]byte(tmpDbTestKey1)), db.Type())
59 assert.False(t, db.Exist([]byte(tmpDbTestKey1)), db.Type())
60
61 // set value
62 db.Set([]byte(tmpDbTestKey1), []byte(tmpDbTestStrVal1))
63
64 // check value set
65 assert.Equal(t, tmpDbTestStrVal1, string(db.Get([]byte(tmpDbTestKey1))), db.Type())
66 assert.True(t, db.Exist([]byte(tmpDbTestKey1)), db.Type())
67
68 // delete value
69 db.Delete([]byte(tmpDbTestKey1))
70
71 // value must be erased
72 assert.Empty(t, db.Get([]byte(tmpDbTestKey1)), db.Type())
73 assert.False(t, db.Exist([]byte(tmpDbTestKey1)), db.Type())
74
75 db.Close()
76 os.RemoveAll(dir)
77 }
78}
79
80func TestTransactionSet(t *testing.T) {
81
82 for key := range dbImpls {
83 dir, db := createTmpDB(key)
84
85 // create a new writable tx
86 tx := db.NewTx()
87
88 // set the value in the tx
89 tx.Set([]byte(tmpDbTestKey1), []byte(tmpDbTestStrVal1))
90 // the value will not visible at a db
91 assert.Empty(t, db.Get([]byte(tmpDbTestKey1)), db.Type())
92
93 tx.Commit()
94
95 // after commit, the value visible from the db
96 assert.Equal(t, tmpDbTestStrVal1, string(db.Get([]byte(tmpDbTestKey1))), db.Type())
97
98 db.Close()
99 os.RemoveAll(dir)
100 }
101}
102
103func TestTransactionDiscard(t *testing.T) {
104
105 for key := range dbImpls {
106 dir, db := createTmpDB(key)
107
108 // create a new writable tx
109 tx := db.NewTx()
110 // discard test
111 tx = db.NewTx()
112 // set the value in the tx
113 tx.Set([]byte(tmpDbTestKey1), []byte(tmpDbTestStrVal2))
114
115 // discard tx
116 tx.Discard()
117
118 assert.Panics(t, func() { tx.Commit() }, "commit after discard is not allowed")
119
120 // after discard, the value must be reset at the db
121 assert.False(t, db.Exist([]byte(tmpDbTestKey1)), db.Type())
122
123 db.Close()
124 os.RemoveAll(dir)
125 }
126}
127
128func TestTransactionDelete(t *testing.T) {
129
130 for key := range dbImpls {
131 dir, db := createTmpDB(key)
132
133 // create a new writable tx
134 tx := db.NewTx()
135
136 // set the value in the tx
137 tx.Set([]byte(tmpDbTestKey1), []byte(tmpDbTestStrVal1))
138
139 // delete the value in the tx
140 tx.Delete([]byte(tmpDbTestKey1))
141
142 tx.Commit()
143
144 // after commit, chekc the value from the db
145 assert.Equal(t, "", string(db.Get([]byte(tmpDbTestKey1))), db.Type())
146
147 db.Close()
148 os.RemoveAll(dir)
149 }
150}
151
152func TestTransactionCommitTwice(t *testing.T) {
153 for key := range dbImpls {
154 dir, db := createTmpDB(key)
155
156 // create a new writable tx
157 tx := db.NewTx()
158
159 // a first commit will success
160 tx.Commit()
161
162 // a second commit will cause panic
163 assert.Panics(t, func() { tx.Commit() })
164
165 db.Close()
166 os.RemoveAll(dir)
167 }
168}
169
170func TestBulk(t *testing.T) {
171
172 for key := range dbImpls {
173 dir, db := createTmpDB(key)
174
175 // create a new Bulk instance
176 bulk := db.NewBulk()
177
178 // set the huge number of value in the bulk
179 for i := 0; i < 1000000; i++ {
180 bulk.Set([]byte(fmt.Sprintf("key%d", i)),
181 []byte(tmpDbTestStrVal1))
182 }
183
184 bulk.Flush()
185
186 // after commit, the value visible from the db
187
188 for i := 0; i < 1000000; i++ {
189 assert.Equal(t, tmpDbTestStrVal1, string(db.Get([]byte(fmt.Sprintf("key%d", i)))), db.Type())
190 }
191
192 db.Close()
193 os.RemoveAll(dir)
194 }
195}
196
197func TestIter(t *testing.T) {
198
199 for key := range dbImpls {
200 dir, db := createTmpDB(key)
201
202 setInitData(db)
203
204 i := 1
205
206 for iter := db.Iterator(nil, nil); iter.Valid(); iter.Next() {
207 assert.EqualValues(t, strconv.Itoa(i), string(iter.Key()))
208 i++
209 }
210
211 db.Close()
212 os.RemoveAll(dir)
213 }
214}
215
216func TestRangeIter(t *testing.T) {
217
218 for key := range dbImpls {
219 dir, db := createTmpDB(key)
220
221 setInitData(db)
222
223 // test iteration 2 -> 5
224 i := 2
225 for iter := db.Iterator([]byte("2"), []byte("5")); iter.Valid(); iter.Next() {
226 assert.EqualValues(t, strconv.Itoa(i), string(iter.Key()))
227 assert.EqualValues(t, strconv.Itoa(i), string(iter.Value()))
228 i++
229 }
230 assert.EqualValues(t, i, 5)
231
232 // nil sames with []byte("0")
233 // test iteration 0 -> 5
234 i = 1
235 for iter := db.Iterator(nil, []byte("5")); iter.Valid(); iter.Next() {
236 assert.EqualValues(t, strconv.Itoa(i), string(iter.Key()))
237 assert.EqualValues(t, strconv.Itoa(i), string(iter.Value()))
238 i++
239 }
240 assert.EqualValues(t, i, 5)
241
242 db.Close()
243 os.RemoveAll(dir)
244 }
245}
246
247func TestReverseIter(t *testing.T) {
248
249 for key := range dbImpls {
250 dir, db := createTmpDB(key)
251
252 setInitData(db)
253
254 // test reverse iteration 5 <- 2
255 i := 5
256 for iter := db.Iterator([]byte("5"), []byte("2")); iter.Valid(); iter.Next() {
257 assert.EqualValues(t, strconv.Itoa(i), string(iter.Key()))
258 assert.EqualValues(t, strconv.Itoa(i), string(iter.Value()))
259 i--
260 }
261 assert.EqualValues(t, i, 2)
262
263 // nil sames with []byte("0")
264 // test reverse iteration 5 -> 0
265 i = 5
266 for iter := db.Iterator([]byte("5"), nil); iter.Valid(); iter.Next() {
267 assert.EqualValues(t, strconv.Itoa(i), string(iter.Key()))
268 assert.EqualValues(t, strconv.Itoa(i), string(iter.Value()))
269 i--
270 }
271 assert.EqualValues(t, i, 0)
272
273 db.Close()
274 os.RemoveAll(dir)
275 }
276}