github.com/mailru/activerecord@v1.12.2/pkg/octopus/testutil.go (about)

     1  package octopus
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"fmt"
     7  	"sync/atomic"
     8  
     9  	// Надо избавиться от использования этого модуля
    10  	"log"
    11  )
    12  
    13  // FixtureType - структура определяющая ответ Response
    14  // для конкретного запроса Request
    15  type FixtureType struct {
    16  	// Уникальный идентификатор фикстуры
    17  	ID uint32
    18  
    19  	// Msg - задаёт тип запроса (select, insert, delete, update)
    20  	Msg RequetsTypeType
    21  
    22  	// Байтовое представление запроса
    23  	Request []byte
    24  
    25  	// Байтовое представление ответа
    26  	Response []byte
    27  
    28  	// Возвращаемые объекты. Используется в режиме mock
    29  	RespObjs []MockEntities
    30  
    31  	// Trigger - функция, которая будет выполнена при обработке запроса
    32  	// в случае если надо проверить insert или delete внутри этой функции
    33  	// можно модифицировать список фикстур сервера
    34  	Trigger func([]FixtureType) []FixtureType
    35  }
    36  
    37  type MockEntities interface {
    38  	// Метод который позволяет отдать ответ из mock сервера
    39  	MockSelectResponse() ([][]byte, error)
    40  
    41  	// Метод который позволяет поднять сущность из БД
    42  	RepoSelector(ctx context.Context) (any, error)
    43  }
    44  
    45  // CreateFixture - конструктор фикстур
    46  func CreateFixture(id uint32, msg uint8, reqData []byte, respData []byte, trigger func([]FixtureType) []FixtureType) FixtureType {
    47  	return FixtureType{
    48  		ID:       id,
    49  		Msg:      RequetsTypeType(msg),
    50  		Request:  reqData,
    51  		Response: respData,
    52  		RespObjs: []MockEntities{},
    53  		Trigger:  trigger,
    54  	}
    55  }
    56  
    57  var fixtureID uint32
    58  
    59  // CreateSelectFixture - конструктор фикстур для select-а
    60  func CreateSelectFixture(reqData func(mocks []MockEntities) []byte, respEnt []MockEntities) (FixtureType, error) {
    61  	newID := atomic.AddUint32(&fixtureID, 1)
    62  
    63  	respByte, err := PackMockResponse(respEnt)
    64  	if err != nil {
    65  		return FixtureType{}, fmt.Errorf("error prepare fixture response: %s", err)
    66  	}
    67  
    68  	oft := FixtureType{
    69  		ID:       newID,
    70  		Msg:      RequestTypeSelect,
    71  		Request:  reqData(respEnt),
    72  		Response: respByte,
    73  		RespObjs: respEnt,
    74  		Trigger:  nil,
    75  	}
    76  
    77  	return oft, nil
    78  }
    79  
    80  func CreateUpdateFixture(reqData []byte, trigger func([]FixtureType) []FixtureType) FixtureType {
    81  	newID := atomic.AddUint32(&fixtureID, 1)
    82  
    83  	dummyRespBytes := [][][]byte{{{'0'}}}
    84  
    85  	respData, err := PackResopnseStatus(RcOK, dummyRespBytes)
    86  	if err != nil {
    87  		log.Fatalf("error while pack update response: %s", err)
    88  	}
    89  
    90  	oft := FixtureType{
    91  		ID:       newID,
    92  		Msg:      RequestTypeUpdate,
    93  		Request:  reqData,
    94  		Response: respData,
    95  		RespObjs: nil,
    96  		Trigger:  trigger,
    97  	}
    98  
    99  	return oft
   100  }
   101  
   102  func CreateDeleteFixture(reqData []byte, trigger func([]FixtureType) []FixtureType) FixtureType {
   103  	newID := atomic.AddUint32(&fixtureID, 1)
   104  
   105  	dummyRespBytes := [][][]byte{{{'0'}}}
   106  
   107  	respData, err := PackResopnseStatus(RcOK, dummyRespBytes)
   108  	if err != nil {
   109  		log.Fatalf("error while pack delete response: %s", err)
   110  	}
   111  
   112  	oft := FixtureType{
   113  		ID:       newID,
   114  		Msg:      RequestTypeDelete,
   115  		Request:  reqData,
   116  		Response: respData,
   117  		RespObjs: nil,
   118  		Trigger:  trigger,
   119  	}
   120  
   121  	return oft
   122  }
   123  
   124  func CreateInsertOrReplaceFixture(entity MockEntities, reqData []byte, trigger func([]FixtureType) []FixtureType) FixtureType {
   125  	newID := atomic.AddUint32(&fixtureID, 1)
   126  
   127  	// by default return same entity
   128  	respData, err := PackMockResponse([]MockEntities{entity})
   129  	if err != nil {
   130  		log.Fatalf("error while pack insert or replace response: %s", err)
   131  	}
   132  
   133  	oft := FixtureType{
   134  		ID:       newID,
   135  		Msg:      RequestTypeInsert,
   136  		Request:  reqData,
   137  		Response: respData,
   138  		RespObjs: nil,
   139  		Trigger:  trigger,
   140  	}
   141  
   142  	return oft
   143  }
   144  
   145  // CreateCallFixture - конструктор фикстур для вызова процедуры
   146  func CreateCallFixture(reqData func(mocks []MockEntities) []byte, respEnt []MockEntities) (FixtureType, error) {
   147  	newID := atomic.AddUint32(&fixtureID, 1)
   148  
   149  	respByte, err := PackMockResponse(respEnt)
   150  	if err != nil {
   151  		return FixtureType{}, fmt.Errorf("error prepare fixture response: %s", err)
   152  	}
   153  
   154  	oft := FixtureType{
   155  		ID:       newID,
   156  		Msg:      RequestTypeCall,
   157  		Request:  reqData(respEnt),
   158  		Response: respByte,
   159  		RespObjs: respEnt,
   160  		Trigger:  nil,
   161  	}
   162  
   163  	return oft, nil
   164  }
   165  
   166  func WrapTriggerWithOnUsePromise(trigger func(types []FixtureType) []FixtureType) (wrappedTrigger func(types []FixtureType) []FixtureType, isUsed func() bool) {
   167  	used := false
   168  
   169  	promise := func() bool {
   170  		return used
   171  	}
   172  
   173  	wrappedTrigger = func(types []FixtureType) []FixtureType {
   174  		used = true
   175  
   176  		if trigger != nil {
   177  			return trigger(types)
   178  		}
   179  
   180  		return types
   181  	}
   182  
   183  	return wrappedTrigger, promise
   184  }
   185  
   186  func PackMockResponse(ome []MockEntities) ([]byte, error) {
   187  	tuples := [][][]byte{}
   188  
   189  	for _, om := range ome {
   190  		tuple, err := om.MockSelectResponse()
   191  		if err != nil {
   192  			return nil, fmt.Errorf("error prepare fixtures: %s", err)
   193  		}
   194  
   195  		tuples = append(tuples, tuple)
   196  	}
   197  
   198  	return PackResopnseStatus(RcOK, tuples)
   199  }
   200  
   201  func UnpackSelect(data []byte) (ns, indexnum, offset, limit uint32, keys [][][]byte, err error) {
   202  	rdr := bytes.NewReader(data)
   203  
   204  	if ns, err = UnpackSpace(rdr); err != nil {
   205  		return
   206  	}
   207  
   208  	if indexnum, err = UnpackIndexNum(rdr); err != nil {
   209  		return
   210  	}
   211  
   212  	if offset, err = UnpackOffset(rdr); err != nil {
   213  		return
   214  	}
   215  
   216  	if limit, err = UnpackLimit(rdr); err != nil {
   217  		return
   218  	}
   219  
   220  	if keys, err = UnpackTuples(rdr); err != nil {
   221  		return
   222  	}
   223  
   224  	return
   225  }
   226  
   227  type SelectMockFixture struct {
   228  	Indexnum   uint32
   229  	Offset     uint32
   230  	Limit      uint32
   231  	Keys       [][][]byte
   232  	RespTuples []TupleData
   233  }
   234  
   235  type InsertMockFixture struct {
   236  	NeedRetVal bool
   237  	InsertMode InsertMode
   238  	Tuple      TupleData
   239  }
   240  
   241  type UpdateMockFixture struct {
   242  	PrimaryKey [][]byte
   243  	UpdateOps  []Ops
   244  }
   245  
   246  type DeleteMockFixture struct {
   247  	PrimaryKey [][]byte
   248  }
   249  
   250  type CallMockFixture struct {
   251  	ProcName   string
   252  	Args       [][]byte
   253  	RespTuples []TupleData
   254  }