github.com/iotexproject/iotex-core@v1.14.1-rc1/testutil/testdb/db.go (about) 1 package testdb 2 3 import ( 4 "bytes" 5 "context" 6 7 "github.com/golang/mock/gomock" 8 "github.com/pkg/errors" 9 10 "github.com/iotexproject/go-pkgs/hash" 11 "github.com/iotexproject/iotex-core/action/protocol" 12 "github.com/iotexproject/iotex-core/db" 13 "github.com/iotexproject/iotex-core/state" 14 "github.com/iotexproject/iotex-core/test/mock/mock_chainmanager" 15 ) 16 17 // NewMockKVStore returns a in memory KVStore. 18 func NewMockKVStore(ctrl *gomock.Controller) db.KVStore { 19 kv := db.NewMockKVStore(ctrl) 20 kmap := make(map[string]map[hash.Hash160][]byte) 21 vmap := make(map[string]map[hash.Hash160][]byte) 22 23 kv.EXPECT().Start(gomock.Any()).Return(nil).AnyTimes() 24 kv.EXPECT().Stop(gomock.Any()).DoAndReturn( 25 func(ctx context.Context) error { 26 kmap = nil 27 vmap = nil 28 return nil 29 }, 30 ).AnyTimes() 31 kv.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn( 32 func(ns string, k []byte, v []byte) error { 33 kns, ok := kmap[ns] 34 if !ok { 35 kns = make(map[hash.Hash160][]byte) 36 kmap[ns] = kns 37 } 38 vns, ok := vmap[ns] 39 if !ok { 40 vns = make(map[hash.Hash160][]byte) 41 vmap[ns] = vns 42 } 43 h := hash.Hash160b(k) 44 key := make([]byte, len(k)) 45 copy(key, k) 46 value := make([]byte, len(v)) 47 copy(value, v) 48 kns[h] = key 49 vns[h] = value 50 return nil 51 }, 52 ).AnyTimes() 53 kv.EXPECT().Get(gomock.Any(), gomock.Any()).DoAndReturn( 54 func(ns string, k []byte) ([]byte, error) { 55 vns, ok := vmap[ns] 56 if !ok { 57 return nil, db.ErrBucketNotExist 58 } 59 v, ok := vns[hash.Hash160b(k)] 60 if ok { 61 return v, nil 62 } 63 return nil, db.ErrNotExist 64 }, 65 ).AnyTimes() 66 kv.EXPECT().Delete(gomock.Any(), gomock.Any()).DoAndReturn( 67 func(ns string, k []byte) error { 68 kns, ok := kmap[ns] 69 if !ok { 70 return db.ErrBucketNotExist 71 } 72 vns := vmap[ns] 73 h := hash.Hash160b(k) 74 delete(kns, h) 75 delete(vns, h) 76 return nil 77 }, 78 ).AnyTimes() 79 kv.EXPECT().WriteBatch(gomock.Any()).Return(nil).AnyTimes() 80 var fk, fv [][]byte 81 kv.EXPECT().Filter(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn( 82 func(ns string, cond db.Condition, minKey, maxKey []byte) ([][]byte, [][]byte, error) { 83 // clear filter result 84 fk = fk[:0] 85 fv = fv[:0] 86 kns, ok := kmap[ns] 87 if !ok { 88 return nil, nil, db.ErrBucketNotExist 89 } 90 vns := vmap[ns] 91 checkMin := len(minKey) > 0 92 checkMax := len(maxKey) > 0 93 for h, k := range kns { 94 if checkMin && bytes.Compare(k, minKey) == -1 { 95 continue 96 } 97 if checkMax && bytes.Compare(k, maxKey) == 1 { 98 continue 99 } 100 v := vns[h] 101 if cond(k, v) { 102 key := make([]byte, len(k)) 103 copy(key, k) 104 value := make([]byte, len(v)) 105 copy(value, v) 106 fk = append(fk, key) 107 fv = append(fv, value) 108 } 109 } 110 return fk, fv, nil 111 }, 112 ).AnyTimes() 113 return kv 114 } 115 116 // NewMockStateManager returns a in memory StateManager. 117 func NewMockStateManager(ctrl *gomock.Controller) *mock_chainmanager.MockStateManager { 118 sm := NewMockStateManagerWithoutHeightFunc(ctrl) 119 sm.EXPECT().Height().Return(uint64(0), nil).AnyTimes() 120 121 return sm 122 } 123 124 // NewMockStateManagerWithoutHeightFunc returns a in memory StateManager without default height function. 125 func NewMockStateManagerWithoutHeightFunc(ctrl *gomock.Controller) *mock_chainmanager.MockStateManager { 126 sm := mock_chainmanager.NewMockStateManager(ctrl) 127 kv := NewMockKVStore(ctrl) 128 dk := protocol.NewDock() 129 view := protocol.View{} 130 sm.EXPECT().State(gomock.Any(), gomock.Any()).DoAndReturn( 131 func(s interface{}, opts ...protocol.StateOption) (uint64, error) { 132 cfg, err := protocol.CreateStateConfig(opts...) 133 if err != nil { 134 return 0, err 135 } 136 value, err := kv.Get(cfg.Namespace, cfg.Key) 137 if err != nil { 138 return 0, state.ErrStateNotExist 139 } 140 ss, ok := s.(state.Deserializer) 141 if !ok { 142 return 0, errors.New("state is not a deserializer") 143 } 144 return 0, ss.Deserialize(value) 145 }, 146 ).AnyTimes() 147 sm.EXPECT().PutState(gomock.Any(), gomock.Any()).DoAndReturn( 148 func(s interface{}, opts ...protocol.StateOption) (uint64, error) { 149 cfg, err := protocol.CreateStateConfig(opts...) 150 if err != nil { 151 return 0, err 152 } 153 ss, ok := s.(state.Serializer) 154 if !ok { 155 return 0, errors.New("state is not a serializer") 156 } 157 value, err := ss.Serialize() 158 if err != nil { 159 return 0, err 160 } 161 return 0, kv.Put(cfg.Namespace, cfg.Key, value) 162 }, 163 ).AnyTimes() 164 sm.EXPECT().DelState(gomock.Any()).DoAndReturn( 165 func(opts ...protocol.StateOption) (uint64, error) { 166 cfg, err := protocol.CreateStateConfig(opts...) 167 if err != nil { 168 return 0, err 169 } 170 return 0, kv.Delete(cfg.Namespace, cfg.Key) 171 }, 172 ).AnyTimes() 173 sm.EXPECT().States(gomock.Any()).DoAndReturn( 174 func(opts ...protocol.StateOption) (uint64, state.Iterator, error) { 175 cfg, err := protocol.CreateStateConfig(opts...) 176 if err != nil { 177 return 0, nil, err 178 } 179 var fv [][]byte 180 if cfg.Keys == nil { 181 _, fv, err = kv.Filter(cfg.Namespace, func(k, v []byte) bool { 182 return true 183 }, nil, nil) 184 if err != nil { 185 return 0, nil, state.ErrStateNotExist 186 } 187 } else { 188 for _, key := range cfg.Keys { 189 value, err := kv.Get(cfg.Namespace, key) 190 switch errors.Cause(err) { 191 case db.ErrNotExist, db.ErrBucketNotExist: 192 fv = append(fv, nil) 193 case nil: 194 fv = append(fv, value) 195 default: 196 return 0, nil, err 197 } 198 } 199 } 200 return 0, state.NewIterator(fv), nil 201 }, 202 ).AnyTimes() 203 // sm.EXPECT().Height().Return(uint64(0), nil).AnyTimes() 204 sm.EXPECT().Load(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn( 205 func(ns, key string, v interface{}) error { 206 return dk.Load(ns, key, v) 207 }, 208 ).AnyTimes() 209 sm.EXPECT().Unload(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn( 210 func(ns, key string, v interface{}) error { 211 return dk.Unload(ns, key, v) 212 }, 213 ).AnyTimes() 214 sm.EXPECT().ReadView(gomock.Any()).DoAndReturn( 215 func(name string) (interface{}, error) { 216 if v, hit := view[name]; hit { 217 return v, nil 218 } 219 return nil, protocol.ErrNoName 220 }, 221 ).AnyTimes() 222 sm.EXPECT().WriteView(gomock.Any(), gomock.Any()).DoAndReturn( 223 func(name string, v interface{}) error { 224 view[name] = v 225 return nil 226 }, 227 ).AnyTimes() 228 // use Snapshot() to simulate workingset.Reset() 229 sm.EXPECT().Snapshot().DoAndReturn( 230 func() int { 231 dk.Reset() 232 return 0 233 }, 234 ).AnyTimes() 235 236 return sm 237 }