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  }