/
mocked_peer.go
143 lines (115 loc) · 3.29 KB
/
mocked_peer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package testing
import (
"context"
"fmt"
"sync"
"github.com/hyperledger/fabric/core/chaincode/shim"
"github.com/pkg/errors"
"github.com/hyperledger/fabric/msp"
"github.com/hyperledger/fabric/protos/peer"
"github.com/s7techlab/hlf-sdk-go/api"
)
type (
ChannelMockStubs map[string]*MockStub
ChannelsMockStubs map[string]ChannelMockStubs
MockedPeer struct {
// channel name -> chaincode name
ChannelCC ChannelsMockStubs
m sync.Mutex
}
EventSubscription struct {
events chan *peer.ChaincodeEvent
errors chan error
closer sync.Once
}
)
// NewInvoker implements Invoker interface from hlf-sdk-go
func NewPeer() *MockedPeer {
return &MockedPeer{
ChannelCC: make(ChannelsMockStubs),
}
}
func (mi *MockedPeer) WithChannel(channel string, mockStubs ...*MockStub) *MockedPeer {
if _, ok := mi.ChannelCC[channel]; !ok {
mi.ChannelCC[channel] = make(ChannelMockStubs)
}
for _, ms := range mockStubs {
mi.ChannelCC[channel][ms.Name] = ms
for chName, chnl := range mi.ChannelCC {
for ccName, cc := range chnl {
// add visibility of added cc to all other cc
cc.MockPeerChaincode(ms.Name+`/`+channel, ms)
// add visibility of other cc to added cc
ms.MockPeerChaincode(ccName+`/`+chName, cc)
}
}
}
return mi
}
func (mi *MockedPeer) Invoke(
ctx context.Context, from msp.SigningIdentity, channel string, chaincode string,
fn string, args [][]byte, transArgs api.TransArgs) (*peer.Response, api.ChaincodeTx, error) {
mi.m.Lock()
defer mi.m.Unlock()
mockStub, err := mi.Chaincode(channel, chaincode)
if err != nil {
return nil, ``, err
}
response := mockStub.From(from).WithTransient(transArgs).InvokeBytes(append([][]byte{[]byte(fn)}, args...)...)
if response.Status == shim.ERROR {
err = errors.New(response.Message)
}
return &response, api.ChaincodeTx(mockStub.TxID), err
}
func (mi *MockedPeer) Query(
ctx context.Context, from msp.SigningIdentity, channel string, chaincode string,
fn string, args [][]byte, transArgs api.TransArgs) (*peer.Response, error) {
mi.m.Lock()
defer mi.m.Unlock()
mockStub, err := mi.Chaincode(channel, chaincode)
if err != nil {
return nil, err
}
response := mockStub.From(from).WithTransient(transArgs).QueryBytes(append([][]byte{[]byte(fn)}, args...)...)
if response.Status == shim.ERROR {
err = errors.New(response.Message)
}
return &response, err
}
func (mi *MockedPeer) Subscribe(
ctx context.Context, from msp.SigningIdentity, channel, chaincode string) (api.EventCCSubscription, error) {
mockStub, err := mi.Chaincode(channel, chaincode)
if err != nil {
return nil, err
}
sub := &EventSubscription{
events: mockStub.EventSubscription(),
errors: make(chan error),
}
go func() {
<-ctx.Done()
close(sub.events)
close(sub.errors)
}()
return sub, nil
}
func (mi *MockedPeer) Chaincode(channel string, chaincode string) (*MockStub, error) {
ms, exists := mi.ChannelCC[channel][chaincode]
if !exists {
return nil, fmt.Errorf(`%s: channell=%s, chaincode=%s`, ErrChaincodeNotExists, channel, chaincode)
}
return ms, nil
}
func (es *EventSubscription) Events() chan *peer.ChaincodeEvent {
return es.events
}
func (es *EventSubscription) Errors() chan error {
return es.errors
}
func (es *EventSubscription) Close() error {
es.closer.Do(func() {
close(es.events)
close(es.errors)
})
return nil
}