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  }