github.com/voedger/voedger@v0.0.0-20240520144910-273e84102129/pkg/istructsmem/internal/teststore/store.go (about)

     1  /*
     2   * Copyright (c) 2021-present Sigma-Soft, Ltd.
     3   * @author: Nikolay Nikitin
     4   */
     5  
     6  package teststore
     7  
     8  import (
     9  	"bytes"
    10  	"context"
    11  
    12  	"github.com/voedger/voedger/pkg/istorage"
    13  	"github.com/voedger/voedger/pkg/istorage/mem"
    14  	"github.com/voedger/voedger/pkg/istorage/provider"
    15  	"github.com/voedger/voedger/pkg/istructs"
    16  )
    17  
    18  // Test storage. Trained to return the specified error
    19  type (
    20  	scheduleStorageError struct {
    21  		err         error
    22  		pKey, cCols []byte
    23  	}
    24  
    25  	damagedStorageFunc    func(*[]byte)
    26  	scheduleStorageDamage struct {
    27  		dam damagedStorageFunc
    28  		scheduleStorageError
    29  	}
    30  
    31  	TestMemStorage struct {
    32  		storage  istorage.IAppStorage
    33  		get, put scheduleStorageError
    34  		damage   scheduleStorageDamage
    35  	}
    36  
    37  	testStorageProvider struct {
    38  		testStorage *TestMemStorage
    39  	}
    40  )
    41  
    42  func (tsp *testStorageProvider) AppStorage(appName istructs.AppQName) (structs istorage.IAppStorage, err error) {
    43  	return tsp.testStorage, nil
    44  }
    45  
    46  // Returns new storage provider for specified test storage
    47  func NewStorageProvider(ts *TestMemStorage) istorage.IAppStorageProvider {
    48  	return &testStorageProvider{testStorage: ts}
    49  }
    50  
    51  // Returns new test storage
    52  func NewStorage() *TestMemStorage {
    53  	s := TestMemStorage{get: scheduleStorageError{}, put: scheduleStorageError{}}
    54  	asf := mem.Provide()
    55  	sp := provider.Provide(asf)
    56  	var err error
    57  	if s.storage, err = sp.AppStorage(istructs.AppQName_test1_app1); err != nil {
    58  		panic(err)
    59  	}
    60  
    61  	return &s
    62  }
    63  
    64  // Returns new test storage and new test storage provider
    65  func New() (storage *TestMemStorage, provider istorage.IAppStorageProvider) {
    66  	s := NewStorage()
    67  	return s, NewStorageProvider(s)
    68  }
    69  
    70  // Returns is partition key and clustering columns matches the scheduled error
    71  func (e *scheduleStorageError) match(pKey, cCols []byte) bool {
    72  	return ((len(e.pKey) == 0) || bytes.Equal(e.pKey, pKey)) &&
    73  		((len(e.cCols) == 0) || bytes.Equal(e.cCols, cCols))
    74  }
    75  
    76  // Clear all scheduled errors
    77  func (s *TestMemStorage) Reset() {
    78  	s.get = scheduleStorageError{}
    79  	s.put = scheduleStorageError{}
    80  	s.damage = scheduleStorageDamage{}
    81  }
    82  
    83  // Schedule Get() to return error
    84  func (s *TestMemStorage) ScheduleGetError(err error, pKey, cCols []byte) {
    85  	s.get.err = err
    86  	s.get.pKey = make([]byte, len(pKey))
    87  	copy(s.get.pKey, pKey)
    88  	s.get.cCols = make([]byte, len(cCols))
    89  	copy(s.get.cCols, cCols)
    90  }
    91  
    92  // Schedule Get() to return damaged data
    93  func (s *TestMemStorage) ScheduleGetDamage(dam damagedStorageFunc, pKey, cCols []byte) {
    94  	s.damage.dam = dam
    95  	s.damage.pKey = make([]byte, len(pKey))
    96  	copy(s.damage.pKey, pKey)
    97  	s.damage.cCols = make([]byte, len(cCols))
    98  	copy(s.damage.cCols, cCols)
    99  }
   100  
   101  // Schedule Put() to return error
   102  func (s *TestMemStorage) SchedulePutError(err error, pKey, cCols []byte) {
   103  	s.put.err = err
   104  	s.put.pKey = make([]byte, len(pKey))
   105  	copy(s.put.pKey, pKey)
   106  	s.put.cCols = make([]byte, len(cCols))
   107  	copy(s.put.cCols, cCols)
   108  }
   109  
   110  func (s *TestMemStorage) Get(pKey []byte, cCols []byte, data *[]byte) (ok bool, err error) {
   111  	if s.get.err != nil {
   112  		if s.get.match(pKey, cCols) {
   113  			err = s.get.err
   114  			s.get.err = nil
   115  			return false, err
   116  		}
   117  	}
   118  
   119  	ok, err = s.storage.Get(pKey, cCols, data)
   120  
   121  	if ok && (s.damage.dam != nil) {
   122  		if s.damage.match(pKey, cCols) {
   123  			s.damage.dam(data)
   124  			s.damage.dam = nil
   125  			return ok, err
   126  		}
   127  	}
   128  
   129  	return ok, err
   130  }
   131  
   132  func (s *TestMemStorage) GetBatch(pKey []byte, items []istorage.GetBatchItem) (err error) {
   133  	if s.get.err != nil {
   134  		for _, item := range items {
   135  			if s.get.match(pKey, item.CCols) {
   136  				err = s.get.err
   137  				s.get.err = nil
   138  				return err
   139  			}
   140  		}
   141  	}
   142  
   143  	err = s.storage.GetBatch(pKey, items)
   144  
   145  	if s.damage.dam != nil {
   146  		for i := 0; i < len(items); i++ {
   147  			if s.damage.match(pKey, items[i].CCols) {
   148  				if items[i].Ok {
   149  					s.damage.dam(items[i].Data)
   150  					s.damage.dam = nil
   151  				}
   152  			}
   153  		}
   154  	}
   155  
   156  	return err
   157  }
   158  
   159  func (s *TestMemStorage) Put(pKey []byte, cCols []byte, value []byte) (err error) {
   160  	if s.put.err != nil {
   161  		if s.put.match(pKey, cCols) {
   162  			err = s.put.err
   163  			s.put.err = nil
   164  			return err
   165  		}
   166  	}
   167  	return s.storage.Put(pKey, cCols, value)
   168  }
   169  
   170  func (s *TestMemStorage) PutBatch(items []istorage.BatchItem) (err error) {
   171  	for _, p := range items {
   172  		if err = s.Put(p.PKey, p.CCols, p.Value); err != nil {
   173  			return err
   174  		}
   175  	}
   176  	return nil
   177  }
   178  
   179  func (s *TestMemStorage) Read(ctx context.Context, pKey []byte, startCCols, finishCCols []byte, cb istorage.ReadCallback) (err error) {
   180  	cbWrap := func(cCols []byte, data []byte) (err error) {
   181  		if s.get.err != nil {
   182  			if s.get.match(pKey, cCols) {
   183  				err = s.get.err
   184  				s.get.err = nil
   185  				return err
   186  			}
   187  		}
   188  
   189  		if s.damage.dam != nil {
   190  			if s.damage.match(pKey, cCols) {
   191  				s.damage.dam(&data)
   192  				s.damage.dam = nil
   193  			}
   194  		}
   195  
   196  		return cb(cCols, data)
   197  	}
   198  
   199  	return s.storage.Read(ctx, pKey, startCCols, finishCCols, cbWrap)
   200  }