github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/orderer/common/broadcast/broadcast_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 broadcast
    18  
    19  import (
    20  	"fmt"
    21  	"io"
    22  	"testing"
    23  	"time"
    24  
    25  	"github.com/hyperledger/fabric/orderer/common/filter"
    26  	cb "github.com/hyperledger/fabric/protos/common"
    27  	ab "github.com/hyperledger/fabric/protos/orderer"
    28  	"github.com/hyperledger/fabric/protos/utils"
    29  
    30  	logging "github.com/op/go-logging"
    31  	"github.com/stretchr/testify/assert"
    32  	"google.golang.org/grpc"
    33  )
    34  
    35  func init() {
    36  	logging.SetLevel(logging.DEBUG, "")
    37  }
    38  
    39  var systemChain = "systemChain"
    40  
    41  type mockB struct {
    42  	grpc.ServerStream
    43  	recvChan chan *cb.Envelope
    44  	sendChan chan *ab.BroadcastResponse
    45  }
    46  
    47  func newMockB() *mockB {
    48  	return &mockB{
    49  		recvChan: make(chan *cb.Envelope),
    50  		sendChan: make(chan *ab.BroadcastResponse),
    51  	}
    52  }
    53  
    54  func (m *mockB) Send(br *ab.BroadcastResponse) error {
    55  	m.sendChan <- br
    56  	return nil
    57  }
    58  
    59  func (m *mockB) Recv() (*cb.Envelope, error) {
    60  	msg, ok := <-m.recvChan
    61  	if !ok {
    62  		return msg, io.EOF
    63  	}
    64  	return msg, nil
    65  }
    66  
    67  type erroneousRecvMockB struct {
    68  	grpc.ServerStream
    69  }
    70  
    71  func (m *erroneousRecvMockB) Send(br *ab.BroadcastResponse) error {
    72  	return nil
    73  }
    74  
    75  func (m *erroneousRecvMockB) Recv() (*cb.Envelope, error) {
    76  	// The point here is to simulate an error other than EOF.
    77  	// We don't bother to create a new custom error type.
    78  	return nil, io.ErrUnexpectedEOF
    79  }
    80  
    81  type erroneousSendMockB struct {
    82  	grpc.ServerStream
    83  	recvVal *cb.Envelope
    84  }
    85  
    86  func (m *erroneousSendMockB) Send(br *ab.BroadcastResponse) error {
    87  	// The point here is to simulate an error other than EOF.
    88  	// We don't bother to create a new custom error type.
    89  	return io.ErrUnexpectedEOF
    90  }
    91  
    92  func (m *erroneousSendMockB) Recv() (*cb.Envelope, error) {
    93  	return m.recvVal, nil
    94  }
    95  
    96  var RejectRule = filter.Rule(rejectRule{})
    97  
    98  type rejectRule struct{}
    99  
   100  func (r rejectRule) Apply(message *cb.Envelope) (filter.Action, filter.Committer) {
   101  	return filter.Reject, nil
   102  }
   103  
   104  type mockSupportManager struct {
   105  	chains     map[string]*mockSupport
   106  	ProcessVal *cb.Envelope
   107  }
   108  
   109  func (mm *mockSupportManager) GetChain(chainID string) (Support, bool) {
   110  	chain, ok := mm.chains[chainID]
   111  	return chain, ok
   112  }
   113  
   114  func (mm *mockSupportManager) Process(configTx *cb.Envelope) (*cb.Envelope, error) {
   115  	if mm.ProcessVal == nil {
   116  		return nil, fmt.Errorf("Nil result implies error")
   117  	}
   118  	return mm.ProcessVal, nil
   119  }
   120  
   121  type mockSupport struct {
   122  	filters       *filter.RuleSet
   123  	rejectEnqueue bool
   124  }
   125  
   126  func (ms *mockSupport) Filters() *filter.RuleSet {
   127  	return ms.filters
   128  }
   129  
   130  // Enqueue sends a message for ordering
   131  func (ms *mockSupport) Enqueue(env *cb.Envelope) bool {
   132  	return !ms.rejectEnqueue
   133  }
   134  
   135  func makeConfigMessage(chainID string) *cb.Envelope {
   136  	payload := &cb.Payload{
   137  		Data: utils.MarshalOrPanic(&cb.ConfigEnvelope{}),
   138  		Header: &cb.Header{
   139  			ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{
   140  				ChannelId: chainID,
   141  				Type:      int32(cb.HeaderType_CONFIG_UPDATE),
   142  			}),
   143  		},
   144  	}
   145  	return &cb.Envelope{
   146  		Payload: utils.MarshalOrPanic(payload),
   147  	}
   148  }
   149  
   150  func makeMessage(chainID string, data []byte) *cb.Envelope {
   151  	payload := &cb.Payload{
   152  		Data: data,
   153  		Header: &cb.Header{
   154  			ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{
   155  				ChannelId: chainID,
   156  			}),
   157  		},
   158  	}
   159  	return &cb.Envelope{
   160  		Payload: utils.MarshalOrPanic(payload),
   161  	}
   162  }
   163  
   164  func getMockSupportManager() (*mockSupportManager, *mockSupport) {
   165  	filters := filter.NewRuleSet([]filter.Rule{
   166  		filter.EmptyRejectRule,
   167  		filter.AcceptRule,
   168  	})
   169  	mm := &mockSupportManager{
   170  		chains: make(map[string]*mockSupport),
   171  	}
   172  	mSysChain := &mockSupport{
   173  		filters: filters,
   174  	}
   175  	mm.chains[string(systemChain)] = mSysChain
   176  	return mm, mSysChain
   177  }
   178  
   179  func TestEnqueueFailure(t *testing.T) {
   180  	mm, mSysChain := getMockSupportManager()
   181  	bh := NewHandlerImpl(mm)
   182  	m := newMockB()
   183  	defer close(m.recvChan)
   184  	done := make(chan struct{})
   185  	go func() {
   186  		bh.Handle(m)
   187  		close(done)
   188  	}()
   189  
   190  	for i := 0; i < 2; i++ {
   191  		m.recvChan <- makeMessage(systemChain, []byte("Some bytes"))
   192  		reply := <-m.sendChan
   193  		if reply.Status != cb.Status_SUCCESS {
   194  			t.Fatalf("Should have successfully queued the message")
   195  		}
   196  	}
   197  
   198  	mSysChain.rejectEnqueue = true
   199  	m.recvChan <- makeMessage(systemChain, []byte("Some bytes"))
   200  	reply := <-m.sendChan
   201  	if reply.Status != cb.Status_SERVICE_UNAVAILABLE {
   202  		t.Fatalf("Should not have successfully queued the message")
   203  	}
   204  
   205  	select {
   206  	case <-done:
   207  	case <-time.After(time.Second):
   208  		t.Fatalf("Should have terminated the stream")
   209  	}
   210  }
   211  
   212  func TestEmptyEnvelope(t *testing.T) {
   213  	mm, _ := getMockSupportManager()
   214  	bh := NewHandlerImpl(mm)
   215  	m := newMockB()
   216  	defer close(m.recvChan)
   217  	done := make(chan struct{})
   218  	go func() {
   219  		bh.Handle(m)
   220  		close(done)
   221  	}()
   222  
   223  	m.recvChan <- &cb.Envelope{}
   224  	reply := <-m.sendChan
   225  	if reply.Status != cb.Status_BAD_REQUEST {
   226  		t.Fatalf("Should have rejected the null message")
   227  	}
   228  
   229  	select {
   230  	case <-done:
   231  	case <-time.After(time.Second):
   232  		t.Fatalf("Should have terminated the stream")
   233  	}
   234  }
   235  
   236  func TestBadChannelId(t *testing.T) {
   237  	mm, _ := getMockSupportManager()
   238  	bh := NewHandlerImpl(mm)
   239  	m := newMockB()
   240  	defer close(m.recvChan)
   241  	done := make(chan struct{})
   242  	go func() {
   243  		bh.Handle(m)
   244  		close(done)
   245  	}()
   246  
   247  	m.recvChan <- makeMessage("Wrong chain", []byte("Some bytes"))
   248  	reply := <-m.sendChan
   249  	if reply.Status != cb.Status_NOT_FOUND {
   250  		t.Fatalf("Should have rejected message to a chain which does not exist")
   251  	}
   252  
   253  	select {
   254  	case <-done:
   255  	case <-time.After(time.Second):
   256  		t.Fatalf("Should have terminated the stream")
   257  	}
   258  }
   259  
   260  func TestGoodConfigUpdate(t *testing.T) {
   261  	mm, _ := getMockSupportManager()
   262  	mm.ProcessVal = &cb.Envelope{Payload: utils.MarshalOrPanic(&cb.Payload{Header: &cb.Header{ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{ChannelId: systemChain})}})}
   263  	bh := NewHandlerImpl(mm)
   264  	m := newMockB()
   265  	defer close(m.recvChan)
   266  	go bh.Handle(m)
   267  	newChannelId := "New Chain"
   268  
   269  	m.recvChan <- makeConfigMessage(newChannelId)
   270  	reply := <-m.sendChan
   271  	assert.Equal(t, cb.Status_SUCCESS, reply.Status, "Should have allowed a good CONFIG_UPDATE")
   272  }
   273  
   274  func TestBadConfigUpdate(t *testing.T) {
   275  	mm, _ := getMockSupportManager()
   276  	bh := NewHandlerImpl(mm)
   277  	m := newMockB()
   278  	defer close(m.recvChan)
   279  	go bh.Handle(m)
   280  
   281  	m.recvChan <- makeConfigMessage(systemChain)
   282  	reply := <-m.sendChan
   283  	assert.NotEqual(t, cb.Status_SUCCESS, reply.Status, "Should have rejected CONFIG_UPDATE")
   284  }
   285  
   286  func TestGracefulShutdown(t *testing.T) {
   287  	bh := NewHandlerImpl(nil)
   288  	m := newMockB()
   289  	close(m.recvChan)
   290  	assert.NoError(t, bh.Handle(m), "Should exit normally upon EOF")
   291  }
   292  
   293  func TestRejected(t *testing.T) {
   294  	filters := filter.NewRuleSet([]filter.Rule{RejectRule})
   295  	mm := &mockSupportManager{
   296  		chains: map[string]*mockSupport{string(systemChain): {filters: filters}},
   297  	}
   298  	mm.ProcessVal = &cb.Envelope{Payload: utils.MarshalOrPanic(&cb.Payload{Header: &cb.Header{ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{ChannelId: systemChain})}})}
   299  	bh := NewHandlerImpl(mm)
   300  	m := newMockB()
   301  	defer close(m.recvChan)
   302  	go bh.Handle(m)
   303  
   304  	newChannelId := "New Chain"
   305  
   306  	m.recvChan <- makeConfigMessage(newChannelId)
   307  	reply := <-m.sendChan
   308  	assert.Equal(t, cb.Status_BAD_REQUEST, reply.Status, "Should have rejected CONFIG_UPDATE")
   309  }
   310  
   311  func TestBadStreamRecv(t *testing.T) {
   312  	bh := NewHandlerImpl(nil)
   313  	assert.Error(t, bh.Handle(&erroneousRecvMockB{}), "Should catch unexpected stream error")
   314  }
   315  
   316  func TestBadStreamSend(t *testing.T) {
   317  	mm, _ := getMockSupportManager()
   318  	mm.ProcessVal = &cb.Envelope{Payload: utils.MarshalOrPanic(&cb.Payload{Header: &cb.Header{ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{ChannelId: systemChain})}})}
   319  	bh := NewHandlerImpl(mm)
   320  	m := &erroneousSendMockB{recvVal: makeConfigMessage("New Chain")}
   321  	assert.Error(t, bh.Handle(m), "Should catch unexpected stream error")
   322  }
   323  
   324  func TestMalformedEnvelope(t *testing.T) {
   325  	mm, _ := getMockSupportManager()
   326  	bh := NewHandlerImpl(mm)
   327  	m := newMockB()
   328  	defer close(m.recvChan)
   329  	go bh.Handle(m)
   330  
   331  	m.recvChan <- &cb.Envelope{Payload: []byte("foo")}
   332  	reply := <-m.sendChan
   333  	assert.Equal(t, cb.Status_BAD_REQUEST, reply.Status, "Should have rejected the malformed message")
   334  }
   335  
   336  func TestMissingHeader(t *testing.T) {
   337  	mm, _ := getMockSupportManager()
   338  	bh := NewHandlerImpl(mm)
   339  	m := newMockB()
   340  	defer close(m.recvChan)
   341  	go bh.Handle(m)
   342  
   343  	m.recvChan <- &cb.Envelope{Payload: utils.MarshalOrPanic(&cb.Payload{})}
   344  	reply := <-m.sendChan
   345  	assert.Equal(t, cb.Status_BAD_REQUEST, reply.Status, "Should have rejected the payload without header")
   346  }
   347  
   348  func TestBadChannelHeader(t *testing.T) {
   349  	mm, _ := getMockSupportManager()
   350  	bh := NewHandlerImpl(mm)
   351  	m := newMockB()
   352  	defer close(m.recvChan)
   353  	go bh.Handle(m)
   354  
   355  	m.recvChan <- &cb.Envelope{Payload: utils.MarshalOrPanic(&cb.Payload{Header: &cb.Header{ChannelHeader: []byte("foo")}})}
   356  	reply := <-m.sendChan
   357  	assert.Equal(t, cb.Status_BAD_REQUEST, reply.Status, "Should have rejected bad header")
   358  }
   359  
   360  func TestBadPayloadAfterProcessing(t *testing.T) {
   361  	mm, _ := getMockSupportManager()
   362  	mm.ProcessVal = &cb.Envelope{Payload: []byte("foo")}
   363  	bh := NewHandlerImpl(mm)
   364  	m := newMockB()
   365  	defer close(m.recvChan)
   366  	go bh.Handle(m)
   367  
   368  	m.recvChan <- makeConfigMessage("New Chain")
   369  	reply := <-m.sendChan
   370  	assert.Equal(t, cb.Status_INTERNAL_SERVER_ERROR, reply.Status, "Should respond with internal server error")
   371  }
   372  
   373  func TestNilHeaderAfterProcessing(t *testing.T) {
   374  	mm, _ := getMockSupportManager()
   375  	mm.ProcessVal = &cb.Envelope{Payload: utils.MarshalOrPanic(&cb.Payload{})}
   376  	bh := NewHandlerImpl(mm)
   377  	m := newMockB()
   378  	defer close(m.recvChan)
   379  	go bh.Handle(m)
   380  
   381  	m.recvChan <- makeConfigMessage("New Chain")
   382  	reply := <-m.sendChan
   383  	assert.Equal(t, cb.Status_INTERNAL_SERVER_ERROR, reply.Status, "Should respond with internal server error")
   384  }
   385  
   386  func TestBadChannelHeaderAfterProcessing(t *testing.T) {
   387  	mm, _ := getMockSupportManager()
   388  	mm.ProcessVal = &cb.Envelope{Payload: utils.MarshalOrPanic(&cb.Payload{Header: &cb.Header{ChannelHeader: []byte("foo")}})}
   389  	bh := NewHandlerImpl(mm)
   390  	m := newMockB()
   391  	defer close(m.recvChan)
   392  	go bh.Handle(m)
   393  
   394  	m.recvChan <- makeConfigMessage("New Chain")
   395  	reply := <-m.sendChan
   396  	assert.Equal(t, cb.Status_INTERNAL_SERVER_ERROR, reply.Status, "Should respond with internal server error")
   397  }
   398  
   399  func TestEmptyChannelIDAfterProcessing(t *testing.T) {
   400  	mm, _ := getMockSupportManager()
   401  	mm.ProcessVal = &cb.Envelope{Payload: utils.MarshalOrPanic(&cb.Payload{Header: &cb.Header{ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{})}})}
   402  	bh := NewHandlerImpl(mm)
   403  	m := newMockB()
   404  	defer close(m.recvChan)
   405  	go bh.Handle(m)
   406  
   407  	m.recvChan <- makeConfigMessage("New Chain")
   408  	reply := <-m.sendChan
   409  	assert.Equal(t, cb.Status_INTERNAL_SERVER_ERROR, reply.Status, "Should respond with internal server error")
   410  }