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  }