github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/syndtr/goleveldb/leveldb/testutil/db.go (about) 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/insionng/yougam/libraries/onsi/gomega" 14 15 "github.com/insionng/yougam/libraries/syndtr/goleveldb/leveldb/errors" 16 "github.com/insionng/yougam/libraries/syndtr/goleveldb/leveldb/iterator" 17 "github.com/insionng/yougam/libraries/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 }