@@ -20,6 +20,7 @@ import (
20
20
"bytes"
21
21
"errors"
22
22
"fmt"
23
+ "math/rand"
23
24
"strconv"
24
25
"sync"
25
26
"testing"
@@ -154,7 +155,7 @@ func bootPeers(ids ...int) []string {
154
155
type peerNode struct {
155
156
port int
156
157
g gossip.Gossip
157
- s GossipStateProvider
158
+ s * GossipStateProviderImpl
158
159
cs * cryptoServiceMock
159
160
commit committer.Committer
160
161
}
@@ -171,17 +172,21 @@ type mockCommitter struct {
171
172
}
172
173
173
174
func (mc * mockCommitter ) Commit (block * pcomm.Block ) error {
174
- mc .Called (block )
175
+ mc .Lock ()
176
+ m := mc .Mock
177
+ mc .Unlock ()
178
+ m .Called (block )
175
179
return nil
176
180
}
177
181
178
182
func (mc * mockCommitter ) LedgerHeight () (uint64 , error ) {
179
183
mc .Lock ()
180
- defer mc .Unlock ()
181
- if mc .Called ().Get (1 ) == nil {
182
- return mc .Called ().Get (0 ).(uint64 ), nil
184
+ m := mc .Mock
185
+ mc .Unlock ()
186
+ if m .Called ().Get (1 ) == nil {
187
+ return m .Called ().Get (0 ).(uint64 ), nil
183
188
}
184
- return mc .Called ().Get (0 ).(uint64 ), mc .Called ().Get (1 ).(error )
189
+ return m .Called ().Get (0 ).(uint64 ), m .Called ().Get (1 ).(error )
185
190
}
186
191
187
192
func (mc * mockCommitter ) GetBlocks (blockSeqs []uint64 ) []* pcomm.Block {
@@ -252,7 +257,7 @@ func newPeerNodeWithGossip(config *gossip.Config, committer committer.Committer,
252
257
return & peerNode {
253
258
port : config .BindPort ,
254
259
g : g ,
255
- s : sp ,
260
+ s : sp .( * GossipStateProviderImpl ) ,
256
261
commit : committer ,
257
262
cs : cs ,
258
263
}
@@ -271,13 +276,13 @@ func TestNilDirectMsg(t *testing.T) {
271
276
g .On ("Accept" , mock .Anything , true ).Return (nil , make (<- chan proto.ReceivedMessage ))
272
277
p := newPeerNodeWithGossip (newGossipConfig (0 ), mc , noopPeerIdentityAcceptor , g )
273
278
defer p .shutdown ()
274
- p .s .( * GossipStateProviderImpl ). handleStateRequest (nil )
275
- p .s .( * GossipStateProviderImpl ). directMessage (nil )
276
- sMsg , _ := p .s .( * GossipStateProviderImpl ). stateRequestMessage (uint64 (10 ), uint64 (8 )).NoopSign ()
279
+ p .s .handleStateRequest (nil )
280
+ p .s .directMessage (nil )
281
+ sMsg , _ := p .s .stateRequestMessage (uint64 (10 ), uint64 (8 )).NoopSign ()
277
282
req := & comm.ReceivedMessageImpl {
278
283
SignedGossipMessage : sMsg ,
279
284
}
280
- p .s .( * GossipStateProviderImpl ). directMessage (req )
285
+ p .s .directMessage (req )
281
286
}
282
287
283
288
func TestNilAddPayload (t * testing.T ) {
@@ -341,32 +346,32 @@ func TestOverPopulation(t *testing.T) {
341
346
for i := 1 ; i <= 4 ; i ++ {
342
347
rawblock := pcomm .NewBlock (uint64 (i ), []byte {})
343
348
b , _ := pb .Marshal (rawblock )
344
- assert .NoError (t , p .s .AddPayload (& proto.Payload {
349
+ assert .NoError (t , p .s .addPayload (& proto.Payload {
345
350
SeqNum : uint64 (i ),
346
351
Data : b ,
347
- }))
352
+ }, nonBlocking ))
348
353
}
349
354
350
355
// Add payloads from 10 to defMaxBlockDistance, while we're missing blocks [5,9]
351
356
// Should succeed
352
357
for i := 10 ; i <= defMaxBlockDistance ; i ++ {
353
358
rawblock := pcomm .NewBlock (uint64 (i ), []byte {})
354
359
b , _ := pb .Marshal (rawblock )
355
- assert .NoError (t , p .s .AddPayload (& proto.Payload {
360
+ assert .NoError (t , p .s .addPayload (& proto.Payload {
356
361
SeqNum : uint64 (i ),
357
362
Data : b ,
358
- }))
363
+ }, nonBlocking ))
359
364
}
360
365
361
366
// Add payloads from defMaxBlockDistance + 2 to defMaxBlockDistance * 10
362
367
// Should fail.
363
368
for i := defMaxBlockDistance + 1 ; i <= defMaxBlockDistance * 10 ; i ++ {
364
369
rawblock := pcomm .NewBlock (uint64 (i ), []byte {})
365
370
b , _ := pb .Marshal (rawblock )
366
- assert .Error (t , p .s .AddPayload (& proto.Payload {
371
+ assert .Error (t , p .s .addPayload (& proto.Payload {
367
372
SeqNum : uint64 (i ),
368
373
Data : b ,
369
- }))
374
+ }, nonBlocking ))
370
375
}
371
376
372
377
// Ensure only blocks 1-4 were passed to the ledger
@@ -379,9 +384,76 @@ func TestOverPopulation(t *testing.T) {
379
384
assert .Equal (t , 5 , i )
380
385
381
386
// Ensure we don't store too many blocks in memory
382
- sp := p .s .( * GossipStateProviderImpl )
387
+ sp := p .s
383
388
assert .True (t , sp .payloads .Size () < defMaxBlockDistance )
389
+ }
384
390
391
+ func TestBlockingEnqueue (t * testing.T ) {
392
+ // Scenario: In parallel, get blocks from gossip and from the orderer.
393
+ // The blocks from the orderer we get are X2 times the amount of blocks from gossip.
394
+ // The blocks we get from gossip are random indices, to maximize disruption.
395
+ mc := & mockCommitter {}
396
+ blocksPassedToLedger := make (chan uint64 , 10 )
397
+ mc .On ("Commit" , mock .Anything ).Run (func (arg mock.Arguments ) {
398
+ blocksPassedToLedger <- arg .Get (0 ).(* pcomm.Block ).Header .Number
399
+ })
400
+ mc .On ("LedgerHeight" , mock .Anything ).Return (uint64 (1 ), nil )
401
+ g := & mocks.GossipMock {}
402
+ g .On ("Accept" , mock .Anything , false ).Return (make (<- chan * proto.GossipMessage ), nil )
403
+ g .On ("Accept" , mock .Anything , true ).Return (nil , make (<- chan proto.ReceivedMessage ))
404
+ p := newPeerNode (newGossipConfig (0 ), mc , noopPeerIdentityAcceptor )
405
+ defer p .shutdown ()
406
+
407
+ numBlocksReceived := 500
408
+ receivedBlockCount := 0
409
+ // Get a block from the orderer every 1ms
410
+ go func () {
411
+ for i := 1 ; i <= numBlocksReceived ; i ++ {
412
+ rawblock := pcomm .NewBlock (uint64 (i ), []byte {})
413
+ b , _ := pb .Marshal (rawblock )
414
+ block := & proto.Payload {
415
+ SeqNum : uint64 (i ),
416
+ Data : b ,
417
+ }
418
+ p .s .AddPayload (block )
419
+ time .Sleep (time .Millisecond )
420
+ }
421
+ }()
422
+
423
+ // Get a block from gossip every 1ms too
424
+ go func () {
425
+ rand .Seed (time .Now ().UnixNano ())
426
+ for i := 1 ; i <= numBlocksReceived / 2 ; i ++ {
427
+ blockSeq := rand .Intn (numBlocksReceived )
428
+ rawblock := pcomm .NewBlock (uint64 (blockSeq ), []byte {})
429
+ b , _ := pb .Marshal (rawblock )
430
+ block := & proto.Payload {
431
+ SeqNum : uint64 (blockSeq ),
432
+ Data : b ,
433
+ }
434
+ p .s .addPayload (block , nonBlocking )
435
+ time .Sleep (time .Millisecond )
436
+ }
437
+ }()
438
+
439
+ for {
440
+ receivedBlock := <- blocksPassedToLedger
441
+ receivedBlockCount ++
442
+ m := mock.Mock {}
443
+ m .On ("LedgerHeight" , mock .Anything ).Return (receivedBlock , nil )
444
+ m .On ("Commit" , mock .Anything ).Run (func (arg mock.Arguments ) {
445
+ blocksPassedToLedger <- arg .Get (0 ).(* pcomm.Block ).Header .Number
446
+ })
447
+ mc .Lock ()
448
+ mc .Mock = m
449
+ mc .Unlock ()
450
+ assert .Equal (t , receivedBlock , uint64 (receivedBlockCount ))
451
+ if int (receivedBlockCount ) == numBlocksReceived {
452
+ break
453
+ }
454
+ time .Sleep (time .Millisecond * 10 )
455
+ t .Log ("got block" , receivedBlock )
456
+ }
385
457
}
386
458
387
459
func TestFailures (t * testing.T ) {
0 commit comments