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