github.com/voedger/voedger@v0.0.0-20240520144910-273e84102129/pkg/state/impl_bundled_host_state_test.go (about) 1 /* 2 * Copyright (c) 2022-present unTill Pro, Ltd. 3 */ 4 5 package state 6 7 import ( 8 "context" 9 "testing" 10 11 "github.com/stretchr/testify/mock" 12 "github.com/stretchr/testify/require" 13 "github.com/voedger/voedger/pkg/appdef" 14 "github.com/voedger/voedger/pkg/istructs" 15 ) 16 17 func TestBundledHostState_BasicUsage(t *testing.T) { 18 require := require.New(t) 19 factory := ProvideAsyncActualizerStateFactory() 20 n10nFn := func(view appdef.QName, wsid istructs.WSID, offset istructs.Offset) {} 21 22 // Create instance of async actualizer state 23 aaState := factory(context.Background(), mockedAppStructs, nil, SimpleWSIDFunc(istructs.WSID(1)), n10nFn, nil, nil, nil, nil, 2, 1) 24 25 // Declare simple extension 26 extension := func(state istructs.IState, intents istructs.IIntents) { 27 //Create key 28 kb, err := state.KeyBuilder(View, testViewRecordQName1) 29 require.NoError(err) 30 kb.PutInt64("pkFld", int64(64)) 31 32 // Create new value 33 eb, err := intents.NewValue(kb) 34 require.NoError(err) 35 eb.PutInt64("vFld", 10) 36 eb.PutInt64(ColOffset, 45) 37 } 38 39 // Run extension 40 extension(aaState, aaState) 41 42 // Apply intents 43 readyToFlush, err := aaState.ApplyIntents() 44 require.NoError(err) 45 require.True(readyToFlush) 46 47 _ = aaState.FlushBundles() 48 } 49 50 func mockedAppStructs() istructs.IAppStructs { 51 mv := &mockValue{} 52 mv. 53 On("AsInt64", "vFld").Return(int64(10)). 54 On("AsInt64", ColOffset).Return(int64(45)) 55 mvb1 := &mockValueBuilder{} 56 mvb1. 57 On("PutInt64", "vFld", int64(10)). 58 On("PutInt64", ColOffset, int64(45)). 59 On("Build").Return(mv) 60 mvb2 := &mockValueBuilder{} 61 mvb2. 62 On("PutInt64", "vFld", int64(10)).Once(). 63 On("PutInt64", ColOffset, int64(45)).Once(). 64 On("PutInt64", "vFld", int64(17)).Once(). 65 On("PutInt64", ColOffset, int64(46)).Once() 66 mkb := &mockKeyBuilder{} 67 mkb. 68 On("PutInt64", "pkFld", int64(64)) 69 70 viewRecords := &mockViewRecords{} 71 viewRecords. 72 On("KeyBuilder", testViewRecordQName1).Return(mkb). 73 On("NewValueBuilder", testViewRecordQName1).Return(mvb1).Once(). 74 On("NewValueBuilder", testViewRecordQName1).Return(mvb2).Once(). 75 On("PutBatch", istructs.WSID(1), mock.AnythingOfType("[]istructs.ViewKV")).Return(nil) 76 77 mockWorkspaceRecord := &mockRecord{} 78 mockWorkspaceRecord.On("AsQName", "WSKind").Return(testWSDescriptorQName) 79 mockWorkspaceRecord.On("QName").Return(qNameCDocWorkspaceDescriptor) 80 mockedRecords := &mockRecords{} 81 mockedRecords.On("GetSingleton", istructs.WSID(1), mock.Anything).Return(mockWorkspaceRecord, nil) 82 83 appDefBuilder := appdef.New() 84 wsDesc := appDefBuilder.AddCDoc(testWSDescriptorQName) 85 wsDesc.AddField(field_WSKind, appdef.DataKind_bytes, false) 86 view := appDefBuilder.AddView(testViewRecordQName1) 87 view.Key().PartKey().AddField("pkFld", appdef.DataKind_int64) 88 view.Key().ClustCols().AddField("ccFld", appdef.DataKind_string) 89 view.Value(). 90 AddField("vFld", appdef.DataKind_int64, true). 91 AddField(ColOffset, appdef.DataKind_int64, true) 92 ws := appDefBuilder.AddWorkspace(testWSQName) 93 ws.AddType(testViewRecordQName1) 94 ws.SetDescriptor(testWSDescriptorQName) 95 appDef, err := appDefBuilder.Build() 96 if err != nil { 97 panic(err) 98 } 99 100 appStructs := &mockAppStructs{} 101 appStructs. 102 On("AppDef").Return(appDef). 103 On("AppQName").Return(testAppQName). 104 On("ViewRecords").Return(viewRecords). 105 On("Events").Return(&nilEvents{}). 106 On("Records").Return(mockedRecords) 107 return appStructs 108 } 109 110 func TestAsyncActualizerState_CanExist(t *testing.T) { 111 t.Run("Should be ok", func(t *testing.T) { 112 require := require.New(t) 113 stateStorage := &mockStorage{} 114 stateStorage. 115 On("NewKeyBuilder", testViewRecordQName1, nil).Return(newKeyBuilder(testStorage, testViewRecordQName1)). 116 On("GetBatch", mock.AnythingOfType("[]state.GetBatchItem")). 117 Return(nil). 118 Run(func(args mock.Arguments) { 119 args.Get(0).([]GetBatchItem)[0].value = &mockStateValue{} 120 }) 121 s := asyncActualizerStateWithTestStateStorage(stateStorage) 122 kb, err := s.KeyBuilder(testStorage, testViewRecordQName1) 123 require.NoError(err) 124 125 _, ok, err := s.CanExist(kb) 126 require.NoError(err) 127 128 require.True(ok) 129 }) 130 t.Run("Should return error when error occurred on get batch", func(t *testing.T) { 131 require := require.New(t) 132 stateStorage := &mockStorage{} 133 stateStorage. 134 On("NewKeyBuilder", testViewRecordQName1, nil).Return(newKeyBuilder(testStorage, testViewRecordQName1)). 135 On("GetBatch", mock.AnythingOfType("[]state.GetBatchItem")).Return(errTest) 136 s := asyncActualizerStateWithTestStateStorage(stateStorage) 137 kb, err := s.KeyBuilder(testStorage, testViewRecordQName1) 138 require.NoError(err) 139 140 _, _, err = s.CanExist(kb) 141 142 require.ErrorIs(err, errTest) 143 }) 144 } 145 func TestAsyncActualizerState_CanExistAll(t *testing.T) { 146 t.Run("Should be ok", func(t *testing.T) { 147 require := require.New(t) 148 times := 0 149 stateStorage := &mockStorage{} 150 stateStorage. 151 On("NewKeyBuilder", testViewRecordQName1, nil).Return(newKeyBuilder(testStorage, testViewRecordQName1)). 152 On("GetBatch", mock.AnythingOfType("[]state.GetBatchItem")).Return(nil) 153 s := asyncActualizerStateWithTestStateStorage(stateStorage) 154 kb1, err := s.KeyBuilder(testStorage, testViewRecordQName1) 155 require.NoError(err) 156 kb2, err := s.KeyBuilder(testStorage, testViewRecordQName1) 157 require.NoError(err) 158 159 _ = s.CanExistAll([]istructs.IStateKeyBuilder{kb1, kb2}, func(istructs.IKeyBuilder, istructs.IStateValue, bool) error { 160 times++ 161 return nil 162 }) 163 164 require.Equal(2, times) 165 }) 166 t.Run("Should return error when error occurred on can exist", func(t *testing.T) { 167 require := require.New(t) 168 stateStorage := &mockStorage{} 169 stateStorage. 170 On("NewKeyBuilder", testViewRecordQName1, nil).Return(newKeyBuilder(testStorage, testViewRecordQName1)). 171 On("GetBatch", mock.AnythingOfType("[]state.GetBatchItem")).Return(errTest) 172 s := asyncActualizerStateWithTestStateStorage(stateStorage) 173 kb1, err := s.KeyBuilder(testStorage, testViewRecordQName1) 174 require.NoError(err) 175 kb2, err := s.KeyBuilder(testStorage, testViewRecordQName1) 176 require.NoError(err) 177 178 err = s.CanExistAll([]istructs.IStateKeyBuilder{kb1, kb2}, nil) 179 180 require.ErrorIs(err, errTest) 181 }) 182 } 183 func TestAsyncActualizerState_MustExist(t *testing.T) { 184 t.Run("Should be ok", func(t *testing.T) { 185 require := require.New(t) 186 stateStorage := &mockStorage{} 187 stateStorage. 188 On("NewKeyBuilder", testViewRecordQName1, nil).Return(newKeyBuilder(testStorage, testViewRecordQName1)). 189 On("GetBatch", mock.AnythingOfType("[]state.GetBatchItem")). 190 Return(nil). 191 Run(func(args mock.Arguments) { 192 args.Get(0).([]GetBatchItem)[0].value = &mockStateValue{} 193 }) 194 s := asyncActualizerStateWithTestStateStorage(stateStorage) 195 kb, err := s.KeyBuilder(testStorage, testViewRecordQName1) 196 require.NoError(err) 197 198 _, err = s.MustExist(kb) 199 200 require.NoError(err) 201 }) 202 t.Run("Should return error when entity not exists", func(t *testing.T) { 203 require := require.New(t) 204 stateStorage := &mockStorage{} 205 stateStorage. 206 On("NewKeyBuilder", testViewRecordQName1, nil).Return(newKeyBuilder(testStorage, testViewRecordQName1)). 207 On("GetBatch", mock.AnythingOfType("[]state.GetBatchItem")). 208 Return(nil). 209 Run(func(args mock.Arguments) { 210 args.Get(0).([]GetBatchItem)[0].value = nil 211 }) 212 s := asyncActualizerStateWithTestStateStorage(stateStorage) 213 kb, err := s.KeyBuilder(testStorage, testViewRecordQName1) 214 require.NoError(err) 215 216 _, err = s.MustExist(kb) 217 218 require.ErrorIs(err, ErrNotExists) 219 }) 220 t.Run("Should return error when error occurred on can exist", func(t *testing.T) { 221 require := require.New(t) 222 stateStorage := &mockStorage{} 223 stateStorage. 224 On("NewKeyBuilder", testViewRecordQName1, nil).Return(newKeyBuilder(testStorage, testViewRecordQName1)). 225 On("GetBatch", mock.AnythingOfType("[]state.GetBatchItem")).Return(errTest) 226 s := asyncActualizerStateWithTestStateStorage(stateStorage) 227 kb, err := s.KeyBuilder(testStorage, testViewRecordQName1) 228 require.NoError(err) 229 230 _, err = s.MustExist(kb) 231 232 require.ErrorIs(err, errTest) 233 }) 234 } 235 func TestAsyncActualizerState_MustExistAll(t *testing.T) { 236 t.Run("Should be ok", func(t *testing.T) { 237 require := require.New(t) 238 stateStorage := &mockStorage{} 239 stateStorage. 240 On("NewKeyBuilder", testViewRecordQName1, nil).Return(newKeyBuilder(testStorage, testViewRecordQName1)). 241 On("GetBatch", mock.AnythingOfType("[]state.GetBatchItem")). 242 Return(nil). 243 Run(func(args mock.Arguments) { 244 args.Get(0).([]GetBatchItem)[0].value = &mockStateValue{} 245 }) 246 s := asyncActualizerStateWithTestStateStorage(stateStorage) 247 k1, err := s.KeyBuilder(testStorage, testViewRecordQName1) 248 require.NoError(err) 249 k2, err := s.KeyBuilder(testStorage, testViewRecordQName1) 250 require.NoError(err) 251 kk := make([]istructs.IKeyBuilder, 0, 2) 252 253 _ = s.MustExistAll([]istructs.IStateKeyBuilder{k1, k2}, func(key istructs.IKeyBuilder, value istructs.IStateValue, ok bool) (err error) { 254 kk = append(kk, key) 255 require.True(ok) 256 return 257 }) 258 259 require.Equal(k1, kk[0]) 260 require.Equal(k1, kk[1]) 261 }) 262 t.Run("Should return error when entity not exists", func(t *testing.T) { 263 require := require.New(t) 264 stateStorage := &mockStorage{} 265 stateStorage. 266 On("NewKeyBuilder", testViewRecordQName1, nil).Return(newKeyBuilder(testStorage, testViewRecordQName1)). 267 On("GetBatch", mock.AnythingOfType("[]state.GetBatchItem")). 268 Return(nil). 269 Run(func(args mock.Arguments) { 270 args.Get(0).([]GetBatchItem)[0].value = nil 271 }) 272 s := asyncActualizerStateWithTestStateStorage(stateStorage) 273 k1, err := s.KeyBuilder(testStorage, testViewRecordQName1) 274 require.NoError(err) 275 k2, err := s.KeyBuilder(testStorage, testViewRecordQName1) 276 require.NoError(err) 277 278 err = s.MustExistAll([]istructs.IStateKeyBuilder{k1, k2}, nil) 279 280 require.ErrorIs(err, ErrNotExists) 281 }) 282 } 283 func TestAsyncActualizerState_MustNotExist(t *testing.T) { 284 t.Run("Should be ok", func(t *testing.T) { 285 require := require.New(t) 286 stateStorage := &mockStorage{} 287 stateStorage. 288 On("NewKeyBuilder", testViewRecordQName1, nil).Return(newKeyBuilder(testStorage, testViewRecordQName1)). 289 On("GetBatch", mock.AnythingOfType("[]state.GetBatchItem")). 290 Return(nil). 291 Run(func(args mock.Arguments) { 292 args.Get(0).([]GetBatchItem)[0].value = nil 293 }) 294 s := asyncActualizerStateWithTestStateStorage(stateStorage) 295 k, err := s.KeyBuilder(testStorage, testViewRecordQName1) 296 require.NoError(err) 297 298 err = s.MustNotExist(k) 299 300 require.NoError(err) 301 }) 302 t.Run("Should return error when entity exists", func(t *testing.T) { 303 require := require.New(t) 304 stateStorage := &mockStorage{} 305 stateStorage. 306 On("NewKeyBuilder", testViewRecordQName1, nil).Return(newKeyBuilder(testStorage, testViewRecordQName1)). 307 On("GetBatch", mock.AnythingOfType("[]state.GetBatchItem")). 308 Return(nil). 309 Run(func(args mock.Arguments) { 310 args.Get(0).([]GetBatchItem)[0].value = &mockStateValue{} 311 }) 312 s := asyncActualizerStateWithTestStateStorage(stateStorage) 313 k, err := s.KeyBuilder(testStorage, testViewRecordQName1) 314 require.NoError(err) 315 316 err = s.MustNotExist(k) 317 318 require.ErrorIs(err, ErrExists) 319 }) 320 t.Run("Should return error when error occurred on must exist", func(t *testing.T) { 321 require := require.New(t) 322 stateStorage := &mockStorage{} 323 stateStorage. 324 On("NewKeyBuilder", testViewRecordQName1, nil).Return(newKeyBuilder(testStorage, testViewRecordQName1)). 325 On("GetBatch", mock.AnythingOfType("[]state.GetBatchItem")).Return(errTest) 326 s := asyncActualizerStateWithTestStateStorage(stateStorage) 327 kb, err := s.KeyBuilder(testStorage, testViewRecordQName1) 328 require.NoError(err) 329 330 err = s.MustNotExist(kb) 331 332 require.ErrorIs(err, errTest) 333 }) 334 } 335 func TestAsyncActualizerState_MustNotExistAll(t *testing.T) { 336 t.Run("Should be ok", func(t *testing.T) { 337 require := require.New(t) 338 stateStorage := &mockStorage{} 339 stateStorage. 340 On("NewKeyBuilder", testViewRecordQName1, nil).Return(newKeyBuilder(testStorage, testViewRecordQName1)). 341 On("GetBatch", mock.AnythingOfType("[]state.GetBatchItem")). 342 Return(nil). 343 Run(func(args mock.Arguments) { 344 args.Get(0).([]GetBatchItem)[0].value = nil 345 }) 346 s := asyncActualizerStateWithTestStateStorage(stateStorage) 347 k1, err := s.KeyBuilder(testStorage, testViewRecordQName1) 348 require.NoError(err) 349 k2, err := s.KeyBuilder(testStorage, testViewRecordQName1) 350 require.NoError(err) 351 352 err = s.MustNotExistAll([]istructs.IStateKeyBuilder{k1, k2}) 353 354 require.NoError(err) 355 }) 356 t.Run("Should return error when entity exists", func(t *testing.T) { 357 require := require.New(t) 358 stateStorage := &mockStorage{} 359 stateStorage. 360 On("NewKeyBuilder", testViewRecordQName1, nil).Return(newKeyBuilder(testStorage, testViewRecordQName1)). 361 On("GetBatch", mock.AnythingOfType("[]state.GetBatchItem")). 362 Return(nil). 363 Run(func(args mock.Arguments) { 364 args.Get(0).([]GetBatchItem)[0].value = &mockStateValue{} 365 }) 366 s := asyncActualizerStateWithTestStateStorage(stateStorage) 367 k1, err := s.KeyBuilder(testStorage, testViewRecordQName1) 368 require.NoError(err) 369 k2, err := s.KeyBuilder(testStorage, testViewRecordQName1) 370 require.NoError(err) 371 372 err = s.MustNotExistAll([]istructs.IStateKeyBuilder{k1, k2}) 373 374 require.ErrorIs(err, ErrExists) 375 }) 376 } 377 func TestAsyncActualizerState_Read(t *testing.T) { 378 t.Run("Should flush bundle before read", func(t *testing.T) { 379 require := require.New(t) 380 touched := false 381 mockedStructs, mockedViews := mockedStructs(t) 382 mockedViews. 383 On("KeyBuilder", testViewRecordQName1).Return(&nilKeyBuilder{}). 384 On("KeyBuilder", testViewRecordQName2).Return(&nilKeyBuilder{}). 385 On("NewValueBuilder", testViewRecordQName1).Return(&nilValueBuilder{}). 386 On("NewValueBuilder", testViewRecordQName2).Return(&nilValueBuilder{}). 387 On("PutBatch", istructs.WSID(1), mock.AnythingOfType("[]istructs.ViewKV")). 388 Return(nil). 389 Run(func(args mock.Arguments) { 390 require.Len(args.Get(1).([]istructs.ViewKV), 2) 391 }). 392 On("Read", context.Background(), istructs.WSID(1), mock.Anything, mock.AnythingOfType("istructs.ValuesCallback")). 393 Return(nil). 394 Run(func(args mock.Arguments) { 395 _ = args.Get(3).(istructs.ValuesCallback)(&nilKey{}, &nilValue{}) 396 }) 397 398 s := ProvideAsyncActualizerStateFactory()(context.Background(), func() istructs.IAppStructs { return mockedStructs }, nil, SimpleWSIDFunc(istructs.WSID(1)), nil, nil, nil, nil, nil, 10, 10) 399 kb1, err := s.KeyBuilder(View, testViewRecordQName1) 400 require.NoError(err) 401 kb2, err := s.KeyBuilder(View, testViewRecordQName2) 402 require.NoError(err) 403 404 _, _ = s.NewValue(kb1) 405 _, _ = s.NewValue(kb2) 406 407 readyToFlush, err := s.ApplyIntents() 408 require.False(readyToFlush) 409 require.NoError(err) 410 411 _ = s.Read(kb1, func(key istructs.IKey, value istructs.IStateValue) (err error) { 412 touched = true 413 return 414 }) 415 416 require.True(touched) 417 }) 418 t.Run("Should return error when error occurred on apply batch", func(t *testing.T) { 419 require := require.New(t) 420 touched := false 421 mockedStructs, mockedViews := mockedStructs(t) 422 mockedViews. 423 On("KeyBuilder", testViewRecordQName1).Return(&nilKeyBuilder{}). 424 On("KeyBuilder", testViewRecordQName2).Return(&nilKeyBuilder{}). 425 On("NewValueBuilder", testViewRecordQName1).Return(&nilValueBuilder{}). 426 On("NewValueBuilder", testViewRecordQName2).Return(&nilValueBuilder{}). 427 On("PutBatch", istructs.WSID(1), mock.AnythingOfType("[]istructs.ViewKV")).Return(errTest) 428 s := ProvideAsyncActualizerStateFactory()(context.Background(), func() istructs.IAppStructs { return mockedStructs }, nil, SimpleWSIDFunc(istructs.WSID(1)), nil, nil, nil, nil, nil, 10, 10) 429 kb1, err := s.KeyBuilder(View, testViewRecordQName1) 430 require.NoError(err) 431 kb2, err := s.KeyBuilder(View, testViewRecordQName2) 432 require.NoError(err) 433 434 _, _ = s.NewValue(kb1) 435 _, _ = s.NewValue(kb2) 436 437 readyToFlush, err := s.ApplyIntents() 438 require.False(readyToFlush) 439 require.NoError(err) 440 441 err = s.Read(kb1, func(key istructs.IKey, value istructs.IStateValue) (err error) { 442 touched = true 443 return err 444 }) 445 446 require.ErrorIs(err, errTest) 447 require.False(touched) 448 }) 449 } 450 func asyncActualizerStateWithTestStateStorage(s *mockStorage) istructs.IState { 451 as := ProvideAsyncActualizerStateFactory()(context.Background(), nilAppStructsFunc, nil, nil, nil, nil, nil, nil, nil, 10, 10) 452 as.(*asyncActualizerState).addStorage(testStorage, s, S_GET_BATCH|S_READ) 453 return as 454 }