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  }