github.com/voedger/voedger@v0.0.0-20240520144910-273e84102129/pkg/iextengine/wazero/impl_helpers_test.go (about)

     1  /*
     2    - Copyright (c) 2023-present unTill Software Development Group B.V.
     3      @author Michael Saigachenko
     4  */
     5  
     6  package iextenginewazero
     7  
     8  import (
     9  	"encoding/json"
    10  	"errors"
    11  	"fmt"
    12  	"net/url"
    13  	"path/filepath"
    14  
    15  	"github.com/voedger/voedger/pkg/appdef"
    16  	"github.com/voedger/voedger/pkg/istructs"
    17  	"github.com/voedger/voedger/pkg/state"
    18  	coreutils "github.com/voedger/voedger/pkg/utils"
    19  )
    20  
    21  var errTestIOError = errors.New("test i/o error")
    22  
    23  var storageTest = appdef.NewQName("sys", "Test")
    24  var storageTest2 = appdef.NewQName("sys", "Test2")
    25  var storageTest3 = appdef.NewQName("sys", "Test3")
    26  var storageTestQname = appdef.NewQName("sys", "TestQName")
    27  var storageIoError = appdef.NewQName("sys", "IoErrorStorage")
    28  var projectorMode bool
    29  
    30  const testPackageLocalPath = "testpkg1"
    31  const testPackageFullPath = "github.com/voedger/testpkg1"
    32  
    33  type mockIo struct {
    34  	istructs.IState
    35  	istructs.IIntents
    36  	istructs.IPkgNameResolver
    37  	intents []intent
    38  }
    39  
    40  func (s *mockIo) PackageFullPath(localName string) string {
    41  	if localName == testPackageLocalPath {
    42  		return testPackageFullPath
    43  	}
    44  	return localName
    45  
    46  }
    47  func (s *mockIo) PackageLocalName(fullPath string) string {
    48  	if fullPath == testPackageFullPath {
    49  		return testPackageLocalPath
    50  	}
    51  	return fullPath
    52  }
    53  
    54  func testModuleURL(path string) (u *url.URL) {
    55  
    56  	path, err := filepath.Abs(path)
    57  	if err != nil {
    58  		panic(err)
    59  	}
    60  
    61  	u, err = url.Parse("file:///" + filepath.ToSlash(path))
    62  	if err != nil {
    63  		panic(err)
    64  	}
    65  
    66  	return
    67  
    68  }
    69  
    70  func (s *mockIo) KeyBuilder(storage, entity appdef.QName) (builder istructs.IStateKeyBuilder, err error) {
    71  	return &mockKeyBuilder{
    72  		entity:  entity,
    73  		storage: storage,
    74  		data:    map[string]interface{}{},
    75  	}, nil
    76  }
    77  
    78  func mockedValue(name string, value interface{}) istructs.IStateValue {
    79  	mv := mockValue{
    80  		TestObject: coreutils.TestObject{Data: map[string]interface{}{}},
    81  	}
    82  	mv.Data[name] = value
    83  	return &mv
    84  }
    85  
    86  func (s *mockIo) CanExist(key istructs.IStateKeyBuilder) (value istructs.IStateValue, ok bool, err error) {
    87  	k := key.(*mockKeyBuilder)
    88  	mv := mockValue{
    89  		TestObject: coreutils.TestObject{Data: map[string]interface{}{}},
    90  	}
    91  	if k.storage == storageIoError {
    92  		return nil, false, errTestIOError
    93  	}
    94  	if k.storage == state.Event {
    95  		if projectorMode {
    96  			mv.Data["offs"] = int32(12345)
    97  			mv.Data["qname"] = "air.UpdateSubscription"
    98  			mv.Data["arg"] = newJsonValue(`
    99  				{
   100  					"subscription": {
   101  						"status": "active"
   102  					},
   103  					"customer": {
   104  						"email": "customer@test.com"
   105  					}
   106  				}
   107  			`)
   108  			return &mv, true, nil
   109  
   110  		}
   111  		mv.Data["qname"] = "sys.InvitationAccepted"
   112  		mv.Data["arg"] = mockedValue("UserEmail", "email@user.com")
   113  		mv.Data["offs"] = int32(12345)
   114  		return &mv, true, nil
   115  	}
   116  	if k.storage == storageTest {
   117  		mv.Data["500c"] = "01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
   118  		mv.Data["bytes"] = make([]byte, WasmPreallocatedBufferSize*2)
   119  		return &mv, true, nil
   120  	}
   121  	if k.storage == storageTest3 {
   122  		mv.index = make([]interface{}, 4)
   123  		mv.index[0] = int32(123)
   124  		mv.index[1] = "test string"
   125  		mv.index[2] = make([]byte, 1024)
   126  		mv.index[3] = appdef.NewQName(testPackageLocalPath, "test")
   127  		return &mv, true, nil
   128  	}
   129  	if k.storage == storageTest2 {
   130  		const vvv = "012345678901234567890"
   131  		mv.Data["а10"] = vvv
   132  		mv.Data["а11"] = vvv
   133  		mv.Data["а12"] = vvv
   134  		mv.Data["а13"] = vvv
   135  		mv.Data["а14"] = vvv
   136  		mv.Data["а15"] = vvv
   137  		mv.Data["а16"] = vvv
   138  		mv.Data["а17"] = vvv
   139  		mv.Data["а18"] = vvv
   140  		mv.Data["а19"] = vvv
   141  		mv.Data["а20"] = vvv
   142  		mv.Data["а21"] = vvv
   143  		mv.Data["а22"] = vvv
   144  		mv.Data["а23"] = vvv
   145  		mv.Data["а24"] = vvv
   146  		mv.Data["а25"] = vvv
   147  		mv.Data["а26"] = vvv
   148  		mv.Data["а27"] = vvv
   149  		mv.Data["а28"] = vvv
   150  		mv.Data["а29"] = vvv
   151  		mv.Data["а30"] = vvv
   152  		mv.Data["а31"] = vvv
   153  		mv.Data["а32"] = vvv
   154  		mv.Data["а33"] = vvv
   155  		mv.Data["а34"] = vvv
   156  		mv.Data["а35"] = vvv
   157  		mv.Data["а36"] = vvv
   158  		mv.Data["а37"] = vvv
   159  		mv.Data["а38"] = vvv
   160  		mv.Data["а39"] = vvv
   161  		return &mv, true, nil
   162  	}
   163  	if k.storage == storageTestQname {
   164  		qn := k.data["qname"].(appdef.QName)
   165  		if qn.Pkg() != testPackageLocalPath {
   166  			return nil, false, errors.New("unexpected package: " + qn.Pkg())
   167  		}
   168  		return &mv, true, nil
   169  	}
   170  	if k.storage == state.SendMail {
   171  		return &mv, true, nil
   172  	}
   173  	if k.storage == state.Record {
   174  		return &mv, false, nil
   175  	}
   176  	return nil, false, errors.New("unsupported storage: " + k.storage.Pkg() + "." + k.storage.Entity())
   177  }
   178  
   179  func (s *mockIo) CanExistAll(keys []istructs.IStateKeyBuilder, callback istructs.StateValueCallback) (err error) {
   180  	return nil
   181  }
   182  
   183  func (s *mockIo) MustExist(key istructs.IStateKeyBuilder) (value istructs.IStateValue, err error) {
   184  	k := key.(*mockKeyBuilder)
   185  	if k.storage == storageIoError {
   186  		return nil, errTestIOError
   187  	}
   188  	if k.storage == state.Record {
   189  		return nil, state.ErrNotExists
   190  	}
   191  	v, ok, err := s.CanExist(key)
   192  	if err != nil {
   193  		return v, err
   194  	}
   195  	if !ok {
   196  		panic("not exists")
   197  	}
   198  
   199  	return v, nil
   200  }
   201  
   202  func (s *mockIo) MustExistAll(keys []istructs.IStateKeyBuilder, callback istructs.StateValueCallback) (err error) {
   203  	return nil
   204  }
   205  
   206  func (s *mockIo) MustNotExist(key istructs.IStateKeyBuilder) (err error) {
   207  	return nil
   208  }
   209  
   210  func (s *mockIo) MustNotExistAll(keys []istructs.IStateKeyBuilder) (err error) {
   211  	return nil
   212  }
   213  
   214  func (s *mockIo) Read(key istructs.IStateKeyBuilder, callback istructs.ValueCallback) (err error) {
   215  	k := key.(*mockKeyBuilder)
   216  	if k.storage == storageIoError {
   217  		return errTestIOError
   218  	}
   219  	if k.storage == storageTest {
   220  		for i := 1; i <= 3; i++ {
   221  			mk := coreutils.TestObject{Data: map[string]interface{}{}}
   222  			mk.Data["i32"] = int32(i)
   223  			mk.Data["i64"] = 10 + int64(i)
   224  			mk.Data["f32"] = float32(i) + 0.1
   225  			mk.Data["f64"] = float64(i) + 0.01
   226  			mk.Data["str"] = fmt.Sprintf("key%d", i)
   227  			mk.Data["bytes"] = []byte{byte(i), 2, 3}
   228  			mk.Data["qname"] = appdef.NewQName(testPackageLocalPath, fmt.Sprintf("e%d", i))
   229  			mk.Data["bool"] = true
   230  
   231  			mv := mockValue{
   232  				TestObject: coreutils.TestObject{Data: map[string]interface{}{}},
   233  			}
   234  			mv.Data["i32"] = 100 + int32(i)
   235  			mv.Data["i64"] = 1000 + int64(i)
   236  			mv.Data["f32"] = float32(i) + 0.001
   237  			mv.Data["f64"] = float64(i) + 0.0001
   238  			mv.Data["str"] = fmt.Sprintf("value%d", i)
   239  			mv.Data["bytes"] = []byte{3, 2, 1}
   240  			mv.Data["qname"] = appdef.NewQName(testPackageLocalPath, fmt.Sprintf("ee%d", i))
   241  			mv.Data["bool"] = false
   242  			if err := callback(&mk, &mv); err != nil {
   243  				return err
   244  			}
   245  		}
   246  
   247  	}
   248  	return nil
   249  }
   250  
   251  type mockKeyBuilder struct {
   252  	entity  appdef.QName
   253  	storage appdef.QName
   254  	data    map[string]interface{}
   255  }
   256  
   257  func (kb *mockKeyBuilder) Storage() appdef.QName                            { return kb.storage }
   258  func (kb *mockKeyBuilder) Entity() appdef.QName                             { return kb.entity }
   259  func (kb *mockKeyBuilder) PartitionKey() istructs.IRowWriter                { return nil }
   260  func (kb *mockKeyBuilder) ClusteringColumns() istructs.IRowWriter           { return nil }
   261  func (kb *mockKeyBuilder) Equals(src istructs.IKeyBuilder) bool             { return false }
   262  func (kb *mockKeyBuilder) PutInt32(name string, value int32)                {}
   263  func (kb *mockKeyBuilder) PutInt64(name string, value int64)                {}
   264  func (kb *mockKeyBuilder) PutFloat32(name string, value float32)            {}
   265  func (kb *mockKeyBuilder) PutFloat64(name string, value float64)            {}
   266  func (kb *mockKeyBuilder) PutBytes(name string, value []byte)               {}
   267  func (kb *mockKeyBuilder) PutString(name, value string)                     {}
   268  func (kb *mockKeyBuilder) PutQName(name string, value appdef.QName)         { kb.data[name] = value }
   269  func (kb *mockKeyBuilder) PutBool(name string, value bool)                  {}
   270  func (kb *mockKeyBuilder) PutRecordID(name string, value istructs.RecordID) {}
   271  func (kb *mockKeyBuilder) ToBytes(istructs.WSID) ([]byte, []byte, error)    { return nil, nil, nil }
   272  
   273  // Tries to make conversion from value to a name type
   274  func (kb *mockKeyBuilder) PutNumber(name string, value float64) {}
   275  
   276  // Tries to make conversion from value to a name type
   277  func (kb *mockKeyBuilder) PutChars(name string, value string) {}
   278  
   279  func (kb *mockKeyBuilder) PutFromJSON(map[string]any) {}
   280  
   281  func newJsonValue(jsonString string) istructs.IStateValue {
   282  	v := mockValue{TestObject: coreutils.TestObject{Data: map[string]interface{}{}}}
   283  	err := json.Unmarshal([]byte(jsonString), &v.Data)
   284  	if err != nil {
   285  		panic(err)
   286  	}
   287  	return &v
   288  }
   289  
   290  type mockValue struct {
   291  	coreutils.TestObject
   292  	index []interface{}
   293  }
   294  
   295  func (v *mockValue) ToJSON(opts ...interface{}) (string, error)     { return "", nil }
   296  func (v *mockValue) AsRecord(name string) (record istructs.IRecord) { return nil }
   297  func (v *mockValue) AsEvent(name string) (event istructs.IDbEvent)  { return nil }
   298  
   299  func (v *mockValue) GetAsInt32(index int) int32        { return v.index[index].(int32) }
   300  func (v *mockValue) GetAsInt64(index int) int64        { return 0 }
   301  func (v *mockValue) GetAsFloat32(index int) float32    { return 0 }
   302  func (v *mockValue) GetAsFloat64(index int) float64    { return 0 }
   303  func (v *mockValue) GetAsBytes(index int) []byte       { return v.index[index].([]byte) }
   304  func (v *mockValue) GetAsString(index int) string      { return v.index[index].(string) }
   305  func (v *mockValue) GetAsQName(index int) appdef.QName { return v.index[index].(appdef.QName) }
   306  func (v *mockValue) GetAsBool(index int) bool          { return false }
   307  
   308  func (v *mockValue) Length() int                              { return 0 }
   309  func (v *mockValue) AsRecordID(name string) istructs.RecordID { return 0 }
   310  func (v *mockValue) GetAsValue(index int) istructs.IStateValue {
   311  	iv, ok := v.index[index].(istructs.IStateValue)
   312  	if ok {
   313  		return iv
   314  	}
   315  	mv, ok := v.index[index].([]interface{})
   316  	if ok {
   317  		return &mockValue{
   318  			index: mv,
   319  		}
   320  	}
   321  	panic(fmt.Sprintf("unsupported value stored under index: %d", index))
   322  }
   323  func (v *mockValue) AsValue(name string) istructs.IStateValue {
   324  	iv, ok := v.Data[name].(istructs.IStateValue)
   325  	if ok {
   326  		return iv
   327  	}
   328  	mv, ok := v.Data[name].(map[string]interface{})
   329  	if ok {
   330  		return &mockValue{
   331  			TestObject: coreutils.TestObject{Data: mv},
   332  		}
   333  	}
   334  	panic("unsupported value stored under key: " + name)
   335  }
   336  func (v *mockValue) RecordIDs(includeNulls bool, cb func(name string, value istructs.RecordID)) {}
   337  func (v *mockValue) FieldNames(cb func(fieldName string)) {
   338  	v.TestObject.FieldNames(cb)
   339  }
   340  
   341  type intent struct {
   342  	key   istructs.IStateKeyBuilder
   343  	value istructs.IStateValueBuilder
   344  }
   345  
   346  func (s *mockIo) NewValue(key istructs.IStateKeyBuilder) (builder istructs.IStateValueBuilder, err error) {
   347  	k := key.(*mockKeyBuilder)
   348  	if k.storage == storageIoError {
   349  		return nil, errTestIOError
   350  	}
   351  	vb := mockValueBuilder{
   352  		items: make(map[string]interface{}),
   353  	}
   354  	s.intents = append(s.intents, intent{
   355  		key:   key,
   356  		value: &vb,
   357  	})
   358  	return &vb, nil
   359  }
   360  
   361  func (s *mockIo) UpdateValue(key istructs.IStateKeyBuilder, existingValue istructs.IStateValue) (builder istructs.IStateValueBuilder, err error) {
   362  	k := key.(*mockKeyBuilder)
   363  	if k.storage == storageIoError {
   364  		return nil, errTestIOError
   365  	}
   366  	vb := mockValueBuilder{
   367  		items: make(map[string]interface{}),
   368  	}
   369  	mv := existingValue.(*mockValue)
   370  	for k, v := range mv.Data {
   371  		vb.items[k] = v
   372  	}
   373  	s.intents = append(s.intents, intent{
   374  		key:   key,
   375  		value: &vb,
   376  	})
   377  	return &vb, nil
   378  }
   379  
   380  type mockValueBuilder struct {
   381  	items map[string]interface{}
   382  }
   383  
   384  func (vb *mockValueBuilder) Equal(src istructs.IStateValueBuilder) bool       { return false }
   385  func (vb *mockValueBuilder) BuildValue() istructs.IStateValue                 { return nil }
   386  func (vb *mockValueBuilder) PutRecord(name string, record istructs.IRecord)   {}
   387  func (vb *mockValueBuilder) PutEvent(name string, event istructs.IDbEvent)    {}
   388  func (vb *mockValueBuilder) Build() istructs.IValue                           { return nil }
   389  func (vb *mockValueBuilder) PutInt32(name string, value int32)                { vb.items[name] = value }
   390  func (vb *mockValueBuilder) PutInt64(name string, value int64)                {}
   391  func (vb *mockValueBuilder) PutFloat32(name string, value float32)            {}
   392  func (vb *mockValueBuilder) PutFloat64(name string, value float64)            {}
   393  func (vb *mockValueBuilder) PutBytes(name string, value []byte)               { vb.items[name] = value }
   394  func (vb *mockValueBuilder) PutString(name, value string)                     { vb.items[name] = value }
   395  func (vb *mockValueBuilder) PutQName(name string, value appdef.QName)         { vb.items[name] = value }
   396  func (vb *mockValueBuilder) PutBool(name string, value bool)                  {}
   397  func (vb *mockValueBuilder) PutRecordID(name string, value istructs.RecordID) {}
   398  func (vb *mockValueBuilder) PutFromJSON(map[string]any)                       {}
   399  func (vb *mockValueBuilder) ToBytes() ([]byte, error)                         { return nil, nil }
   400  func (vb *mockValueBuilder) PutNumber(name string, value float64)             {}
   401  func (vb *mockValueBuilder) PutChars(name string, value string)               {}