github.com/voedger/voedger@v0.0.0-20240520144910-273e84102129/pkg/state/impl_test.go (about) 1 /* 2 * Copyright (c) 2022-present unTill Pro, Ltd. 3 */ 4 5 package state 6 7 import ( 8 "context" 9 "fmt" 10 "testing" 11 12 "github.com/stretchr/testify/mock" 13 "github.com/stretchr/testify/require" 14 "github.com/voedger/voedger/pkg/appdef" 15 "github.com/voedger/voedger/pkg/istructs" 16 ) 17 18 var ( 19 testRecordQName1 = appdef.NewQName("test", "record1") 20 testRecordQName2 = appdef.NewQName("test", "record2") 21 testRecordQName3 = appdef.NewQName("test", "record3") 22 testViewRecordQName1 = appdef.NewQName("test", "viewRecord1") 23 testViewRecordQName2 = appdef.NewQName("test", "viewRecord2") 24 testStorage = appdef.NewQName("test", "testStorage") 25 testWSQName = appdef.NewQName("test", "testWS") 26 testWSDescriptorQName = appdef.NewQName("test", "testWSDescriptor") 27 testAppQName = istructs.NewAppQName("test", "testApp") 28 ) 29 30 func TestSimpleWSIDFunc(t *testing.T) { 31 require.Equal(t, istructs.WSID(10), SimpleWSIDFunc(istructs.WSID(10))()) 32 } 33 func TestSimplePartitionIDFuncDFunc(t *testing.T) { 34 require.Equal(t, istructs.PartitionID(10), SimplePartitionIDFunc(istructs.PartitionID(10))()) 35 } 36 func Test_put(t *testing.T) { 37 t.Run("Should be ok", func(t *testing.T) { 38 mrw := &mockRowWriter{} 39 mrw. 40 On("PutInt32", "int32Fld", int32(1)). 41 On("PutInt64", "int64Fld", int64(2)). 42 On("PutFloat32", "float32Fld", float32(3.1)). 43 On("PutFloat64", "float64Fld", 4.2). 44 On("PutBytes", "byteFld", []byte{5}). 45 On("PutString", "stringFld", "string"). 46 On("PutQName", "qNameFld", testRecordQName1). 47 On("PutBool", "boolFld", true). 48 On("PutRecordID", "recordIDFld", istructs.RecordID(6)) 49 mrr := &mockRowReader{} 50 mrr. 51 On("AsInt32", "int32Fld").Return(int32(1)). 52 On("AsInt64", "int64Fld").Return(int64(2)). 53 On("AsFloat32", "float32Fld").Return(float32(3.1)). 54 On("AsFloat64", "float64Fld").Return(4.2). 55 On("AsBytes", "byteFld").Return([]byte{5}). 56 On("AsString", "stringFld").Return("string"). 57 On("AsQName", "qNameFld").Return(testRecordQName1). 58 On("AsBool", "boolFld").Return(true). 59 On("AsRecordID", "recordIDFld").Return(istructs.RecordID(6)) 60 61 put("int32Fld", appdef.DataKind_int32, mrr, mrw) 62 put("int64Fld", appdef.DataKind_int64, mrr, mrw) 63 put("float32Fld", appdef.DataKind_float32, mrr, mrw) 64 put("float64Fld", appdef.DataKind_float64, mrr, mrw) 65 put("byteFld", appdef.DataKind_bytes, mrr, mrw) 66 put("stringFld", appdef.DataKind_string, mrr, mrw) 67 put("qNameFld", appdef.DataKind_QName, mrr, mrw) 68 put("boolFld", appdef.DataKind_bool, mrr, mrw) 69 put("recordIDFld", appdef.DataKind_RecordID, mrr, mrw) 70 71 mrw.AssertExpectations(t) 72 mrr.AssertExpectations(t) 73 }) 74 t.Run("Should panic when data kind not supported", func(t *testing.T) { 75 require.PanicsWithError(t, 76 fmt.Sprintf("illegal state: field - 'notSupported', kind - '%d': not supported", appdef.DataKind_FakeLast), 77 func() { put("notSupported", appdef.DataKind_FakeLast, nil, nil) }) 78 }) 79 } 80 81 func Test_getStorageID(t *testing.T) { 82 t.Run("Should be ok", func(t *testing.T) { 83 tests := []struct { 84 name string 85 kb istructs.IStateKeyBuilder 86 expectedStorage appdef.QName 87 }{ 88 { 89 name: "General storage key", 90 kb: newKeyBuilder(Record, appdef.NullQName), 91 expectedStorage: Record, 92 }, 93 { 94 name: "Email storage key", 95 kb: &sendMailKeyBuilder{keyBuilder: newKeyBuilder(SendMail, appdef.NullQName)}, 96 expectedStorage: SendMail, 97 }, 98 { 99 name: "HTTP storage key", 100 kb: &httpKeyBuilder{keyBuilder: newKeyBuilder(Http, appdef.NullQName)}, 101 expectedStorage: Http, 102 }, 103 { 104 name: "View storage key", 105 kb: &viewKeyBuilder{}, 106 expectedStorage: View, 107 }, 108 } 109 for _, test := range tests { 110 require.Equal(t, test.expectedStorage, test.kb.Storage()) 111 } 112 }) 113 } 114 115 type nilAppStructs struct { 116 istructs.IAppStructs 117 } 118 119 func nilAppStructsFunc() istructs.IAppStructs { 120 return &nilAppStructs{} 121 } 122 123 func (s *nilAppStructs) AppDef() appdef.IAppDef { return nil } 124 func (s *nilAppStructs) Events() istructs.IEvents { return nil } 125 func (s *nilAppStructs) Records() istructs.IRecords { return nil } 126 func (s *nilAppStructs) ViewRecords() istructs.IViewRecords { return nil } 127 128 type nilEvents struct { 129 istructs.IEvents 130 } 131 132 type nilRecords struct { 133 istructs.IRecords 134 } 135 136 type nilAppDef struct { 137 appdef.IAppDef 138 } 139 140 type nilViewRecords struct { 141 istructs.IViewRecords 142 } 143 144 type mockAppStructs struct { 145 istructs.IAppStructs 146 mock.Mock 147 } 148 149 func (s *mockAppStructs) AppQName() istructs.AppQName { 150 return s.Called().Get(0).(istructs.AppQName) 151 } 152 func (s *mockAppStructs) AppDef() appdef.IAppDef { 153 return s.Called().Get(0).(appdef.IAppDef) 154 } 155 func (s *mockAppStructs) Events() istructs.IEvents { return s.Called().Get(0).(istructs.IEvents) } 156 func (s *mockAppStructs) Records() istructs.IRecords { return s.Called().Get(0).(istructs.IRecords) } 157 func (s *mockAppStructs) ViewRecords() istructs.IViewRecords { 158 return s.Called().Get(0).(istructs.IViewRecords) 159 } 160 161 type mockEvents struct { 162 istructs.IEvents 163 mock.Mock 164 } 165 166 func (e *mockEvents) ReadPLog(ctx context.Context, partition istructs.PartitionID, offset istructs.Offset, toReadCount int, cb istructs.PLogEventsReaderCallback) (err error) { 167 return e.Called(ctx, partition, offset, toReadCount, cb).Error(0) 168 } 169 func (e *mockEvents) ReadWLog(ctx context.Context, workspace istructs.WSID, offset istructs.Offset, toReadCount int, cb istructs.WLogEventsReaderCallback) (err error) { 170 return e.Called(ctx, workspace, offset, toReadCount, cb).Error(0) 171 } 172 173 type mockRecords struct { 174 istructs.IRecords 175 mock.Mock 176 } 177 178 func (r *mockRecords) GetBatch(workspace istructs.WSID, highConsistency bool, ids []istructs.RecordGetBatchItem) (err error) { 179 return r.Called(workspace, highConsistency, ids).Error(0) 180 } 181 func (r *mockRecords) Get(workspace istructs.WSID, highConsistency bool, id istructs.RecordID) (record istructs.IRecord, err error) { 182 args := r.Called(workspace, highConsistency, id) 183 184 if args.Get(0) == nil { 185 return nil, args.Error(1) 186 187 } 188 return args.Get(0).(istructs.IRecord), args.Error(1) 189 } 190 func (r *mockRecords) GetSingleton(workspace istructs.WSID, qName appdef.QName) (record istructs.IRecord, err error) { 191 aa := r.Called(workspace, qName) 192 return aa.Get(0).(istructs.IRecord), aa.Error(1) 193 } 194 195 type mockViewRecords struct { 196 istructs.IViewRecords 197 mock.Mock 198 } 199 200 func (r *mockViewRecords) KeyBuilder(view appdef.QName) istructs.IKeyBuilder { 201 return r.Called(view).Get(0).(istructs.IKeyBuilder) 202 } 203 func (r *mockViewRecords) NewValueBuilder(view appdef.QName) istructs.IValueBuilder { 204 return r.Called(view).Get(0).(istructs.IValueBuilder) 205 } 206 func (r *mockViewRecords) UpdateValueBuilder(view appdef.QName, existing istructs.IValue) istructs.IValueBuilder { 207 return r.Called(view, existing).Get(0).(istructs.IValueBuilder) 208 } 209 func (r *mockViewRecords) Get(workspace istructs.WSID, key istructs.IKeyBuilder) (value istructs.IValue, err error) { 210 c := r.Called(workspace, key) 211 if c.Get(0) == nil { 212 return nil, c.Error(1) 213 } 214 return c.Get(0).(istructs.IValue), c.Error(1) 215 } 216 func (r *mockViewRecords) GetBatch(workspace istructs.WSID, kv []istructs.ViewRecordGetBatchItem) (err error) { 217 return r.Called(workspace, kv).Error(0) 218 } 219 func (r *mockViewRecords) PutBatch(workspace istructs.WSID, batch []istructs.ViewKV) (err error) { 220 return r.Called(workspace, batch).Error(0) 221 } 222 func (r *mockViewRecords) Read(ctx context.Context, workspace istructs.WSID, key istructs.IKeyBuilder, cb istructs.ValuesCallback) (err error) { 223 return r.Called(ctx, workspace, key, cb).Error(0) 224 } 225 226 type mockRecord struct { 227 istructs.IRecord 228 mock.Mock 229 } 230 231 func (r *mockRecord) QName() appdef.QName { return r.Called().Get(0).(appdef.QName) } 232 func (r *mockRecord) AsInt64(name string) int64 { return r.Called(name).Get(0).(int64) } 233 func (r *mockRecord) AsQName(name string) appdef.QName { 234 return r.Called(name).Get(0).(appdef.QName) 235 } 236 func (r *mockRecord) FieldNames(cb func(fieldName string)) { 237 r.Called(cb) 238 } 239 240 type mockValue struct { 241 istructs.IValue 242 mock.Mock 243 } 244 245 func (v *mockValue) AsInt32(name string) int32 { return v.Called(name).Get(0).(int32) } 246 func (v *mockValue) AsInt64(name string) int64 { return v.Called(name).Get(0).(int64) } 247 func (v *mockValue) AsFloat32(name string) float32 { return v.Called(name).Get(0).(float32) } 248 func (v *mockValue) AsFloat64(name string) float64 { return v.Called(name).Get(0).(float64) } 249 func (v *mockValue) AsBytes(name string) []byte { return v.Called(name).Get(0).([]byte) } 250 func (v *mockValue) AsString(name string) string { return v.Called(name).String(0) } 251 func (v *mockValue) AsQName(name string) appdef.QName { 252 return v.Called(name).Get(0).(appdef.QName) 253 } 254 func (v *mockValue) AsBool(name string) bool { return v.Called(name).Bool(0) } 255 func (v *mockValue) AsRecordID(name string) istructs.RecordID { 256 return v.Called(name).Get(0).(istructs.RecordID) 257 } 258 func (v *mockValue) AsRecord(name string) (record istructs.IRecord) { 259 return v.Called(name).Get(0).(istructs.IRecord) 260 } 261 func (v *mockValue) AsEvent(name string) (event istructs.IDbEvent) { 262 return v.Called(name).Get(0).(istructs.IDbEvent) 263 } 264 265 type nilKey struct { 266 istructs.IKey 267 } 268 269 type nilValue struct { 270 istructs.IValue 271 } 272 273 type mockStorage struct { 274 IWithInsert 275 mock.Mock 276 } 277 278 func (s *mockStorage) NewKeyBuilder(entity appdef.QName, existingBuilder istructs.IStateKeyBuilder) istructs.IStateKeyBuilder { 279 return s.Called(entity, existingBuilder).Get(0).(istructs.IStateKeyBuilder) 280 } 281 func (s *mockStorage) GetBatch(items []GetBatchItem) (err error) { 282 return s.Called(items).Error(0) 283 } 284 func (s *mockStorage) Get(key istructs.IStateKeyBuilder) (value istructs.IStateValue, err error) { 285 return s.Called(key).Get(0).(istructs.IStateValue), s.Called(key).Error(1) 286 } 287 func (s *mockStorage) Read(key istructs.IStateKeyBuilder, callback istructs.ValueCallback) (err error) { 288 return s.Called(key, callback).Error(0) 289 } 290 func (s *mockStorage) ProvideValueBuilder(key istructs.IStateKeyBuilder, existingBuilder istructs.IStateValueBuilder) (istructs.IStateValueBuilder, error) { 291 return s.Called(key, existingBuilder).Get(0).(istructs.IStateValueBuilder), nil 292 } 293 func (s *mockStorage) ProvideValueBuilderForUpdate(key istructs.IStateKeyBuilder, existingValue istructs.IStateValue, existingBuilder istructs.IStateValueBuilder) (istructs.IStateValueBuilder, error) { 294 return s.Called(key, existingValue, existingBuilder).Get(0).(istructs.IStateValueBuilder), nil 295 } 296 func (s *mockStorage) Validate(items []ApplyBatchItem) (err error) { 297 return s.Called(items).Error(0) 298 } 299 func (s *mockStorage) ApplyBatch(items []ApplyBatchItem) (err error) { 300 return s.Called(items).Error(0) 301 } 302 303 type mockKeyBuilder struct { 304 istructs.IKeyBuilder 305 mock.Mock 306 } 307 308 func (b *mockKeyBuilder) PutInt64(name string, value int64) { b.Called(name, value) } 309 func (b *mockKeyBuilder) PutString(name, value string) { b.Called(name, value) } 310 func (b *mockKeyBuilder) PutRecordID(name string, value istructs.RecordID) { b.Called(name, value) } 311 func (b *mockKeyBuilder) PutQName(name string, value appdef.QName) { b.Called(name, value) } 312 func (b *mockKeyBuilder) Equals(src istructs.IKeyBuilder) bool { return b.Called(src).Bool(0) } 313 314 type nilKeyBuilder struct { 315 istructs.IKeyBuilder 316 } 317 318 func (b *nilKeyBuilder) Equals(istructs.IKeyBuilder) bool { return false } 319 320 type mockValueBuilder struct { 321 istructs.IValueBuilder 322 mock.Mock 323 } 324 325 func (b *mockValueBuilder) PutInt32(name string, value int32) { b.Called(name, value) } 326 func (b *mockValueBuilder) PutInt64(name string, value int64) { b.Called(name, value) } 327 func (b *mockValueBuilder) PutFloat32(name string, value float32) { b.Called(name, value) } 328 func (b *mockValueBuilder) PutFloat64(name string, value float64) { b.Called(name, value) } 329 func (b *mockValueBuilder) PutBytes(name string, value []byte) { b.Called(name, value) } 330 func (b *mockValueBuilder) PutString(name string, value string) { b.Called(name, value) } 331 func (b *mockValueBuilder) PutQName(name string, value appdef.QName) { b.Called(name, value) } 332 func (b *mockValueBuilder) PutBool(name string, value bool) { b.Called(name, value) } 333 func (b *mockValueBuilder) PutRecordID(name string, value istructs.RecordID) { b.Called(name, value) } 334 func (b *mockValueBuilder) Build() istructs.IValue { return b.Called().Get(0).(istructs.IValue) } 335 336 type nilValueBuilder struct { 337 istructs.IValueBuilder 338 } 339 340 type mockRowReader struct { 341 istructs.IRowReader 342 mock.Mock 343 } 344 345 func (r *mockRowReader) AsInt32(name string) int32 { return r.Called(name).Get(0).(int32) } 346 func (r *mockRowReader) AsInt64(name string) int64 { return r.Called(name).Get(0).(int64) } 347 func (r *mockRowReader) AsFloat32(name string) float32 { return r.Called(name).Get(0).(float32) } 348 func (r *mockRowReader) AsFloat64(name string) float64 { return r.Called(name).Get(0).(float64) } 349 func (r *mockRowReader) AsBytes(name string) []byte { return r.Called(name).Get(0).([]byte) } 350 func (r *mockRowReader) AsString(name string) string { return r.Called(name).String(0) } 351 func (r *mockRowReader) AsQName(name string) appdef.QName { 352 return r.Called(name).Get(0).(appdef.QName) 353 } 354 func (r *mockRowReader) AsBool(name string) bool { return r.Called(name).Bool(0) } 355 func (r *mockRowReader) AsRecordID(name string) istructs.RecordID { 356 return r.Called(name).Get(0).(istructs.RecordID) 357 } 358 359 type mockRowWriter struct { 360 istructs.IRowWriter 361 mock.Mock 362 } 363 364 func (w *mockRowWriter) PutInt32(name string, value int32) { w.Called(name, value) } 365 func (w *mockRowWriter) PutInt64(name string, value int64) { w.Called(name, value) } 366 func (w *mockRowWriter) PutFloat32(name string, value float32) { w.Called(name, value) } 367 func (w *mockRowWriter) PutFloat64(name string, value float64) { w.Called(name, value) } 368 func (w *mockRowWriter) PutBytes(name string, value []byte) { w.Called(name, value) } 369 func (w *mockRowWriter) PutString(name, value string) { w.Called(name, value) } 370 func (w *mockRowWriter) PutQName(name string, value appdef.QName) { w.Called(name, value) } 371 func (w *mockRowWriter) PutBool(name string, value bool) { w.Called(name, value) } 372 func (w *mockRowWriter) PutRecordID(name string, value istructs.RecordID) { w.Called(name, value) } 373 374 func errorFromPanic(f func()) (err error) { 375 defer func() { 376 defer func() { 377 if r := recover(); r != nil { 378 err = r.(error) 379 } 380 }() 381 f() 382 }() 383 return 384 } 385 386 type mockWLogEvent struct { 387 mock.Mock 388 } 389 390 func (e *mockWLogEvent) ArgumentObject() istructs.IObject { 391 return e.Called().Get(0).(istructs.IObject) 392 } 393 func (e *mockWLogEvent) Bytes() []byte { return e.Called().Get(0).([]byte) } 394 func (e *mockWLogEvent) CUDs(cb func(rec istructs.ICUDRow)) { 395 e.Called(cb) 396 } 397 func (e *mockWLogEvent) RegisteredAt() istructs.UnixMilli { 398 return e.Called().Get(0).(istructs.UnixMilli) 399 } 400 func (e *mockWLogEvent) DeviceID() istructs.ConnectedDeviceID { 401 return e.Called().Get(0).(istructs.ConnectedDeviceID) 402 } 403 func (e *mockWLogEvent) Synced() bool { return e.Called().Bool(0) } 404 func (e *mockWLogEvent) QName() appdef.QName { return e.Called().Get(0).(appdef.QName) } 405 func (e *mockWLogEvent) SyncedAt() istructs.UnixMilli { return e.Called().Get(0).(istructs.UnixMilli) } 406 func (e *mockWLogEvent) Error() istructs.IEventError { return e.Called().Get(0).(istructs.IEventError) } 407 func (e *mockWLogEvent) Release() {} 408 409 type mockCUD struct { 410 mock.Mock 411 } 412 413 func (c *mockCUD) Create(qName appdef.QName) istructs.IRowWriter { 414 return c.Called().Get(0).(istructs.IRowWriter) 415 } 416 func (c *mockCUD) Update(record istructs.IRecord) istructs.IRowWriter { 417 return c.Called(record).Get(0).(istructs.IRowWriter) 418 } 419 420 type mockStateValue struct { 421 istructs.IStateValue 422 mock.Mock 423 } 424 425 type mockCUDRow struct { 426 istructs.ICUDRow 427 mock.Mock 428 }