github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/orderer/solo/consensus_test.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package solo 18 19 import ( 20 "testing" 21 "time" 22 23 mockconfigvaluesorderer "github.com/hyperledger/fabric/common/mocks/configvalues/channel/orderer" 24 mockblockcutter "github.com/hyperledger/fabric/orderer/mocks/blockcutter" 25 mockmultichain "github.com/hyperledger/fabric/orderer/mocks/multichain" 26 cb "github.com/hyperledger/fabric/protos/common" 27 28 logging "github.com/op/go-logging" 29 ) 30 31 func init() { 32 logging.SetLevel(logging.DEBUG, "") 33 } 34 35 var testMessage = &cb.Envelope{Payload: []byte("TEST_MESSAGE")} 36 37 func syncQueueMessage(msg *cb.Envelope, chain *chain, bc *mockblockcutter.Receiver) { 38 chain.Enqueue(msg) 39 bc.Block <- struct{}{} 40 } 41 42 type waitableGo struct { 43 done chan struct{} 44 } 45 46 func goWithWait(target func()) *waitableGo { 47 wg := &waitableGo{ 48 done: make(chan struct{}), 49 } 50 go func() { 51 target() 52 close(wg.done) 53 }() 54 return wg 55 } 56 57 func TestEmptyBatch(t *testing.T) { 58 batchTimeout, _ := time.ParseDuration("1ms") 59 support := &mockmultichain.ConsenterSupport{ 60 Batches: make(chan []*cb.Envelope), 61 BlockCutterVal: mockblockcutter.NewReceiver(), 62 SharedConfigVal: &mockconfigvaluesorderer.SharedConfig{BatchTimeoutVal: batchTimeout}, 63 } 64 defer close(support.BlockCutterVal.Block) 65 bs := newChain(support) 66 wg := goWithWait(bs.main) 67 defer bs.Halt() 68 69 syncQueueMessage(testMessage, bs, support.BlockCutterVal) 70 bs.Halt() 71 select { 72 case <-support.Batches: 73 t.Fatalf("Expected no invocations of Append") 74 case <-wg.done: 75 } 76 } 77 78 func TestBatchTimer(t *testing.T) { 79 batchTimeout, _ := time.ParseDuration("1ms") 80 support := &mockmultichain.ConsenterSupport{ 81 Batches: make(chan []*cb.Envelope), 82 BlockCutterVal: mockblockcutter.NewReceiver(), 83 SharedConfigVal: &mockconfigvaluesorderer.SharedConfig{BatchTimeoutVal: batchTimeout}, 84 } 85 defer close(support.BlockCutterVal.Block) 86 bs := newChain(support) 87 wg := goWithWait(bs.main) 88 defer bs.Halt() 89 90 syncQueueMessage(testMessage, bs, support.BlockCutterVal) 91 92 select { 93 case <-support.Batches: 94 case <-time.After(time.Second): 95 t.Fatalf("Expected a block to be cut because of batch timer expiration but did not") 96 } 97 98 syncQueueMessage(testMessage, bs, support.BlockCutterVal) 99 select { 100 case <-support.Batches: 101 case <-time.After(time.Second): 102 t.Fatalf("Did not create the second batch, indicating that the timer was not appopriately reset") 103 } 104 105 bs.Halt() 106 select { 107 case <-support.Batches: 108 t.Fatalf("Expected no invocations of Append") 109 case <-wg.done: 110 } 111 } 112 113 func TestBatchTimerHaltOnFilledBatch(t *testing.T) { 114 batchTimeout, _ := time.ParseDuration("1h") 115 support := &mockmultichain.ConsenterSupport{ 116 Batches: make(chan []*cb.Envelope), 117 BlockCutterVal: mockblockcutter.NewReceiver(), 118 SharedConfigVal: &mockconfigvaluesorderer.SharedConfig{BatchTimeoutVal: batchTimeout}, 119 } 120 defer close(support.BlockCutterVal.Block) 121 122 bs := newChain(support) 123 wg := goWithWait(bs.main) 124 defer bs.Halt() 125 126 syncQueueMessage(testMessage, bs, support.BlockCutterVal) 127 support.BlockCutterVal.CutNext = true 128 syncQueueMessage(testMessage, bs, support.BlockCutterVal) 129 130 select { 131 case <-support.Batches: 132 case <-time.After(time.Second): 133 t.Fatalf("Expected a block to be cut because the batch was filled, but did not") 134 } 135 136 // Change the batch timeout to be near instant, if the timer was not reset, it will still be waiting an hour 137 bs.batchTimeout = time.Millisecond 138 139 support.BlockCutterVal.CutNext = false 140 syncQueueMessage(testMessage, bs, support.BlockCutterVal) 141 142 select { 143 case <-support.Batches: 144 case <-time.After(time.Second): 145 t.Fatalf("Did not create the second batch, indicating that the old timer was still running") 146 } 147 148 bs.Halt() 149 select { 150 case <-time.After(time.Second): 151 t.Fatalf("Should have exited") 152 case <-wg.done: 153 } 154 } 155 156 func TestConfigStyleMultiBatch(t *testing.T) { 157 batchTimeout, _ := time.ParseDuration("1h") 158 support := &mockmultichain.ConsenterSupport{ 159 Batches: make(chan []*cb.Envelope), 160 BlockCutterVal: mockblockcutter.NewReceiver(), 161 SharedConfigVal: &mockconfigvaluesorderer.SharedConfig{BatchTimeoutVal: batchTimeout}, 162 } 163 defer close(support.BlockCutterVal.Block) 164 bs := newChain(support) 165 wg := goWithWait(bs.main) 166 defer bs.Halt() 167 168 syncQueueMessage(testMessage, bs, support.BlockCutterVal) 169 support.BlockCutterVal.IsolatedTx = true 170 syncQueueMessage(testMessage, bs, support.BlockCutterVal) 171 172 select { 173 case <-support.Batches: 174 case <-time.After(time.Second): 175 t.Fatalf("Expected two blocks to be cut but never got the first") 176 } 177 178 select { 179 case <-support.Batches: 180 case <-time.After(time.Second): 181 t.Fatalf("Expected the config type tx to create two blocks, but only go the first") 182 } 183 184 bs.Halt() 185 select { 186 case <-time.After(time.Second): 187 t.Fatalf("Should have exited") 188 case <-wg.done: 189 } 190 }