github.com/s7techlab/cckit@v0.10.5/testing/tx.go (about) 1 package testing 2 3 import ( 4 "sync" 5 6 "github.com/golang/protobuf/ptypes/timestamp" 7 "github.com/hyperledger/fabric-chaincode-go/shim" 8 "github.com/hyperledger/fabric-protos-go/peer" 9 "go.uber.org/zap" 10 11 "github.com/s7techlab/cckit/response" 12 "github.com/s7techlab/cckit/router" 13 "github.com/s7techlab/cckit/testing/expect" 14 ) 15 16 type ( 17 TxHandler struct { 18 MockStub *MockStub 19 m sync.Mutex 20 Logger *zap.Logger 21 Context router.Context 22 } 23 24 TxResult struct { 25 Result interface{} 26 Err error 27 Event *peer.ChaincodeEvent 28 } 29 ) 30 31 func NewTxHandler(name string) (*TxHandler, router.Context) { 32 var ( 33 mockStub = NewMockStub(name, nil) 34 logger = router.NewLogger(name) 35 ctx = router.NewContext(mockStub, logger) 36 ) 37 return &TxHandler{ 38 MockStub: mockStub, 39 Logger: logger, 40 Context: ctx, 41 }, ctx 42 } 43 44 func (p *TxHandler) From(creator ...interface{}) *TxHandler { 45 p.MockStub.From(creator...) 46 return p 47 } 48 49 func (p *TxHandler) Init(txHdl func(ctx router.Context) (interface{}, error)) *TxResult { 50 return p.Invoke(txHdl) 51 } 52 53 // Invoke emulates chaincode invocation and returns transaction result 54 func (p *TxHandler) Invoke(invoke func(ctx router.Context) (interface{}, error)) *TxResult { 55 uuid := p.MockStub.generateTxUID() 56 57 p.MockStub.MockTransactionStart(uuid) 58 res, err := invoke(p.Context) 59 p.MockStub.TxResult = response.Create(res, err) 60 p.MockStub.MockTransactionEnd(uuid) 61 62 txRes := &TxResult{ 63 Result: res, 64 Err: err, 65 Event: p.MockStub.ChaincodeEvent, 66 } 67 68 return txRes 69 } 70 71 // Tx emulates chaincode invocation 72 func (p *TxHandler) Tx(tx func()) { 73 p.m.Lock() 74 defer p.m.Unlock() 75 76 uuid := p.MockStub.generateTxUID() 77 p.MockStub.MockTransactionStart(uuid) 78 79 // expect that invoke will be with shim.OK status, need for dump state changes 80 // if during tx func got error - func setTxResult must be called 81 p.MockStub.TxResult = peer.Response{ 82 Status: shim.OK, 83 Message: "", 84 Payload: nil, 85 } 86 tx() 87 p.MockStub.MockTransactionEnd(uuid) 88 } 89 90 // SetTxResult can be used for set txResult error during Tx 91 func (p *TxHandler) SetTxResult(err error) { 92 if p.MockStub.TxID == `` { 93 panic(`can be called only during Tx() evaluation`) 94 } 95 if err != nil { 96 p.MockStub.TxResult.Status = shim.ERROR 97 p.MockStub.TxResult.Message = err.Error() 98 } 99 } 100 101 // TxFunc returns tx closure, can be used directly as ginkgo func 102 func (p *TxHandler) TxFunc(tx func()) func() { 103 return func() { 104 p.Tx(tx) 105 } 106 } 107 108 // Expect returns assertion helper 109 func (p *TxHandler) Expect(res interface{}, err error) *expect.TxRes { 110 return &expect.TxRes{ 111 Result: res, 112 Err: err, 113 Event: p.MockStub.ChaincodeEvent, 114 } 115 } 116 117 // TxTimestamp returns last tx timestamp 118 func (p *TxHandler) TxTimestamp() *timestamp.Timestamp { 119 return p.MockStub.TxTimestamp 120 } 121 122 // TxEvent returns last tx event 123 func (p *TxHandler) TxEvent() *peer.ChaincodeEvent { 124 return p.MockStub.ChaincodeEvent 125 } 126 127 func (r *TxResult) Expect() *expect.TxRes { 128 return &expect.TxRes{ 129 Result: r.Result, 130 Err: r.Err, 131 Event: r.Event, 132 } 133 }