github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/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 mockconfigtxorderer "github.com/hyperledger/fabric/common/mocks/configvalues/channel/orderer" 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 ) 29 30 func init() { 31 logging.SetLevel(logging.DEBUG, "") 32 } 33 34 type isolatedCommitter struct{} 35 36 func (ic isolatedCommitter) Isolated() bool { return true } 37 38 func (ic isolatedCommitter) Commit() {} 39 40 type mockIsolatedFilter struct{} 41 42 func (mif *mockIsolatedFilter) Apply(msg *cb.Envelope) (filter.Action, filter.Committer) { 43 if bytes.Equal(msg.Payload, isolatedTx.Payload) { 44 return filter.Accept, isolatedCommitter{} 45 } 46 return filter.Forward, nil 47 } 48 49 type mockRejectFilter struct{} 50 51 func (mrf mockRejectFilter) Apply(message *cb.Envelope) (filter.Action, filter.Committer) { 52 if bytes.Equal(message.Payload, badTx.Payload) { 53 return filter.Reject, nil 54 } 55 return filter.Forward, nil 56 } 57 58 type mockAcceptFilter struct{} 59 60 func (mrf mockAcceptFilter) Apply(message *cb.Envelope) (filter.Action, filter.Committer) { 61 if bytes.Equal(message.Payload, goodTx.Payload) { 62 return filter.Accept, filter.NoopCommitter 63 } 64 return filter.Forward, nil 65 } 66 67 func getFilters() *filter.RuleSet { 68 return filter.NewRuleSet([]filter.Rule{ 69 &mockIsolatedFilter{}, 70 &mockRejectFilter{}, 71 &mockAcceptFilter{}, 72 }) 73 } 74 75 var badTx = &cb.Envelope{Payload: []byte("BAD")} 76 var goodTx = &cb.Envelope{Payload: []byte("GOOD")} 77 var goodTxLarge = &cb.Envelope{Payload: []byte("GOOD"), Signature: make([]byte, 1000)} 78 var isolatedTx = &cb.Envelope{Payload: []byte("ISOLATED")} 79 var unmatchedTx = &cb.Envelope{Payload: []byte("UNMATCHED")} 80 81 func TestNormalBatch(t *testing.T) { 82 filters := getFilters() 83 maxMessageCount := uint32(2) 84 absoluteMaxBytes := uint32(1000) 85 preferredMaxBytes := uint32(100) 86 r := NewReceiverImpl(&mockconfigtxorderer.SharedConfig{BatchSizeVal: &ab.BatchSize{MaxMessageCount: maxMessageCount, AbsoluteMaxBytes: absoluteMaxBytes, PreferredMaxBytes: preferredMaxBytes}}, filters) 87 88 batches, committers, ok := r.Ordered(goodTx) 89 90 if batches != nil || committers != nil { 91 t.Fatalf("Should not have created batch") 92 } 93 94 if !ok { 95 t.Fatalf("Should have enqueued message into batch") 96 } 97 98 batches, committers, ok = r.Ordered(goodTx) 99 100 if batches == nil || committers == nil { 101 t.Fatalf("Should have created batch") 102 } 103 104 if !ok { 105 t.Fatalf("Should have enqueued second message into batch") 106 } 107 108 } 109 110 func TestBadMessageInBatch(t *testing.T) { 111 filters := getFilters() 112 maxMessageCount := uint32(2) 113 absoluteMaxBytes := uint32(1000) 114 preferredMaxBytes := uint32(100) 115 r := NewReceiverImpl(&mockconfigtxorderer.SharedConfig{BatchSizeVal: &ab.BatchSize{MaxMessageCount: maxMessageCount, AbsoluteMaxBytes: absoluteMaxBytes, PreferredMaxBytes: preferredMaxBytes}}, filters) 116 117 batches, committers, ok := r.Ordered(badTx) 118 119 if batches != nil || committers != nil { 120 t.Fatalf("Should not have created batch") 121 } 122 123 if ok { 124 t.Fatalf("Should not have enqueued bad message into batch") 125 } 126 127 batches, committers, ok = r.Ordered(goodTx) 128 129 if batches != nil || committers != nil { 130 t.Fatalf("Should not have created batch") 131 } 132 133 if !ok { 134 t.Fatalf("Should have enqueued good message into batch") 135 } 136 137 batches, committers, ok = r.Ordered(badTx) 138 139 if batches != nil || committers != nil { 140 t.Fatalf("Should not have created batch") 141 } 142 143 if ok { 144 t.Fatalf("Should not have enqueued second bad message into batch") 145 } 146 } 147 148 func TestUnmatchedMessageInBatch(t *testing.T) { 149 filters := getFilters() 150 maxMessageCount := uint32(2) 151 absoluteMaxBytes := uint32(1000) 152 preferredMaxBytes := uint32(100) 153 r := NewReceiverImpl(&mockconfigtxorderer.SharedConfig{BatchSizeVal: &ab.BatchSize{MaxMessageCount: maxMessageCount, AbsoluteMaxBytes: absoluteMaxBytes, PreferredMaxBytes: preferredMaxBytes}}, filters) 154 155 batches, committers, ok := r.Ordered(unmatchedTx) 156 157 if batches != nil || committers != nil { 158 t.Fatalf("Should not have created batch") 159 } 160 161 if ok { 162 t.Fatalf("Should not have enqueued unmatched message into batch") 163 } 164 165 batches, committers, ok = r.Ordered(goodTx) 166 167 if batches != nil || committers != nil { 168 t.Fatalf("Should not have created batch") 169 } 170 171 if !ok { 172 t.Fatalf("Should have enqueued good message into batch") 173 } 174 175 batches, committers, ok = r.Ordered(unmatchedTx) 176 177 if batches != nil || committers != nil { 178 t.Fatalf("Should not have created batch from unmatched message") 179 } 180 181 if ok { 182 t.Fatalf("Should not have enqueued second bad message into batch") 183 } 184 } 185 186 func TestIsolatedEmptyBatch(t *testing.T) { 187 filters := getFilters() 188 maxMessageCount := uint32(2) 189 absoluteMaxBytes := uint32(1000) 190 preferredMaxBytes := uint32(100) 191 r := NewReceiverImpl(&mockconfigtxorderer.SharedConfig{BatchSizeVal: &ab.BatchSize{MaxMessageCount: maxMessageCount, AbsoluteMaxBytes: absoluteMaxBytes, PreferredMaxBytes: preferredMaxBytes}}, filters) 192 193 batches, committers, ok := r.Ordered(isolatedTx) 194 195 if !ok { 196 t.Fatalf("Should have enqueued isolated message") 197 } 198 199 if len(batches) != 1 || len(committers) != 1 { 200 t.Fatalf("Should created new batch, got %d and %d", len(batches), len(committers)) 201 } 202 203 if len(batches[0]) != 1 || len(committers[0]) != 1 { 204 t.Fatalf("Should have had one isolatedTx in the second batch got %d and %d", len(batches[1]), len(committers[0])) 205 } 206 207 if !bytes.Equal(batches[0][0].Payload, isolatedTx.Payload) { 208 t.Fatalf("Should have had the isolated tx in the first batch") 209 } 210 } 211 212 func TestIsolatedPartialBatch(t *testing.T) { 213 filters := getFilters() 214 maxMessageCount := uint32(2) 215 absoluteMaxBytes := uint32(1000) 216 preferredMaxBytes := uint32(100) 217 r := NewReceiverImpl(&mockconfigtxorderer.SharedConfig{BatchSizeVal: &ab.BatchSize{MaxMessageCount: maxMessageCount, AbsoluteMaxBytes: absoluteMaxBytes, PreferredMaxBytes: preferredMaxBytes}}, filters) 218 219 batches, committers, ok := r.Ordered(goodTx) 220 221 if batches != nil || committers != nil { 222 t.Fatalf("Should not have created batch") 223 } 224 225 if !ok { 226 t.Fatalf("Should have enqueued good message into batch") 227 } 228 229 batches, committers, ok = r.Ordered(isolatedTx) 230 231 if !ok { 232 t.Fatalf("Should have enqueued isolated message") 233 } 234 235 if len(batches) != 2 || len(committers) != 2 { 236 t.Fatalf("Should have created two batches, got %d and %d", len(batches), len(committers)) 237 } 238 239 if len(batches[0]) != 1 || len(committers[0]) != 1 { 240 t.Fatalf("Should have had one normal tx in the first batch got %d and %d committers", len(batches[0]), len(committers[0])) 241 } 242 243 if !bytes.Equal(batches[0][0].Payload, goodTx.Payload) { 244 t.Fatalf("Should have had the normal tx in the first batch") 245 } 246 247 if len(batches[1]) != 1 || len(committers[1]) != 1 { 248 t.Fatalf("Should have had one isolated tx in the second batch got %d and %d committers", len(batches[1]), len(committers[1])) 249 } 250 251 if !bytes.Equal(batches[1][0].Payload, isolatedTx.Payload) { 252 t.Fatalf("Should have had the isolated tx in the second batch") 253 } 254 } 255 256 func TestBatchSizePreferredMaxBytesOverflow(t *testing.T) { 257 filters := getFilters() 258 259 goodTxBytes := messageSizeBytes(goodTx) 260 261 // set preferred max bytes such that 10 goodTx will not fit 262 preferredMaxBytes := goodTxBytes*10 - 1 263 264 // set message count > 9 265 maxMessageCount := uint32(20) 266 267 r := NewReceiverImpl(&mockconfigtxorderer.SharedConfig{BatchSizeVal: &ab.BatchSize{MaxMessageCount: maxMessageCount, AbsoluteMaxBytes: preferredMaxBytes * 2, PreferredMaxBytes: preferredMaxBytes}}, filters) 268 269 // enqueue 9 messages 270 for i := 0; i < 9; i++ { 271 batches, committers, ok := r.Ordered(goodTx) 272 if batches != nil || committers != nil { 273 t.Fatalf("Should not have created batch") 274 } 275 if !ok { 276 t.Fatalf("Should have enqueued message into batch") 277 } 278 } 279 280 // next message should create batch 281 batches, committers, ok := r.Ordered(goodTx) 282 283 if batches == nil || committers == nil { 284 t.Fatalf("Should have created batch") 285 } 286 287 if len(batches) != 1 || len(committers) != 1 { 288 t.Fatalf("Should have created one batch, got %d and %d", len(batches), len(committers)) 289 } 290 291 if len(batches[0]) != 9 || len(committers[0]) != 9 { 292 t.Fatalf("Should have had nine normal tx in the batch got %d and %d committers", len(batches[0]), len(committers[0])) 293 } 294 if !ok { 295 t.Fatalf("Should have enqueued the tenth message into batch") 296 } 297 298 // force a batch cut 299 messageBatch, committerBatch := r.Cut() 300 301 if messageBatch == nil || committerBatch == nil { 302 t.Fatalf("Should have created batch") 303 } 304 305 if len(messageBatch) != 1 || len(committerBatch) != 1 { 306 t.Fatalf("Should have had one tx in the batch, got %d and %d", len(batches), len(committers)) 307 } 308 309 } 310 311 func TestBatchSizePreferredMaxBytesOverflowNoPending(t *testing.T) { 312 filters := getFilters() 313 314 goodTxLargeBytes := messageSizeBytes(goodTxLarge) 315 316 // set preferred max bytes such that 1 goodTxLarge will not fit 317 preferredMaxBytes := goodTxLargeBytes - 1 318 319 // set message count > 1 320 maxMessageCount := uint32(20) 321 322 r := NewReceiverImpl(&mockconfigtxorderer.SharedConfig{BatchSizeVal: &ab.BatchSize{MaxMessageCount: maxMessageCount, AbsoluteMaxBytes: preferredMaxBytes * 3, PreferredMaxBytes: preferredMaxBytes}}, filters) 323 324 // submit large message 325 batches, committers, ok := r.Ordered(goodTxLarge) 326 327 if batches == nil || committers == nil { 328 t.Fatalf("Should have created batch") 329 } 330 331 if len(batches) != 1 || len(committers) != 1 { 332 t.Fatalf("Should have created one batch, got %d and %d", len(batches), len(committers)) 333 } 334 335 if len(batches[0]) != 1 || len(committers[0]) != 1 { 336 t.Fatalf("Should have had one normal tx in the batch got %d and %d committers", len(batches[0]), len(committers[0])) 337 } 338 if !ok { 339 t.Fatalf("Should have enqueued the message into batch") 340 } 341 342 }