github.com/mailru/activerecord@v1.12.2/pkg/octopus/testutil.go (about) 1 package octopus 2 3 import ( 4 "bytes" 5 "context" 6 "fmt" 7 "sync/atomic" 8 9 // Надо избавиться от использования этого модуля 10 "log" 11 ) 12 13 // FixtureType - структура определяющая ответ Response 14 // для конкретного запроса Request 15 type FixtureType struct { 16 // Уникальный идентификатор фикстуры 17 ID uint32 18 19 // Msg - задаёт тип запроса (select, insert, delete, update) 20 Msg RequetsTypeType 21 22 // Байтовое представление запроса 23 Request []byte 24 25 // Байтовое представление ответа 26 Response []byte 27 28 // Возвращаемые объекты. Используется в режиме mock 29 RespObjs []MockEntities 30 31 // Trigger - функция, которая будет выполнена при обработке запроса 32 // в случае если надо проверить insert или delete внутри этой функции 33 // можно модифицировать список фикстур сервера 34 Trigger func([]FixtureType) []FixtureType 35 } 36 37 type MockEntities interface { 38 // Метод который позволяет отдать ответ из mock сервера 39 MockSelectResponse() ([][]byte, error) 40 41 // Метод который позволяет поднять сущность из БД 42 RepoSelector(ctx context.Context) (any, error) 43 } 44 45 // CreateFixture - конструктор фикстур 46 func CreateFixture(id uint32, msg uint8, reqData []byte, respData []byte, trigger func([]FixtureType) []FixtureType) FixtureType { 47 return FixtureType{ 48 ID: id, 49 Msg: RequetsTypeType(msg), 50 Request: reqData, 51 Response: respData, 52 RespObjs: []MockEntities{}, 53 Trigger: trigger, 54 } 55 } 56 57 var fixtureID uint32 58 59 // CreateSelectFixture - конструктор фикстур для select-а 60 func CreateSelectFixture(reqData func(mocks []MockEntities) []byte, respEnt []MockEntities) (FixtureType, error) { 61 newID := atomic.AddUint32(&fixtureID, 1) 62 63 respByte, err := PackMockResponse(respEnt) 64 if err != nil { 65 return FixtureType{}, fmt.Errorf("error prepare fixture response: %s", err) 66 } 67 68 oft := FixtureType{ 69 ID: newID, 70 Msg: RequestTypeSelect, 71 Request: reqData(respEnt), 72 Response: respByte, 73 RespObjs: respEnt, 74 Trigger: nil, 75 } 76 77 return oft, nil 78 } 79 80 func CreateUpdateFixture(reqData []byte, trigger func([]FixtureType) []FixtureType) FixtureType { 81 newID := atomic.AddUint32(&fixtureID, 1) 82 83 dummyRespBytes := [][][]byte{{{'0'}}} 84 85 respData, err := PackResopnseStatus(RcOK, dummyRespBytes) 86 if err != nil { 87 log.Fatalf("error while pack update response: %s", err) 88 } 89 90 oft := FixtureType{ 91 ID: newID, 92 Msg: RequestTypeUpdate, 93 Request: reqData, 94 Response: respData, 95 RespObjs: nil, 96 Trigger: trigger, 97 } 98 99 return oft 100 } 101 102 func CreateDeleteFixture(reqData []byte, trigger func([]FixtureType) []FixtureType) FixtureType { 103 newID := atomic.AddUint32(&fixtureID, 1) 104 105 dummyRespBytes := [][][]byte{{{'0'}}} 106 107 respData, err := PackResopnseStatus(RcOK, dummyRespBytes) 108 if err != nil { 109 log.Fatalf("error while pack delete response: %s", err) 110 } 111 112 oft := FixtureType{ 113 ID: newID, 114 Msg: RequestTypeDelete, 115 Request: reqData, 116 Response: respData, 117 RespObjs: nil, 118 Trigger: trigger, 119 } 120 121 return oft 122 } 123 124 func CreateInsertOrReplaceFixture(entity MockEntities, reqData []byte, trigger func([]FixtureType) []FixtureType) FixtureType { 125 newID := atomic.AddUint32(&fixtureID, 1) 126 127 // by default return same entity 128 respData, err := PackMockResponse([]MockEntities{entity}) 129 if err != nil { 130 log.Fatalf("error while pack insert or replace response: %s", err) 131 } 132 133 oft := FixtureType{ 134 ID: newID, 135 Msg: RequestTypeInsert, 136 Request: reqData, 137 Response: respData, 138 RespObjs: nil, 139 Trigger: trigger, 140 } 141 142 return oft 143 } 144 145 // CreateCallFixture - конструктор фикстур для вызова процедуры 146 func CreateCallFixture(reqData func(mocks []MockEntities) []byte, respEnt []MockEntities) (FixtureType, error) { 147 newID := atomic.AddUint32(&fixtureID, 1) 148 149 respByte, err := PackMockResponse(respEnt) 150 if err != nil { 151 return FixtureType{}, fmt.Errorf("error prepare fixture response: %s", err) 152 } 153 154 oft := FixtureType{ 155 ID: newID, 156 Msg: RequestTypeCall, 157 Request: reqData(respEnt), 158 Response: respByte, 159 RespObjs: respEnt, 160 Trigger: nil, 161 } 162 163 return oft, nil 164 } 165 166 func WrapTriggerWithOnUsePromise(trigger func(types []FixtureType) []FixtureType) (wrappedTrigger func(types []FixtureType) []FixtureType, isUsed func() bool) { 167 used := false 168 169 promise := func() bool { 170 return used 171 } 172 173 wrappedTrigger = func(types []FixtureType) []FixtureType { 174 used = true 175 176 if trigger != nil { 177 return trigger(types) 178 } 179 180 return types 181 } 182 183 return wrappedTrigger, promise 184 } 185 186 func PackMockResponse(ome []MockEntities) ([]byte, error) { 187 tuples := [][][]byte{} 188 189 for _, om := range ome { 190 tuple, err := om.MockSelectResponse() 191 if err != nil { 192 return nil, fmt.Errorf("error prepare fixtures: %s", err) 193 } 194 195 tuples = append(tuples, tuple) 196 } 197 198 return PackResopnseStatus(RcOK, tuples) 199 } 200 201 func UnpackSelect(data []byte) (ns, indexnum, offset, limit uint32, keys [][][]byte, err error) { 202 rdr := bytes.NewReader(data) 203 204 if ns, err = UnpackSpace(rdr); err != nil { 205 return 206 } 207 208 if indexnum, err = UnpackIndexNum(rdr); err != nil { 209 return 210 } 211 212 if offset, err = UnpackOffset(rdr); err != nil { 213 return 214 } 215 216 if limit, err = UnpackLimit(rdr); err != nil { 217 return 218 } 219 220 if keys, err = UnpackTuples(rdr); err != nil { 221 return 222 } 223 224 return 225 } 226 227 type SelectMockFixture struct { 228 Indexnum uint32 229 Offset uint32 230 Limit uint32 231 Keys [][][]byte 232 RespTuples []TupleData 233 } 234 235 type InsertMockFixture struct { 236 NeedRetVal bool 237 InsertMode InsertMode 238 Tuple TupleData 239 } 240 241 type UpdateMockFixture struct { 242 PrimaryKey [][]byte 243 UpdateOps []Ops 244 } 245 246 type DeleteMockFixture struct { 247 PrimaryKey [][]byte 248 } 249 250 type CallMockFixture struct { 251 ProcName string 252 Args [][]byte 253 RespTuples []TupleData 254 }