@@ -16,7 +16,9 @@ limitations under the License.
16
16
package blocksprovider
17
17
18
18
import (
19
+ "errors"
19
20
"sync"
21
+ "sync/atomic"
20
22
"testing"
21
23
"time"
22
24
@@ -26,16 +28,22 @@ import (
26
28
"github.com/hyperledger/fabric/protos/common"
27
29
"github.com/hyperledger/fabric/protos/orderer"
28
30
"github.com/stretchr/testify/assert"
31
+ "github.com/stretchr/testify/mock"
29
32
)
30
33
31
34
type mockMCS struct {
35
+ mock.Mock
32
36
}
33
37
34
38
func (* mockMCS ) GetPKIidOfCert (peerIdentity api.PeerIdentityType ) common2.PKIidType {
35
39
return common2 .PKIidType ("pkiID" )
36
40
}
37
41
38
- func (* mockMCS ) VerifyBlock (chainID common2.ChainID , signedBlock []byte ) error {
42
+ func (m * mockMCS ) VerifyBlock (chainID common2.ChainID , signedBlock []byte ) error {
43
+ args := m .Called ()
44
+ if args .Get (0 ) != nil {
45
+ return args .Get (0 ).(error )
46
+ }
39
47
return nil
40
48
}
41
49
@@ -55,47 +63,42 @@ func (*mockMCS) ValidateIdentity(peerIdentity api.PeerIdentityType) error {
55
63
return nil
56
64
}
57
65
66
+ type rcvFunc func (mock * mocks.MockBlocksDeliverer ) (* orderer.DeliverResponse , error )
67
+
58
68
// Used to generate a simple test case to initialize delivery
59
69
// from given block sequence number.
60
- func makeTestCase (ledgerHeight uint64 ) func (* testing.T ) {
70
+ func makeTestCase (ledgerHeight uint64 , mcs api. MessageCryptoService , shouldSucceed bool , rcv rcvFunc ) func (* testing.T ) {
61
71
return func (t * testing.T ) {
62
72
gossipServiceAdapter := & mocks.MockGossipServiceAdapter {GossipBlockDisseminations : make (chan uint64 )}
63
73
deliverer := & mocks.MockBlocksDeliverer {Pos : ledgerHeight }
64
- deliverer .MockRecv = mocks .MockRecv
65
-
66
- provider := & blocksProviderImpl {
67
- chainID : "***TEST_CHAINID***" ,
68
- gossip : gossipServiceAdapter ,
69
- client : deliverer ,
70
- mcs : & mockMCS {},
71
- }
72
-
74
+ deliverer .MockRecv = rcv
75
+ provider := NewBlocksProvider ("***TEST_CHAINID***" , deliverer , gossipServiceAdapter , mcs )
76
+ defer provider .Stop ()
73
77
ready := make (chan struct {})
74
78
go func () {
75
79
go provider .DeliverBlocks ()
76
80
// Send notification
77
81
ready <- struct {}{}
78
82
}()
79
83
80
- time .Sleep (time .Duration (10 ) * time .Millisecond )
81
- provider .Stop ()
82
-
83
- select {
84
- case <- ready :
85
- {
86
- // Check that all blocks received eventually get gossiped and locally committed
87
- assert .True (t , deliverer .RecvCnt == gossipServiceAdapter .AddPayloadsCnt )
88
- select {
89
- case <- gossipServiceAdapter .GossipBlockDisseminations :
90
- case <- time .After (time .Second ):
91
- assert .Fail (t , "Didn't gossip a block within a timely manner" )
92
- }
93
- return
94
- }
95
- case <- time .After (time .Duration (1 ) * time .Second ):
96
- {
97
- t .Fatal ("Test hasn't finished in timely manner, failing." )
98
- }
84
+ time .Sleep (time .Second )
85
+
86
+ assertDelivery (t , gossipServiceAdapter , deliverer , shouldSucceed )
87
+ }
88
+ }
89
+
90
+ func assertDelivery (t * testing.T , ga * mocks.MockGossipServiceAdapter , deliverer * mocks.MockBlocksDeliverer , shouldSucceed bool ) {
91
+ // Check that all blocks received eventually get gossiped and locally committed
92
+
93
+ select {
94
+ case <- ga .GossipBlockDisseminations :
95
+ if ! shouldSucceed {
96
+ assert .Fail (t , "Should not have succeede" )
97
+ }
98
+ assert .True (t , deliverer .RecvCnt == ga .AddPayloadsCnt )
99
+ case <- time .After (time .Second ):
100
+ if shouldSucceed {
101
+ assert .Fail (t , "Didn't gossip a block within a timely manner" )
99
102
}
100
103
}
101
104
}
@@ -105,19 +108,22 @@ func makeTestCase(ledgerHeight uint64) func(*testing.T) {
105
108
oldest and that eventually it terminates after the Stop method has been called.
106
109
*/
107
110
func TestBlocksProviderImpl_GetBlockFromTheOldest (t * testing.T ) {
108
- makeTestCase (uint64 (0 ))(t )
111
+ mcs := & mockMCS {}
112
+ mcs .On ("VerifyBlock" , mock .Anything ).Return (nil )
113
+ makeTestCase (uint64 (0 ), mcs , true , mocks .MockRecv )(t )
109
114
}
110
115
111
116
/*
112
117
Test to check whenever blocks provider starts calling new blocks from the
113
118
oldest and that eventually it terminates after the Stop method has been called.
114
119
*/
115
120
func TestBlocksProviderImpl_GetBlockFromSpecified (t * testing.T ) {
116
- makeTestCase (uint64 (101 ))(t )
121
+ mcs := & mockMCS {}
122
+ mcs .On ("VerifyBlock" , mock .Anything ).Return (nil )
123
+ makeTestCase (uint64 (101 ), mcs , true , mocks .MockRecv )(t )
117
124
}
118
125
119
126
func TestBlocksProvider_CheckTerminationDeliveryResponseStatus (t * testing.T ) {
120
-
121
127
tmp := struct { mocks.MockBlocksDeliverer }{}
122
128
123
129
// Making mocked Recv() function to return DeliverResponse_Status to force block
@@ -158,7 +164,7 @@ func TestBlocksProvider_CheckTerminationDeliveryResponseStatus(t *testing.T) {
158
164
assert .Equal (t , int32 (1 ), tmp .RecvCnt )
159
165
// No payload should commit locally
160
166
assert .Equal (t , int32 (0 ), gossipServiceAdapter .AddPayloadsCnt )
161
- // No payload should be transfered to other peers
167
+ // No payload should be transferred to other peers
162
168
select {
163
169
case <- gossipServiceAdapter .GossipBlockDisseminations :
164
170
assert .Fail (t , "Gossiped block but shouldn't have" )
@@ -172,3 +178,42 @@ func TestBlocksProvider_CheckTerminationDeliveryResponseStatus(t *testing.T) {
172
178
}
173
179
}
174
180
}
181
+
182
+ func TestBlockFetchFailure (t * testing.T ) {
183
+ rcvr := func (mock * mocks.MockBlocksDeliverer ) (* orderer.DeliverResponse , error ) {
184
+ return nil , errors .New ("Failed fetching block" )
185
+ }
186
+ mcs := & mockMCS {}
187
+ mcs .On ("VerifyBlock" , mock .Anything ).Return (nil )
188
+ makeTestCase (uint64 (0 ), mcs , false , rcvr )(t )
189
+ }
190
+
191
+ func TestBlockVerificationFailure (t * testing.T ) {
192
+ attempts := int32 (0 )
193
+ rcvr := func (mock * mocks.MockBlocksDeliverer ) (* orderer.DeliverResponse , error ) {
194
+ if atomic .LoadInt32 (& attempts ) == int32 (1 ) {
195
+ return & orderer.DeliverResponse {
196
+ Type : & orderer.DeliverResponse_Status {
197
+ Status : common .Status_SUCCESS ,
198
+ },
199
+ }, nil
200
+ }
201
+ atomic .AddInt32 (& attempts , int32 (1 ))
202
+ return & orderer.DeliverResponse {
203
+ Type : & orderer.DeliverResponse_Block {
204
+ Block : & common.Block {
205
+ Header : & common.BlockHeader {
206
+ Number : 0 ,
207
+ DataHash : []byte {},
208
+ PreviousHash : []byte {},
209
+ },
210
+ Data : & common.BlockData {
211
+ Data : [][]byte {},
212
+ },
213
+ }},
214
+ }, nil
215
+ }
216
+ mcs := & mockMCS {}
217
+ mcs .On ("VerifyBlock" , mock .Anything ).Return (errors .New ("Invalid signature" ))
218
+ makeTestCase (uint64 (0 ), mcs , false , rcvr )(t )
219
+ }
0 commit comments