github.com/darrenli6/fabric-sdk-example@v0.0.0-20220109053535-94b13b56df8c/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 logging "github.com/op/go-logging" 28 "github.com/stretchr/testify/assert" 29 ) 30 31 func init() { 32 logging.SetLevel(logging.DEBUG, "") 33 } 34 35 type isolatedCommitter struct{} 36 37 func (ic isolatedCommitter) Isolated() bool { return true } 38 39 func (ic isolatedCommitter) Commit() {} 40 41 type mockIsolatedFilter struct{} 42 43 func (mif *mockIsolatedFilter) Apply(msg *cb.Envelope) (filter.Action, filter.Committer) { 44 if bytes.Equal(msg.Payload, isolatedTx.Payload) { 45 return filter.Accept, isolatedCommitter{} 46 } 47 return filter.Forward, nil 48 } 49 50 type mockRejectFilter struct{} 51 52 func (mrf mockRejectFilter) Apply(message *cb.Envelope) (filter.Action, filter.Committer) { 53 if bytes.Equal(message.Payload, badTx.Payload) { 54 return filter.Reject, nil 55 } 56 return filter.Forward, nil 57 } 58 59 type mockAcceptFilter struct{} 60 61 func (mrf mockAcceptFilter) Apply(message *cb.Envelope) (filter.Action, filter.Committer) { 62 if bytes.Equal(message.Payload, goodTx.Payload) { 63 return filter.Accept, filter.NoopCommitter 64 } 65 return filter.Forward, nil 66 } 67 68 func getFilters() *filter.RuleSet { 69 return filter.NewRuleSet([]filter.Rule{ 70 &mockIsolatedFilter{}, 71 &mockRejectFilter{}, 72 &mockAcceptFilter{}, 73 }) 74 } 75 76 var badTx = &cb.Envelope{Payload: []byte("BAD")} 77 var goodTx = &cb.Envelope{Payload: []byte("GOOD")} 78 var goodTxLarge = &cb.Envelope{Payload: []byte("GOOD"), Signature: make([]byte, 1000)} 79 var isolatedTx = &cb.Envelope{Payload: []byte("ISOLATED")} 80 var unmatchedTx = &cb.Envelope{Payload: []byte("UNMATCHED")} 81 82 func TestNormalBatch(t *testing.T) { 83 filters := getFilters() 84 maxMessageCount := uint32(2) 85 absoluteMaxBytes := uint32(1000) 86 preferredMaxBytes := uint32(100) 87 r := NewReceiverImpl(&mockconfig.Orderer{BatchSizeVal: &ab.BatchSize{MaxMessageCount: maxMessageCount, AbsoluteMaxBytes: absoluteMaxBytes, PreferredMaxBytes: preferredMaxBytes}}, filters) 88 89 batches, committers, ok, pending := r.Ordered(goodTx) 90 91 assert.Nil(t, batches, "Should not have created batch") 92 assert.Nil(t, committers, "Should not have created batch") 93 assert.True(t, ok, "Should have enqueued message into batch") 94 assert.True(t, pending, "Should have pending messages") 95 96 batches, committers, ok, pending = r.Ordered(goodTx) 97 98 assert.Len(t, batches, 1, "Should have created 1 message batch, got %d", len(batches)) 99 assert.Len(t, committers, 1, "Should have created 1 committer batch, got %d", len(committers)) 100 assert.True(t, ok, "Should have enqueued message into batch") 101 assert.False(t, pending, "Should not have pending messages") 102 } 103 104 func TestBadMessageInBatch(t *testing.T) { 105 filters := getFilters() 106 maxMessageCount := uint32(2) 107 absoluteMaxBytes := uint32(1000) 108 preferredMaxBytes := uint32(100) 109 r := NewReceiverImpl(&mockconfig.Orderer{BatchSizeVal: &ab.BatchSize{MaxMessageCount: maxMessageCount, AbsoluteMaxBytes: absoluteMaxBytes, PreferredMaxBytes: preferredMaxBytes}}, filters) 110 111 batches, committers, ok, _ := r.Ordered(badTx) 112 113 assert.Nil(t, batches, "Should not have created batch") 114 assert.Nil(t, committers, "Should not have created batch") 115 assert.False(t, ok, "Should not have enqueued bad message into batch") 116 117 batches, committers, ok, pending := r.Ordered(goodTx) 118 119 assert.Nil(t, batches, "Should not have created batch") 120 assert.Nil(t, committers, "Should not have created batch") 121 assert.True(t, ok, "Should have enqueued good message into batch") 122 assert.True(t, pending, "Should have pending messages") 123 124 batches, committers, ok, _ = r.Ordered(badTx) 125 126 assert.Nil(t, batches, "Should not have created batch") 127 assert.Nil(t, committers, "Should not have created batch") 128 assert.False(t, ok, "Should not have enqueued second bad message into batch") 129 } 130 131 func TestUnmatchedMessageInBatch(t *testing.T) { 132 filters := getFilters() 133 maxMessageCount := uint32(2) 134 absoluteMaxBytes := uint32(1000) 135 preferredMaxBytes := uint32(100) 136 r := NewReceiverImpl(&mockconfig.Orderer{BatchSizeVal: &ab.BatchSize{MaxMessageCount: maxMessageCount, AbsoluteMaxBytes: absoluteMaxBytes, PreferredMaxBytes: preferredMaxBytes}}, filters) 137 138 batches, committers, ok, _ := r.Ordered(unmatchedTx) 139 140 assert.Nil(t, batches, "Should not have created batch") 141 assert.Nil(t, committers, "Should not have created batch") 142 assert.False(t, ok, "Should not have enqueued unmatched message into batch") 143 144 batches, committers, ok, pending := r.Ordered(goodTx) 145 146 assert.Nil(t, batches, "Should not have created batch") 147 assert.Nil(t, committers, "Should not have created batch") 148 assert.True(t, ok, "Should have enqueued good message into batch") 149 assert.True(t, pending, "Should have pending messages") 150 151 batches, committers, ok, _ = r.Ordered(unmatchedTx) 152 153 assert.Nil(t, batches, "Should not have created batch from unmatched message") 154 assert.Nil(t, committers, "Should not have created batch") 155 assert.False(t, ok, "Should not have enqueued second unmatched message into batch") 156 } 157 158 func TestIsolatedEmptyBatch(t *testing.T) { 159 filters := getFilters() 160 maxMessageCount := uint32(2) 161 absoluteMaxBytes := uint32(1000) 162 preferredMaxBytes := uint32(100) 163 r := NewReceiverImpl(&mockconfig.Orderer{BatchSizeVal: &ab.BatchSize{MaxMessageCount: maxMessageCount, AbsoluteMaxBytes: absoluteMaxBytes, PreferredMaxBytes: preferredMaxBytes}}, filters) 164 165 batches, committers, ok, pending := r.Ordered(isolatedTx) 166 167 assert.Len(t, batches, 1, "Should created 1 new message batch, got %d", len(batches)) 168 assert.Len(t, batches[0], 1, "Should have had one isolatedTx in the message batch, got %d", len(batches[0])) 169 assert.Len(t, committers, 1, "Should created 1 new committer batch, got %d", len(committers)) 170 assert.Len(t, committers[0], 1, "Should have had one isolatedTx in the committer batch, got %d", len(committers[0])) 171 assert.True(t, ok, "Should have enqueued isolated message into batch") 172 assert.False(t, pending, "Should not have pending messages") 173 assert.Equal(t, isolatedTx.Payload, batches[0][0].Payload, "Should have had the isolated tx in the first batch") 174 } 175 176 func TestIsolatedPartialBatch(t *testing.T) { 177 filters := getFilters() 178 maxMessageCount := uint32(2) 179 absoluteMaxBytes := uint32(1000) 180 preferredMaxBytes := uint32(100) 181 r := NewReceiverImpl(&mockconfig.Orderer{BatchSizeVal: &ab.BatchSize{MaxMessageCount: maxMessageCount, AbsoluteMaxBytes: absoluteMaxBytes, PreferredMaxBytes: preferredMaxBytes}}, filters) 182 183 batches, committers, ok, pending := r.Ordered(goodTx) 184 185 assert.Nil(t, batches, "Should not have created batch") 186 assert.Nil(t, committers, "Should not have created batch") 187 assert.True(t, ok, "Should have enqueued message into batch") 188 assert.True(t, pending, "Should have pending messages") 189 190 batches, committers, ok, pending = r.Ordered(isolatedTx) 191 192 assert.Len(t, batches, 2, "Should created 2 new message batch, got %d", len(batches)) 193 assert.Len(t, batches[0], 1, "Should have had one goodTx in the first message batch, got %d", len(batches[0])) 194 assert.Len(t, batches[1], 1, "Should have had one isolatedTx in the second message batch, got %d", len(batches[1])) 195 assert.Len(t, committers, 2, "Should created 2 new committer batch, got %d", len(committers)) 196 assert.Len(t, committers[0], 1, "Should have had 1 committer in the first committer batch, got %d", len(committers[0])) 197 assert.Len(t, committers[1], 1, "Should have had 1 committer in the second committer batch, got %d", len(committers[1])) 198 assert.True(t, ok, "Should have enqueued isolated message into batch") 199 assert.False(t, pending, "Should not have pending messages") 200 assert.Equal(t, goodTx.Payload, batches[0][0].Payload, "Should have had the good tx in the first batch") 201 assert.Equal(t, isolatedTx.Payload, batches[1][0].Payload, "Should have had the isolated tx in the second batch") 202 } 203 204 func TestBatchSizePreferredMaxBytesOverflow(t *testing.T) { 205 filters := getFilters() 206 207 goodTxBytes := messageSizeBytes(goodTx) 208 209 // set preferred max bytes such that 10 goodTx will not fit 210 preferredMaxBytes := goodTxBytes*10 - 1 211 212 // set message count > 9 213 maxMessageCount := uint32(20) 214 215 r := NewReceiverImpl(&mockconfig.Orderer{BatchSizeVal: &ab.BatchSize{MaxMessageCount: maxMessageCount, AbsoluteMaxBytes: preferredMaxBytes * 2, PreferredMaxBytes: preferredMaxBytes}}, filters) 216 217 // enqueue 9 messages 218 for i := 0; i < 9; i++ { 219 batches, committers, ok, pending := r.Ordered(goodTx) 220 221 assert.Nil(t, batches, "Should not have created batch") 222 assert.Nil(t, committers, "Should not have created batch") 223 assert.True(t, ok, "Should have enqueued message into batch") 224 assert.True(t, pending, "Should have pending messages") 225 } 226 227 // next message should create batch 228 batches, committers, ok, pending := r.Ordered(goodTx) 229 230 assert.Len(t, batches, 1, "Should have created 1 message batch, got %d", len(batches)) 231 assert.Len(t, batches[0], 9, "Should have had nine normal tx in the message batch, got %d", len(batches[0])) 232 assert.Len(t, committers, 1, "Should have created 1 committer batch, got %d", len(committers)) 233 assert.Len(t, committers[0], 9, "Should have had nine committers in the committer batch, got %d", len(committers[0])) 234 assert.True(t, ok, "Should have enqueued message into batch") 235 assert.True(t, pending, "Should still have pending messages") 236 237 // force a batch cut 238 messageBatch, committerBatch := r.Cut() 239 240 assert.NotNil(t, messageBatch, "Should have created message batch") 241 assert.Len(t, messageBatch, 1, "Should have had 1 tx in the batch, got %d", len(messageBatch)) 242 assert.NotNil(t, committerBatch, "Should have created committer batch") 243 assert.Len(t, committerBatch, 1, "Should have had 1 committer in the committer batch, got %d", len(committerBatch)) 244 } 245 246 func TestBatchSizePreferredMaxBytesOverflowNoPending(t *testing.T) { 247 filters := getFilters() 248 249 goodTxLargeBytes := messageSizeBytes(goodTxLarge) 250 251 // set preferred max bytes such that 1 goodTxLarge will not fit 252 preferredMaxBytes := goodTxLargeBytes - 1 253 254 // set message count > 1 255 maxMessageCount := uint32(20) 256 257 r := NewReceiverImpl(&mockconfig.Orderer{BatchSizeVal: &ab.BatchSize{MaxMessageCount: maxMessageCount, AbsoluteMaxBytes: preferredMaxBytes * 3, PreferredMaxBytes: preferredMaxBytes}}, filters) 258 259 // submit large message 260 batches, committers, ok, pending := r.Ordered(goodTxLarge) 261 262 assert.Len(t, batches, 1, "Should have created 1 message batch, got %d", len(batches)) 263 assert.Len(t, batches[0], 1, "Should have had 1 normal tx in the message batch, got %d", len(batches[0])) 264 assert.Len(t, committers, 1, "Should have created 1 committer batch, got %d", len(committers)) 265 assert.Len(t, committers[0], 1, "Should have had 1 committer in the committer batch, got %d", len(committers[0])) 266 assert.True(t, ok, "Should have enqueued message into batch") 267 assert.False(t, pending, "Should not have pending messages") 268 }