github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/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  	"testing"
    22  	"time"
    23  
    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  	"github.com/hyperledger/fabric/protos/utils"
    28  
    29  	logging "github.com/op/go-logging"
    30  	"github.com/stretchr/testify/assert"
    31  	"google.golang.org/grpc"
    32  )
    33  
    34  func init() {
    35  	logging.SetLevel(logging.DEBUG, "")
    36  }
    37  
    38  var systemChain = "systemChain"
    39  
    40  type mockB struct {
    41  	grpc.ServerStream
    42  	recvChan chan *cb.Envelope
    43  	sendChan chan *ab.BroadcastResponse
    44  }
    45  
    46  func newMockB() *mockB {
    47  	return &mockB{
    48  		recvChan: make(chan *cb.Envelope),
    49  		sendChan: make(chan *ab.BroadcastResponse),
    50  	}
    51  }
    52  
    53  func (m *mockB) Send(br *ab.BroadcastResponse) error {
    54  	m.sendChan <- br
    55  	return nil
    56  }
    57  
    58  func (m *mockB) Recv() (*cb.Envelope, error) {
    59  	msg, ok := <-m.recvChan
    60  	if !ok {
    61  		return msg, fmt.Errorf("Channel closed")
    62  	}
    63  	return msg, nil
    64  }
    65  
    66  type mockSupportManager struct {
    67  	chains     map[string]*mockSupport
    68  	ProcessVal *cb.Envelope
    69  }
    70  
    71  func (mm *mockSupportManager) GetChain(chainID string) (Support, bool) {
    72  	chain, ok := mm.chains[chainID]
    73  	return chain, ok
    74  }
    75  
    76  func (mm *mockSupportManager) Process(configTx *cb.Envelope) (*cb.Envelope, error) {
    77  	if mm.ProcessVal == nil {
    78  		return nil, fmt.Errorf("Nil result implies error")
    79  	}
    80  	return mm.ProcessVal, nil
    81  }
    82  
    83  type mockSupport struct {
    84  	filters       *filter.RuleSet
    85  	rejectEnqueue bool
    86  }
    87  
    88  func (ms *mockSupport) Filters() *filter.RuleSet {
    89  	return ms.filters
    90  }
    91  
    92  // Enqueue sends a message for ordering
    93  func (ms *mockSupport) Enqueue(env *cb.Envelope) bool {
    94  	return !ms.rejectEnqueue
    95  }
    96  
    97  func makeConfigMessage(chainID string) *cb.Envelope {
    98  	payload := &cb.Payload{
    99  		Data: utils.MarshalOrPanic(&cb.ConfigEnvelope{}),
   100  		Header: &cb.Header{
   101  			ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{
   102  				ChannelId: chainID,
   103  				Type:      int32(cb.HeaderType_CONFIG_UPDATE),
   104  			}),
   105  		},
   106  	}
   107  	return &cb.Envelope{
   108  		Payload: utils.MarshalOrPanic(payload),
   109  	}
   110  }
   111  
   112  func makeMessage(chainID string, data []byte) *cb.Envelope {
   113  	payload := &cb.Payload{
   114  		Data: data,
   115  		Header: &cb.Header{
   116  			ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{
   117  				ChannelId: chainID,
   118  			}),
   119  		},
   120  	}
   121  	return &cb.Envelope{
   122  		Payload: utils.MarshalOrPanic(payload),
   123  	}
   124  }
   125  
   126  func getMockSupportManager() (*mockSupportManager, *mockSupport) {
   127  	filters := filter.NewRuleSet([]filter.Rule{
   128  		filter.EmptyRejectRule,
   129  		filter.AcceptRule,
   130  	})
   131  	mm := &mockSupportManager{
   132  		chains: make(map[string]*mockSupport),
   133  	}
   134  	mSysChain := &mockSupport{
   135  		filters: filters,
   136  	}
   137  	mm.chains[string(systemChain)] = mSysChain
   138  	return mm, mSysChain
   139  }
   140  
   141  func TestEnqueueFailure(t *testing.T) {
   142  	mm, mSysChain := getMockSupportManager()
   143  	bh := NewHandlerImpl(mm)
   144  	m := newMockB()
   145  	defer close(m.recvChan)
   146  	done := make(chan struct{})
   147  	go func() {
   148  		bh.Handle(m)
   149  		close(done)
   150  	}()
   151  
   152  	for i := 0; i < 2; i++ {
   153  		m.recvChan <- makeMessage(systemChain, []byte("Some bytes"))
   154  		reply := <-m.sendChan
   155  		if reply.Status != cb.Status_SUCCESS {
   156  			t.Fatalf("Should have successfully queued the message")
   157  		}
   158  	}
   159  
   160  	mSysChain.rejectEnqueue = true
   161  	m.recvChan <- makeMessage(systemChain, []byte("Some bytes"))
   162  	reply := <-m.sendChan
   163  	if reply.Status != cb.Status_SERVICE_UNAVAILABLE {
   164  		t.Fatalf("Should not have successfully queued the message")
   165  	}
   166  
   167  	select {
   168  	case <-done:
   169  	case <-time.After(time.Second):
   170  		t.Fatalf("Should have terminated the stream")
   171  	}
   172  }
   173  
   174  func TestEmptyEnvelope(t *testing.T) {
   175  	mm, _ := getMockSupportManager()
   176  	bh := NewHandlerImpl(mm)
   177  	m := newMockB()
   178  	defer close(m.recvChan)
   179  	done := make(chan struct{})
   180  	go func() {
   181  		bh.Handle(m)
   182  		close(done)
   183  	}()
   184  
   185  	m.recvChan <- &cb.Envelope{}
   186  	reply := <-m.sendChan
   187  	if reply.Status != cb.Status_BAD_REQUEST {
   188  		t.Fatalf("Should have rejected the null message")
   189  	}
   190  
   191  	select {
   192  	case <-done:
   193  	case <-time.After(time.Second):
   194  		t.Fatalf("Should have terminated the stream")
   195  	}
   196  }
   197  
   198  func TestBadChannelId(t *testing.T) {
   199  	mm, _ := getMockSupportManager()
   200  	bh := NewHandlerImpl(mm)
   201  	m := newMockB()
   202  	defer close(m.recvChan)
   203  	done := make(chan struct{})
   204  	go func() {
   205  		bh.Handle(m)
   206  		close(done)
   207  	}()
   208  
   209  	m.recvChan <- makeMessage("Wrong chain", []byte("Some bytes"))
   210  	reply := <-m.sendChan
   211  	if reply.Status != cb.Status_NOT_FOUND {
   212  		t.Fatalf("Should have rejected message to a chain which does not exist")
   213  	}
   214  
   215  	select {
   216  	case <-done:
   217  	case <-time.After(time.Second):
   218  		t.Fatalf("Should have terminated the stream")
   219  	}
   220  }
   221  
   222  func TestGoodConfigUpdate(t *testing.T) {
   223  	mm, _ := getMockSupportManager()
   224  	mm.ProcessVal = &cb.Envelope{Payload: utils.MarshalOrPanic(&cb.Payload{Header: &cb.Header{ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{ChannelId: systemChain})}})}
   225  	bh := NewHandlerImpl(mm)
   226  	m := newMockB()
   227  	defer close(m.recvChan)
   228  	go bh.Handle(m)
   229  	newChannelId := "New Chain"
   230  
   231  	m.recvChan <- makeConfigMessage(newChannelId)
   232  	reply := <-m.sendChan
   233  	assert.Equal(t, cb.Status_SUCCESS, reply.Status, "Should have allowed a good CONFIG_UPDATE")
   234  }
   235  
   236  func TestBadConfigUpdate(t *testing.T) {
   237  	mm, _ := getMockSupportManager()
   238  	bh := NewHandlerImpl(mm)
   239  	m := newMockB()
   240  	defer close(m.recvChan)
   241  	go bh.Handle(m)
   242  
   243  	m.recvChan <- makeConfigMessage(systemChain)
   244  	reply := <-m.sendChan
   245  	assert.NotEqual(t, cb.Status_SUCCESS, reply.Status, "Should have rejected CONFIG_UPDATE")
   246  }