github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/gossip/state/payloads_buffer_test.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package state 8 9 import ( 10 "crypto/rand" 11 "sync" 12 "sync/atomic" 13 "testing" 14 "time" 15 16 "github.com/hyperledger/fabric/gossip/util" 17 proto "github.com/hyperledger/fabric/protos/gossip" 18 "github.com/stretchr/testify/assert" 19 ) 20 21 func init() { 22 util.SetupTestLogging() 23 } 24 25 func randomPayloadWithSeqNum(seqNum uint64) (*proto.Payload, error) { 26 data := make([]byte, 64) 27 _, err := rand.Read(data) 28 if err != nil { 29 return nil, err 30 } 31 return &proto.Payload{ 32 SeqNum: seqNum, 33 Data: data, 34 }, nil 35 } 36 37 func TestNewPayloadsBuffer(t *testing.T) { 38 payloadsBuffer := NewPayloadsBuffer(10) 39 assert.Equal(t, payloadsBuffer.Next(), uint64(10)) 40 } 41 42 func TestPayloadsBufferImpl_Push(t *testing.T) { 43 buffer := NewPayloadsBuffer(5) 44 45 payload, err := randomPayloadWithSeqNum(4) 46 47 if err != nil { 48 t.Fatal("Wasn't able to generate random payload for test") 49 } 50 51 t.Log("Pushing new payload into buffer") 52 buffer.Push(payload) 53 54 // Payloads with sequence number less than buffer top 55 // index should not be accepted 56 t.Log("Getting next block sequence number") 57 assert.Equal(t, buffer.Next(), uint64(5)) 58 t.Log("Check block buffer size") 59 assert.Equal(t, buffer.Size(), 0) 60 61 // Adding new payload with seq. number equal to top 62 // payload should not be added 63 payload, err = randomPayloadWithSeqNum(5) 64 if err != nil { 65 t.Fatal("Wasn't able to generate random payload for test") 66 } 67 68 t.Log("Pushing new payload into buffer") 69 buffer.Push(payload) 70 t.Log("Getting next block sequence number") 71 assert.Equal(t, buffer.Next(), uint64(5)) 72 t.Log("Check block buffer size") 73 assert.Equal(t, buffer.Size(), 1) 74 } 75 76 func TestPayloadsBufferImpl_Ready(t *testing.T) { 77 fin := make(chan struct{}) 78 buffer := NewPayloadsBuffer(1) 79 assert.Equal(t, buffer.Next(), uint64(1)) 80 81 go func() { 82 <-buffer.Ready() 83 fin <- struct{}{} 84 }() 85 86 time.AfterFunc(100*time.Millisecond, func() { 87 payload, err := randomPayloadWithSeqNum(1) 88 89 if err != nil { 90 t.Fatal("Wasn't able to generate random payload for test") 91 } 92 buffer.Push(payload) 93 }) 94 95 select { 96 case <-fin: 97 payload := buffer.Pop() 98 assert.Equal(t, payload.SeqNum, uint64(1)) 99 case <-time.After(500 * time.Millisecond): 100 t.Fail() 101 } 102 } 103 104 // Test to push several concurrent blocks into the buffer 105 // with same sequence number, only one expected to succeed 106 func TestPayloadsBufferImpl_ConcurrentPush(t *testing.T) { 107 108 // Test setup, next block num to expect and 109 // how many concurrent pushes to simulate 110 nextSeqNum := uint64(7) 111 concurrency := 10 112 113 buffer := NewPayloadsBuffer(nextSeqNum) 114 assert.Equal(t, buffer.Next(), uint64(nextSeqNum)) 115 116 startWG := sync.WaitGroup{} 117 startWG.Add(1) 118 119 finishWG := sync.WaitGroup{} 120 finishWG.Add(concurrency) 121 122 payload, err := randomPayloadWithSeqNum(nextSeqNum) 123 assert.NoError(t, err) 124 125 var errors []error 126 127 ready := int32(0) 128 readyWG := sync.WaitGroup{} 129 readyWG.Add(1) 130 go func() { 131 // Wait for next expected block to arrive 132 <-buffer.Ready() 133 atomic.AddInt32(&ready, 1) 134 readyWG.Done() 135 }() 136 137 for i := 0; i < concurrency; i++ { 138 go func() { 139 startWG.Wait() 140 errors = append(errors, buffer.Push(payload)) 141 finishWG.Done() 142 }() 143 } 144 startWG.Done() 145 finishWG.Wait() 146 147 success := 0 148 149 // Only one push attempt expected to succeed 150 for _, err := range errors { 151 if err == nil { 152 success++ 153 } 154 } 155 156 readyWG.Wait() 157 assert.Equal(t, int32(1), atomic.LoadInt32(&ready)) 158 assert.Equal(t, 1, success) 159 // Buffer size has to be only one 160 assert.Equal(t, 1, buffer.Size()) 161 }