github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/orderer/common/blockcutter/blockcutter_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 blockcutter 18 19 import ( 20 "bytes" 21 "testing" 22 23 mockconfig "github.com/hyperledger/fabric/common/mocks/config" 24 "github.com/hyperledger/fabric/orderer/common/filter" 25 cb "github.com/hyperledger/fabric/protos/common" 26 ab "github.com/hyperledger/fabric/protos/orderer" 27 28 logging "github.com/op/go-logging" 29 "github.com/stretchr/testify/assert" 30 ) 31 32 func init() { 33 logging.SetLevel(logging.DEBUG, "") 34 } 35 36 type isolatedCommitter struct{} 37 38 func (ic isolatedCommitter) Isolated() bool { return true } 39 40 func (ic isolatedCommitter) Commit() {} 41 42 type mockIsolatedFilter struct{} 43 44 func (mif *mockIsolatedFilter) Apply(msg *cb.Envelope) (filter.Action, filter.Committer) { 45 if bytes.Equal(msg.Payload, isolatedTx.Payload) { 46 return filter.Accept, isolatedCommitter{} 47 } 48 return filter.Forward, nil 49 } 50 51 type mockRejectFilter struct{} 52 53 func (mrf mockRejectFilter) Apply(message *cb.Envelope) (filter.Action, filter.Committer) { 54 if bytes.Equal(message.Payload, badTx.Payload) { 55 return filter.Reject, nil 56 } 57 return filter.Forward, nil 58 } 59 60 type mockAcceptFilter struct{} 61 62 func (mrf mockAcceptFilter) Apply(message *cb.Envelope) (filter.Action, filter.Committer) { 63 if bytes.Equal(message.Payload, goodTx.Payload) { 64 return filter.Accept, filter.NoopCommitter 65 } 66 return filter.Forward, nil 67 } 68 69 func getFilters() *filter.RuleSet { 70 return filter.NewRuleSet([]filter.Rule{ 71 &mockIsolatedFilter{}, 72 &mockRejectFilter{}, 73 &mockAcceptFilter{}, 74 }) 75 } 76 77 var badTx = &cb.Envelope{Payload: []byte("BAD")} 78 var goodTx = &cb.Envelope{Payload: []byte("GOOD")} 79 var goodTxLarge = &cb.Envelope{Payload: []byte("GOOD"), Signature: make([]byte, 1000)} 80 var isolatedTx = &cb.Envelope{Payload: []byte("ISOLATED")} 81 var unmatchedTx = &cb.Envelope{Payload: []byte("UNMATCHED")} 82 83 func TestNormalBatch(t *testing.T) { 84 filters := getFilters() 85 maxMessageCount := uint32(2) 86 absoluteMaxBytes := uint32(1000) 87 preferredMaxBytes := uint32(100) 88 r := NewReceiverImpl(&mockconfig.Orderer{BatchSizeVal: &ab.BatchSize{MaxMessageCount: maxMessageCount, AbsoluteMaxBytes: absoluteMaxBytes, PreferredMaxBytes: preferredMaxBytes}}, filters) 89 90 batches, ok := r.Ordered(goodTx) 91 assert.Nil(t, batches, "Should not have created batch") 92 assert.True(t, ok, "Should have enqueued message into batch") 93 94 batches, ok = r.Ordered(goodTx) 95 assert.NotNil(t, batches, "Should have created batch") 96 assert.True(t, ok, "Should have enqueued second message into batch") 97 } 98 99 func TestBadMessageInBatch(t *testing.T) { 100 filters := getFilters() 101 maxMessageCount := uint32(2) 102 absoluteMaxBytes := uint32(1000) 103 preferredMaxBytes := uint32(100) 104 r := NewReceiverImpl(&mockconfig.Orderer{BatchSizeVal: &ab.BatchSize{MaxMessageCount: maxMessageCount, AbsoluteMaxBytes: absoluteMaxBytes, PreferredMaxBytes: preferredMaxBytes}}, filters) 105 106 batches, ok := r.Ordered(badTx) 107 assert.Nil(t, batches, "Should not have created batch") 108 assert.False(t, ok, "Should not have enqueued bad message into batch") 109 110 batches, ok = r.Ordered(goodTx) 111 assert.Nil(t, batches, "Should not have created batch") 112 assert.True(t, ok, "Should have enqueued good message into batch") 113 114 batches, ok = r.Ordered(badTx) 115 assert.Nil(t, batches, "Should not have created batch") 116 assert.False(t, ok, "Should not have enqueued second bad message into batch") 117 } 118 119 func TestUnmatchedMessageInBatch(t *testing.T) { 120 filters := getFilters() 121 maxMessageCount := uint32(2) 122 absoluteMaxBytes := uint32(1000) 123 preferredMaxBytes := uint32(100) 124 r := NewReceiverImpl(&mockconfig.Orderer{BatchSizeVal: &ab.BatchSize{MaxMessageCount: maxMessageCount, AbsoluteMaxBytes: absoluteMaxBytes, PreferredMaxBytes: preferredMaxBytes}}, filters) 125 126 batches, ok := r.Ordered(unmatchedTx) 127 assert.Nil(t, batches, "Should not have created batch") 128 assert.False(t, ok, "Should not have enqueued unmatched message into batch") 129 130 batches, ok = r.Ordered(goodTx) 131 assert.Nil(t, batches, "Should not have created batch") 132 assert.True(t, ok, "Should have enqueued good message into batch") 133 134 batches, ok = r.Ordered(unmatchedTx) 135 assert.Nil(t, batches, "Should not have created batch from unmatched message") 136 assert.False(t, ok, "Should not have enqueued second bad message into batch") 137 } 138 139 func TestIsolatedEmptyBatch(t *testing.T) { 140 filters := getFilters() 141 maxMessageCount := uint32(2) 142 absoluteMaxBytes := uint32(1000) 143 preferredMaxBytes := uint32(100) 144 r := NewReceiverImpl(&mockconfig.Orderer{BatchSizeVal: &ab.BatchSize{MaxMessageCount: maxMessageCount, AbsoluteMaxBytes: absoluteMaxBytes, PreferredMaxBytes: preferredMaxBytes}}, filters) 145 146 assert.Panics(t, func() { r.Ordered(isolatedTx) }, "Should not have handled an isolated by committer message") 147 } 148 149 func TestIsolatedPartialBatch(t *testing.T) { 150 filters := getFilters() 151 maxMessageCount := uint32(2) 152 absoluteMaxBytes := uint32(1000) 153 preferredMaxBytes := uint32(100) 154 r := NewReceiverImpl(&mockconfig.Orderer{BatchSizeVal: &ab.BatchSize{MaxMessageCount: maxMessageCount, AbsoluteMaxBytes: absoluteMaxBytes, PreferredMaxBytes: preferredMaxBytes}}, filters) 155 156 batches, ok := r.Ordered(goodTx) 157 assert.Nil(t, batches, "Should not have created batch") 158 assert.True(t, ok, "Should have enqueued good message into batch") 159 160 assert.Panics(t, func() { r.Ordered(isolatedTx) }, "Should not have handled an isolated by committer message") 161 } 162 163 func TestBatchSizePreferredMaxBytesOverflow(t *testing.T) { 164 filters := getFilters() 165 166 goodTxBytes := messageSizeBytes(goodTx) 167 168 // set preferred max bytes such that 10 goodTx will not fit 169 preferredMaxBytes := goodTxBytes*10 - 1 170 171 // set message count > 9 172 maxMessageCount := uint32(20) 173 174 r := NewReceiverImpl(&mockconfig.Orderer{BatchSizeVal: &ab.BatchSize{MaxMessageCount: maxMessageCount, AbsoluteMaxBytes: preferredMaxBytes * 2, PreferredMaxBytes: preferredMaxBytes}}, filters) 175 176 // enqueue 9 messages 177 for i := 0; i < 9; i++ { 178 batches, ok := r.Ordered(goodTx) 179 assert.Nil(t, batches, "Should not have created batch") 180 assert.True(t, ok, "Should have enqueued message into batch") 181 } 182 183 // next message should create batch 184 batches, ok := r.Ordered(goodTx) 185 assert.NotNil(t, batches, "Should have created batch") 186 assert.True(t, ok, "Should have enqueued message into batch") 187 assert.Len(t, batches, 1, "Should have created one batch") 188 assert.Len(t, batches[0], 9, "Should have had nine normal tx in the batch") 189 190 // force a batch cut 191 messageBatch := r.Cut() 192 assert.NotNil(t, batches, "Should have created batch") 193 assert.Len(t, messageBatch, 1, "Should have had one tx in the batch") 194 } 195 196 func TestBatchSizePreferredMaxBytesOverflowNoPending(t *testing.T) { 197 filters := getFilters() 198 199 goodTxLargeBytes := messageSizeBytes(goodTxLarge) 200 201 // set preferred max bytes such that 1 goodTxLarge will not fit 202 preferredMaxBytes := goodTxLargeBytes - 1 203 204 // set message count > 1 205 maxMessageCount := uint32(20) 206 207 r := NewReceiverImpl(&mockconfig.Orderer{BatchSizeVal: &ab.BatchSize{MaxMessageCount: maxMessageCount, AbsoluteMaxBytes: preferredMaxBytes * 3, PreferredMaxBytes: preferredMaxBytes}}, filters) 208 209 // submit large message 210 batches, ok := r.Ordered(goodTxLarge) 211 assert.NotNil(t, batches, "Should have created batch") 212 assert.True(t, ok, "Should have enqueued message into batch") 213 assert.Len(t, batches, 1, "Should have created one batch") 214 assert.Len(t, batches[0], 1, "Should have had one normal tx in the batch") 215 }