github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/orderer/common/deliver/deliver_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 deliver
    18  
    19  import (
    20  	"fmt"
    21  	"testing"
    22  	"time"
    23  
    24  	"github.com/hyperledger/fabric/common/configtx/tool/provisional"
    25  	configvaluesapi "github.com/hyperledger/fabric/common/configvalues"
    26  	mockconfigvaluesorderer "github.com/hyperledger/fabric/common/mocks/configvalues/channel/orderer"
    27  	mockpolicies "github.com/hyperledger/fabric/common/mocks/policies"
    28  	"github.com/hyperledger/fabric/common/policies"
    29  	ordererledger "github.com/hyperledger/fabric/orderer/ledger"
    30  	ramledger "github.com/hyperledger/fabric/orderer/ledger/ram"
    31  	cb "github.com/hyperledger/fabric/protos/common"
    32  	ab "github.com/hyperledger/fabric/protos/orderer"
    33  	"github.com/hyperledger/fabric/protos/utils"
    34  	logging "github.com/op/go-logging"
    35  	"google.golang.org/grpc"
    36  )
    37  
    38  var genesisBlock = cb.NewBlock(0, nil)
    39  
    40  var systemChainID = "systemChain"
    41  
    42  const ledgerSize = 10
    43  
    44  func init() {
    45  	logging.SetLevel(logging.DEBUG, "")
    46  }
    47  
    48  type mockD struct {
    49  	grpc.ServerStream
    50  	recvChan chan *cb.Envelope
    51  	sendChan chan *ab.DeliverResponse
    52  }
    53  
    54  func newMockD() *mockD {
    55  	return &mockD{
    56  		recvChan: make(chan *cb.Envelope),
    57  		sendChan: make(chan *ab.DeliverResponse),
    58  	}
    59  }
    60  
    61  func (m *mockD) Send(br *ab.DeliverResponse) error {
    62  	m.sendChan <- br
    63  	return nil
    64  }
    65  
    66  func (m *mockD) Recv() (*cb.Envelope, error) {
    67  	msg, ok := <-m.recvChan
    68  	if !ok {
    69  		return msg, fmt.Errorf("Channel closed")
    70  	}
    71  	return msg, nil
    72  }
    73  
    74  type mockSupportManager struct {
    75  	chains map[string]*mockSupport
    76  }
    77  
    78  func (mm *mockSupportManager) GetChain(chainID string) (Support, bool) {
    79  	cs, ok := mm.chains[chainID]
    80  	return cs, ok
    81  }
    82  
    83  type mockSupport struct {
    84  	ledger        ordererledger.ReadWriter
    85  	sharedConfig  *mockconfigvaluesorderer.SharedConfig
    86  	policyManager *mockpolicies.Manager
    87  }
    88  
    89  func (mcs *mockSupport) PolicyManager() policies.Manager {
    90  	return mcs.policyManager
    91  }
    92  
    93  func (mcs *mockSupport) Reader() ordererledger.Reader {
    94  	return mcs.ledger
    95  }
    96  
    97  func NewRAMLedger() ordererledger.ReadWriter {
    98  	rlf := ramledger.New(ledgerSize + 1)
    99  	rl, _ := rlf.GetOrCreate(provisional.TestChainID)
   100  	rl.Append(genesisBlock)
   101  	return rl
   102  }
   103  
   104  func (mcs *mockSupport) SharedConfig() configvaluesapi.Orderer {
   105  	return mcs.sharedConfig
   106  }
   107  
   108  func newMockMultichainManager() *mockSupportManager {
   109  	rl := NewRAMLedger()
   110  	mm := &mockSupportManager{
   111  		chains: make(map[string]*mockSupport),
   112  	}
   113  	mm.chains[systemChainID] = &mockSupport{
   114  		ledger:        rl,
   115  		sharedConfig:  &mockconfigvaluesorderer.SharedConfig{EgressPolicyNamesVal: []string{"somePolicy"}},
   116  		policyManager: &mockpolicies.Manager{Policy: &mockpolicies.Policy{}},
   117  	}
   118  	return mm
   119  }
   120  
   121  var seekOldest = &ab.SeekPosition{Type: &ab.SeekPosition_Oldest{&ab.SeekOldest{}}}
   122  var seekNewest = &ab.SeekPosition{Type: &ab.SeekPosition_Newest{&ab.SeekNewest{}}}
   123  
   124  func seekSpecified(number uint64) *ab.SeekPosition {
   125  	return &ab.SeekPosition{Type: &ab.SeekPosition_Specified{&ab.SeekSpecified{Number: number}}}
   126  }
   127  
   128  func makeSeek(chainID string, seekInfo *ab.SeekInfo) *cb.Envelope {
   129  	return &cb.Envelope{
   130  		Payload: utils.MarshalOrPanic(&cb.Payload{
   131  			Header: &cb.Header{
   132  				ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{
   133  					ChannelId: chainID,
   134  				}),
   135  				SignatureHeader: utils.MarshalOrPanic(&cb.SignatureHeader{}),
   136  			},
   137  			Data: utils.MarshalOrPanic(seekInfo),
   138  		}),
   139  	}
   140  }
   141  
   142  func TestOldestSeek(t *testing.T) {
   143  	mm := newMockMultichainManager()
   144  	for i := 1; i < ledgerSize; i++ {
   145  		ledger := mm.chains[systemChainID].ledger
   146  		ledger.Append(ordererledger.CreateNextBlock(ledger, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", i))}}))
   147  	}
   148  
   149  	m := newMockD()
   150  	defer close(m.recvChan)
   151  	ds := NewHandlerImpl(mm)
   152  
   153  	go ds.Handle(m)
   154  
   155  	m.recvChan <- makeSeek(systemChainID, &ab.SeekInfo{Start: seekOldest, Stop: seekNewest, Behavior: ab.SeekInfo_BLOCK_UNTIL_READY})
   156  
   157  	count := uint64(0)
   158  	for {
   159  		select {
   160  		case deliverReply := <-m.sendChan:
   161  			if deliverReply.GetBlock() == nil {
   162  				if deliverReply.GetStatus() != cb.Status_SUCCESS {
   163  					t.Fatalf("Received an error on the reply channel")
   164  				}
   165  				if count != ledgerSize {
   166  					t.Fatalf("Expected %d blocks but got %d", ledgerSize, count)
   167  				}
   168  				return
   169  			} else {
   170  				if deliverReply.GetBlock().Header.Number != count {
   171  					t.Fatalf("Expected block %d but got block %d", count, deliverReply.GetBlock().Header.Number)
   172  				}
   173  			}
   174  		case <-time.After(time.Second):
   175  			t.Fatalf("Timed out waiting to get all blocks")
   176  		}
   177  		count++
   178  	}
   179  }
   180  
   181  func TestNewestSeek(t *testing.T) {
   182  	mm := newMockMultichainManager()
   183  	for i := 1; i < ledgerSize; i++ {
   184  		ledger := mm.chains[systemChainID].ledger
   185  		ledger.Append(ordererledger.CreateNextBlock(ledger, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", i))}}))
   186  	}
   187  
   188  	m := newMockD()
   189  	defer close(m.recvChan)
   190  	ds := NewHandlerImpl(mm)
   191  
   192  	go ds.Handle(m)
   193  
   194  	m.recvChan <- makeSeek(systemChainID, &ab.SeekInfo{Start: seekNewest, Stop: seekNewest, Behavior: ab.SeekInfo_BLOCK_UNTIL_READY})
   195  
   196  	select {
   197  	case deliverReply := <-m.sendChan:
   198  		if deliverReply.GetBlock() == nil {
   199  			if deliverReply.GetStatus() != cb.Status_SUCCESS {
   200  				t.Fatalf("Received an error on the reply channel")
   201  			}
   202  			return
   203  		} else {
   204  			if deliverReply.GetBlock().Header.Number != uint64(ledgerSize-1) {
   205  				t.Fatalf("Expected only the most recent block")
   206  			}
   207  		}
   208  	case <-time.After(time.Second):
   209  		t.Fatalf("Timed out waiting to get all blocks")
   210  	}
   211  }
   212  
   213  func TestSpecificSeek(t *testing.T) {
   214  	mm := newMockMultichainManager()
   215  	for i := 1; i < ledgerSize; i++ {
   216  		ledger := mm.chains[systemChainID].ledger
   217  		ledger.Append(ordererledger.CreateNextBlock(ledger, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", i))}}))
   218  	}
   219  
   220  	m := newMockD()
   221  	defer close(m.recvChan)
   222  	ds := NewHandlerImpl(mm)
   223  	specifiedStart := uint64(3)
   224  	specifiedStop := uint64(7)
   225  
   226  	go ds.Handle(m)
   227  
   228  	m.recvChan <- makeSeek(systemChainID, &ab.SeekInfo{Start: seekSpecified(specifiedStart), Stop: seekSpecified(specifiedStop), Behavior: ab.SeekInfo_BLOCK_UNTIL_READY})
   229  
   230  	count := uint64(0)
   231  	for {
   232  		select {
   233  		case deliverReply := <-m.sendChan:
   234  			if deliverReply.GetBlock() == nil {
   235  				if deliverReply.GetStatus() != cb.Status_SUCCESS {
   236  					t.Fatalf("Received an error on the reply channel")
   237  				}
   238  				return
   239  			} else {
   240  				if expected := specifiedStart + count; deliverReply.GetBlock().Header.Number != expected {
   241  					t.Fatalf("Expected block %d but got block %d", expected, deliverReply.GetBlock().Header.Number)
   242  				}
   243  			}
   244  		case <-time.After(time.Second):
   245  			t.Fatalf("Timed out waiting to get all blocks")
   246  		}
   247  		count++
   248  	}
   249  }
   250  
   251  func TestUnauthorizedSeek(t *testing.T) {
   252  	mm := newMockMultichainManager()
   253  	for i := 1; i < ledgerSize; i++ {
   254  		ledger := mm.chains[systemChainID].ledger
   255  		ledger.Append(ordererledger.CreateNextBlock(ledger, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", i))}}))
   256  	}
   257  	mm.chains[systemChainID].policyManager.Policy.Err = fmt.Errorf("Fail to evaluate policy")
   258  
   259  	m := newMockD()
   260  	defer close(m.recvChan)
   261  	ds := NewHandlerImpl(mm)
   262  
   263  	go ds.Handle(m)
   264  
   265  	m.recvChan <- makeSeek(systemChainID, &ab.SeekInfo{Start: seekSpecified(uint64(0)), Stop: seekSpecified(uint64(0)), Behavior: ab.SeekInfo_BLOCK_UNTIL_READY})
   266  
   267  	select {
   268  	case deliverReply := <-m.sendChan:
   269  		if deliverReply.GetStatus() != cb.Status_FORBIDDEN {
   270  			t.Fatalf("Received wrong error on the reply channel")
   271  		}
   272  	case <-time.After(time.Second):
   273  		t.Fatalf("Timed out waiting to get all blocks")
   274  	}
   275  }
   276  
   277  func TestBadSeek(t *testing.T) {
   278  	mm := newMockMultichainManager()
   279  	for i := 1; i < ledgerSize; i++ {
   280  		ledger := mm.chains[systemChainID].ledger
   281  		ledger.Append(ordererledger.CreateNextBlock(ledger, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", i))}}))
   282  	}
   283  
   284  	m := newMockD()
   285  	defer close(m.recvChan)
   286  	ds := NewHandlerImpl(mm)
   287  
   288  	go ds.Handle(m)
   289  
   290  	m.recvChan <- makeSeek(systemChainID, &ab.SeekInfo{Start: seekSpecified(uint64(3 * ledgerSize)), Stop: seekSpecified(uint64(3 * ledgerSize)), Behavior: ab.SeekInfo_BLOCK_UNTIL_READY})
   291  
   292  	select {
   293  	case deliverReply := <-m.sendChan:
   294  		if deliverReply.GetStatus() != cb.Status_NOT_FOUND {
   295  			t.Fatalf("Received wrong error on the reply channel")
   296  		}
   297  	case <-time.After(time.Second):
   298  		t.Fatalf("Timed out waiting to get all blocks")
   299  	}
   300  }
   301  
   302  func TestFailFastSeek(t *testing.T) {
   303  	mm := newMockMultichainManager()
   304  	for i := 1; i < ledgerSize; i++ {
   305  		ledger := mm.chains[systemChainID].ledger
   306  		ledger.Append(ordererledger.CreateNextBlock(ledger, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", i))}}))
   307  	}
   308  
   309  	m := newMockD()
   310  	defer close(m.recvChan)
   311  	ds := NewHandlerImpl(mm)
   312  
   313  	go ds.Handle(m)
   314  
   315  	m.recvChan <- makeSeek(systemChainID, &ab.SeekInfo{Start: seekSpecified(uint64(ledgerSize - 1)), Stop: seekSpecified(ledgerSize), Behavior: ab.SeekInfo_FAIL_IF_NOT_READY})
   316  
   317  	select {
   318  	case deliverReply := <-m.sendChan:
   319  		if deliverReply.GetBlock() == nil {
   320  			t.Fatalf("Expected to receive first block")
   321  		}
   322  	case <-time.After(time.Second):
   323  		t.Fatalf("Timed out waiting to get all blocks")
   324  	}
   325  
   326  	select {
   327  	case deliverReply := <-m.sendChan:
   328  		if deliverReply.GetStatus() != cb.Status_NOT_FOUND {
   329  			t.Fatalf("Expected to receive failure for second block")
   330  		}
   331  	case <-time.After(time.Second):
   332  		t.Fatalf("Timed out waiting to get all blocks")
   333  	}
   334  }
   335  
   336  func TestBlockingSeek(t *testing.T) {
   337  	mm := newMockMultichainManager()
   338  	for i := 1; i < ledgerSize; i++ {
   339  		ledger := mm.chains[systemChainID].ledger
   340  		ledger.Append(ordererledger.CreateNextBlock(ledger, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", i))}}))
   341  	}
   342  
   343  	m := newMockD()
   344  	defer close(m.recvChan)
   345  	ds := NewHandlerImpl(mm)
   346  
   347  	go ds.Handle(m)
   348  
   349  	m.recvChan <- makeSeek(systemChainID, &ab.SeekInfo{Start: seekSpecified(uint64(ledgerSize - 1)), Stop: seekSpecified(ledgerSize), Behavior: ab.SeekInfo_BLOCK_UNTIL_READY})
   350  
   351  	select {
   352  	case deliverReply := <-m.sendChan:
   353  		if deliverReply.GetBlock() == nil {
   354  			t.Fatalf("Expected to receive first block")
   355  		}
   356  	case <-time.After(time.Second):
   357  		t.Fatalf("Timed out waiting to get first block")
   358  	}
   359  
   360  	select {
   361  	case <-m.sendChan:
   362  		t.Fatalf("Should not have delivered an error or second block")
   363  	case <-time.After(50 * time.Millisecond):
   364  	}
   365  
   366  	ledger := mm.chains[systemChainID].ledger
   367  	ledger.Append(ordererledger.CreateNextBlock(ledger, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", ledgerSize+1))}}))
   368  
   369  	select {
   370  	case deliverReply := <-m.sendChan:
   371  		if deliverReply.GetBlock() == nil {
   372  			t.Fatalf("Expected to receive new block")
   373  		}
   374  	case <-time.After(time.Second):
   375  		t.Fatalf("Timed out waiting to get new block")
   376  	}
   377  
   378  	select {
   379  	case deliverReply := <-m.sendChan:
   380  		if deliverReply.GetStatus() != cb.Status_SUCCESS {
   381  			t.Fatalf("Expected delivery to complete")
   382  		}
   383  	case <-time.After(time.Second):
   384  		t.Fatalf("Timed out waiting to get all blocks")
   385  	}
   386  }