github.com/voedger/voedger@v0.0.0-20240520144910-273e84102129/pkg/istructsmem/internal/teststore/store.go (about) 1 /* 2 * Copyright (c) 2021-present Sigma-Soft, Ltd. 3 * @author: Nikolay Nikitin 4 */ 5 6 package teststore 7 8 import ( 9 "bytes" 10 "context" 11 12 "github.com/voedger/voedger/pkg/istorage" 13 "github.com/voedger/voedger/pkg/istorage/mem" 14 "github.com/voedger/voedger/pkg/istorage/provider" 15 "github.com/voedger/voedger/pkg/istructs" 16 ) 17 18 // Test storage. Trained to return the specified error 19 type ( 20 scheduleStorageError struct { 21 err error 22 pKey, cCols []byte 23 } 24 25 damagedStorageFunc func(*[]byte) 26 scheduleStorageDamage struct { 27 dam damagedStorageFunc 28 scheduleStorageError 29 } 30 31 TestMemStorage struct { 32 storage istorage.IAppStorage 33 get, put scheduleStorageError 34 damage scheduleStorageDamage 35 } 36 37 testStorageProvider struct { 38 testStorage *TestMemStorage 39 } 40 ) 41 42 func (tsp *testStorageProvider) AppStorage(appName istructs.AppQName) (structs istorage.IAppStorage, err error) { 43 return tsp.testStorage, nil 44 } 45 46 // Returns new storage provider for specified test storage 47 func NewStorageProvider(ts *TestMemStorage) istorage.IAppStorageProvider { 48 return &testStorageProvider{testStorage: ts} 49 } 50 51 // Returns new test storage 52 func NewStorage() *TestMemStorage { 53 s := TestMemStorage{get: scheduleStorageError{}, put: scheduleStorageError{}} 54 asf := mem.Provide() 55 sp := provider.Provide(asf) 56 var err error 57 if s.storage, err = sp.AppStorage(istructs.AppQName_test1_app1); err != nil { 58 panic(err) 59 } 60 61 return &s 62 } 63 64 // Returns new test storage and new test storage provider 65 func New() (storage *TestMemStorage, provider istorage.IAppStorageProvider) { 66 s := NewStorage() 67 return s, NewStorageProvider(s) 68 } 69 70 // Returns is partition key and clustering columns matches the scheduled error 71 func (e *scheduleStorageError) match(pKey, cCols []byte) bool { 72 return ((len(e.pKey) == 0) || bytes.Equal(e.pKey, pKey)) && 73 ((len(e.cCols) == 0) || bytes.Equal(e.cCols, cCols)) 74 } 75 76 // Clear all scheduled errors 77 func (s *TestMemStorage) Reset() { 78 s.get = scheduleStorageError{} 79 s.put = scheduleStorageError{} 80 s.damage = scheduleStorageDamage{} 81 } 82 83 // Schedule Get() to return error 84 func (s *TestMemStorage) ScheduleGetError(err error, pKey, cCols []byte) { 85 s.get.err = err 86 s.get.pKey = make([]byte, len(pKey)) 87 copy(s.get.pKey, pKey) 88 s.get.cCols = make([]byte, len(cCols)) 89 copy(s.get.cCols, cCols) 90 } 91 92 // Schedule Get() to return damaged data 93 func (s *TestMemStorage) ScheduleGetDamage(dam damagedStorageFunc, pKey, cCols []byte) { 94 s.damage.dam = dam 95 s.damage.pKey = make([]byte, len(pKey)) 96 copy(s.damage.pKey, pKey) 97 s.damage.cCols = make([]byte, len(cCols)) 98 copy(s.damage.cCols, cCols) 99 } 100 101 // Schedule Put() to return error 102 func (s *TestMemStorage) SchedulePutError(err error, pKey, cCols []byte) { 103 s.put.err = err 104 s.put.pKey = make([]byte, len(pKey)) 105 copy(s.put.pKey, pKey) 106 s.put.cCols = make([]byte, len(cCols)) 107 copy(s.put.cCols, cCols) 108 } 109 110 func (s *TestMemStorage) Get(pKey []byte, cCols []byte, data *[]byte) (ok bool, err error) { 111 if s.get.err != nil { 112 if s.get.match(pKey, cCols) { 113 err = s.get.err 114 s.get.err = nil 115 return false, err 116 } 117 } 118 119 ok, err = s.storage.Get(pKey, cCols, data) 120 121 if ok && (s.damage.dam != nil) { 122 if s.damage.match(pKey, cCols) { 123 s.damage.dam(data) 124 s.damage.dam = nil 125 return ok, err 126 } 127 } 128 129 return ok, err 130 } 131 132 func (s *TestMemStorage) GetBatch(pKey []byte, items []istorage.GetBatchItem) (err error) { 133 if s.get.err != nil { 134 for _, item := range items { 135 if s.get.match(pKey, item.CCols) { 136 err = s.get.err 137 s.get.err = nil 138 return err 139 } 140 } 141 } 142 143 err = s.storage.GetBatch(pKey, items) 144 145 if s.damage.dam != nil { 146 for i := 0; i < len(items); i++ { 147 if s.damage.match(pKey, items[i].CCols) { 148 if items[i].Ok { 149 s.damage.dam(items[i].Data) 150 s.damage.dam = nil 151 } 152 } 153 } 154 } 155 156 return err 157 } 158 159 func (s *TestMemStorage) Put(pKey []byte, cCols []byte, value []byte) (err error) { 160 if s.put.err != nil { 161 if s.put.match(pKey, cCols) { 162 err = s.put.err 163 s.put.err = nil 164 return err 165 } 166 } 167 return s.storage.Put(pKey, cCols, value) 168 } 169 170 func (s *TestMemStorage) PutBatch(items []istorage.BatchItem) (err error) { 171 for _, p := range items { 172 if err = s.Put(p.PKey, p.CCols, p.Value); err != nil { 173 return err 174 } 175 } 176 return nil 177 } 178 179 func (s *TestMemStorage) Read(ctx context.Context, pKey []byte, startCCols, finishCCols []byte, cb istorage.ReadCallback) (err error) { 180 cbWrap := func(cCols []byte, data []byte) (err error) { 181 if s.get.err != nil { 182 if s.get.match(pKey, cCols) { 183 err = s.get.err 184 s.get.err = nil 185 return err 186 } 187 } 188 189 if s.damage.dam != nil { 190 if s.damage.match(pKey, cCols) { 191 s.damage.dam(&data) 192 s.damage.dam = nil 193 } 194 } 195 196 return cb(cCols, data) 197 } 198 199 return s.storage.Read(ctx, pKey, startCCols, finishCCols, cbWrap) 200 }