github.com/s7techlab/cckit@v0.10.5/testing/mocked_peer.go (about) 1 package testing 2 3 import ( 4 "context" 5 "fmt" 6 "sync" 7 8 "github.com/golang/protobuf/ptypes/timestamp" 9 "github.com/hyperledger/fabric-chaincode-go/shim" 10 "github.com/hyperledger/fabric-protos-go/common" 11 "github.com/hyperledger/fabric-protos-go/peer" 12 "github.com/hyperledger/fabric/msp" 13 "github.com/pkg/errors" 14 ) 15 16 type ( 17 MockedPeer struct { 18 // channel name -> chaincode name 19 ChannelCC ChannelsMockStubs 20 m sync.Mutex 21 } 22 23 ChannelMockStubs map[string]*MockStub 24 25 ChannelsMockStubs map[string]ChannelMockStubs 26 27 EventSubscription struct { 28 events chan *peer.ChaincodeEvent 29 errors chan error 30 closer sync.Once 31 } 32 ) 33 34 // NewPeer implements Peer interface 35 func NewPeer() *MockedPeer { 36 return &MockedPeer{ 37 ChannelCC: make(ChannelsMockStubs), 38 } 39 } 40 41 func (mp *MockedPeer) WithChannel(channel string, mockStubs ...*MockStub) *MockedPeer { 42 if _, ok := mp.ChannelCC[channel]; !ok { 43 mp.ChannelCC[channel] = make(ChannelMockStubs) 44 } 45 46 for _, ms := range mockStubs { 47 mp.ChannelCC[channel][ms.Name] = ms 48 for chName, chnl := range mp.ChannelCC { 49 for ccName, cc := range chnl { 50 51 // add visibility of added cc to all other cc 52 cc.MockPeerChaincode(ms.Name+`/`+channel, ms) 53 54 // add visibility of other cc to added cc 55 ms.MockPeerChaincode(ccName+`/`+chName, cc) 56 } 57 } 58 } 59 60 return mp 61 } 62 63 func (mp *MockedPeer) CurrentIdentity() msp.SigningIdentity { 64 return nil 65 } 66 67 func (mp *MockedPeer) Invoke( 68 ctx context.Context, 69 channel string, 70 chaincode string, 71 args [][]byte, 72 identity msp.SigningIdentity, 73 transArgs map[string][]byte, 74 txWaiterType string) (res *peer.Response, chaincodeTx string, err error) { 75 76 mp.m.Lock() 77 defer mp.m.Unlock() 78 mockStub, err := mp.Chaincode(channel, chaincode) 79 if err != nil { 80 return nil, ``, err 81 } 82 83 response := mockStub.From(identity).WithTransient(transArgs).InvokeBytes(args...) 84 if response.Status == shim.ERROR { 85 err = errors.New(response.Message) 86 } 87 88 return &response, mockStub.TxID, err 89 } 90 91 func (mp *MockedPeer) Query( 92 ctx context.Context, 93 channel string, 94 chaincode string, 95 args [][]byte, 96 identity msp.SigningIdentity, 97 transArgs map[string][]byte) (*peer.Response, error) { 98 99 mp.m.Lock() 100 defer mp.m.Unlock() 101 mockStub, err := mp.Chaincode(channel, chaincode) 102 if err != nil { 103 return nil, err 104 } 105 106 response := mockStub.From(identity).WithTransient(transArgs).QueryBytes(args...) 107 if response.Status == shim.ERROR { 108 err = errors.New(response.Message) 109 } 110 111 return &response, err 112 113 } 114 115 func (mp *MockedPeer) Chaincode(channel string, chaincode string) (*MockStub, error) { 116 ms, exists := mp.ChannelCC[channel][chaincode] 117 if !exists { 118 return nil, fmt.Errorf(`%s: channell=%s, chaincode=%s`, ErrChaincodeNotExists, channel, chaincode) 119 } 120 121 return ms, nil 122 } 123 124 func (mp *MockedPeer) Events( 125 ctx context.Context, 126 channel string, 127 chaincode string, 128 identity msp.SigningIdentity, 129 blockRange ...int64, 130 ) (events chan interface { 131 Event() *peer.ChaincodeEvent 132 Block() uint64 133 TxTimestamp() *timestamp.Timestamp 134 }, closer func() error, err error) { 135 mockStub, err := mp.Chaincode(channel, chaincode) 136 if err != nil { 137 return nil, nil, err 138 } 139 140 var ( 141 eventsRaw chan *peer.ChaincodeEvent 142 ) 143 // from oldest block to current channel height 144 if len(blockRange) > 0 && blockRange[0] == 0 { 145 // create copy of mockStub events chan 146 eventsRaw, closer = mockStub.EventSubscription(0) 147 148 // In real HLF peer stream not closed 149 //// close events channel if its empty, because we receive events until current channel height 150 //go func() { 151 // ticker := time.NewTicker(5 * time.Millisecond) 152 // for { 153 // <-ticker.C 154 // if len(events) == 0 { 155 // closer() 156 // ticker.Stop() 157 // return 158 // } 159 // } 160 //}() 161 } else { 162 eventsRaw, closer = mockStub.EventSubscription() 163 } 164 165 go func() { 166 <-ctx.Done() 167 _ = closer() 168 }() 169 170 eventsExtended := make(chan interface { 171 Event() *peer.ChaincodeEvent 172 Block() uint64 173 TxTimestamp() *timestamp.Timestamp 174 }) 175 go func() { 176 for e := range eventsRaw { 177 eventsExtended <- &ChaincodeEvent{ 178 event: e, 179 180 // todo: store information about block and timestamp in MockStub 181 block: 55, 182 txTimestamp: nil, 183 } 184 } 185 close(eventsExtended) 186 }() 187 188 return eventsExtended, closer, nil 189 } 190 191 func (m *MockedPeer) Blocks( 192 ctx context.Context, 193 channelName string, 194 identity msp.SigningIdentity, 195 blockRange ...int64, 196 ) (blockChan <-chan *common.Block, closer func() error, err error) { 197 panic("not implemented") 198 } 199 200 func (es *EventSubscription) Events() chan *peer.ChaincodeEvent { 201 return es.events 202 } 203 204 func (es *EventSubscription) Errors() chan error { 205 return es.errors 206 } 207 208 func (es *EventSubscription) Close() error { 209 es.closer.Do(func() { 210 close(es.events) 211 close(es.errors) 212 }) 213 return nil 214 }