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  }