github.com/darrenli6/fabric-sdk-example@v0.0.0-20220109053535-94b13b56df8c/orderer/ledger/ram/impl_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 ramledger
    18  
    19  import (
    20  	"testing"
    21  
    22  	"github.com/hyperledger/fabric/common/configtx/tool/provisional"
    23  	"github.com/hyperledger/fabric/orderer/ledger"
    24  	cb "github.com/hyperledger/fabric/protos/common"
    25  	ab "github.com/hyperledger/fabric/protos/orderer"
    26  
    27  	logging "github.com/op/go-logging"
    28  )
    29  
    30  var genesisBlock = cb.NewBlock(0, nil)
    31  
    32  func init() {
    33  	logging.SetLevel(logging.DEBUG, "")
    34  }
    35  
    36  func newTestChain(maxSize int) *ramLedger {
    37  	rlf := New(maxSize)
    38  	chain, err := rlf.GetOrCreate(provisional.TestChainID)
    39  	if err != nil {
    40  		panic(err)
    41  	}
    42  	chain.Append(genesisBlock)
    43  	return chain.(*ramLedger)
    44  }
    45  
    46  // TestAppend ensures that appending blocks stores only the maxSize most recent blocks
    47  // Note that 'only' is applicable because the genesis block will be discarded
    48  func TestAppend(t *testing.T) {
    49  	maxSize := 3
    50  	rl := newTestChain(maxSize)
    51  	var blocks []*cb.Block
    52  	for i := 0; i < 3; i++ {
    53  		blocks = append(blocks, &cb.Block{Header: &cb.BlockHeader{Number: uint64(i + 1)}})
    54  		rl.appendBlock(blocks[i])
    55  	}
    56  	item := rl.oldest
    57  	for i := 0; i < 3; i++ {
    58  		if item.block == nil {
    59  			t.Fatalf("Block for item %d should not be nil", i)
    60  		}
    61  		if item.block.Header.Number != blocks[i].Header.Number {
    62  			t.Errorf("Expected block %d to be %d but got %d", i, blocks[i].Header.Number, item.block.Header.Number)
    63  		}
    64  		if i != 2 && item.next == nil {
    65  			t.Fatalf("Next item should not be nil")
    66  		} else {
    67  			item = item.next
    68  		}
    69  	}
    70  }
    71  
    72  // TestSignal checks if the signal channel closes when an item is appended
    73  func TestSignal(t *testing.T) {
    74  	maxSize := 3
    75  	rl := newTestChain(maxSize)
    76  	item := rl.newest
    77  	select {
    78  	case <-item.signal:
    79  		t.Fatalf("There is no successor, there should be no signal to continue")
    80  	default:
    81  	}
    82  	rl.appendBlock(&cb.Block{Header: &cb.BlockHeader{Number: 1}})
    83  	select {
    84  	case <-item.signal:
    85  	default:
    86  		t.Fatalf("There is a successor, there should be a signal to continue")
    87  	}
    88  }
    89  
    90  // TestTruncatingSafety is intended to simulate a reader who fetches a reference to the oldest list item
    91  // which is then pushed off the history by appending greater than the history size (here, 10 appends with
    92  // a maxSize of 3).  We let the go garbage collector ensure the references still exist
    93  func TestTruncationSafety(t *testing.T) {
    94  	maxSize := 3
    95  	newBlocks := 10
    96  	rl := newTestChain(maxSize)
    97  	item := rl.newest
    98  	for i := 0; i < newBlocks; i++ {
    99  		rl.appendBlock(&cb.Block{Header: &cb.BlockHeader{Number: uint64(i + 1)}})
   100  	}
   101  	count := 0
   102  	for item.next != nil {
   103  		item = item.next
   104  		count++
   105  	}
   106  
   107  	if count != newBlocks {
   108  		t.Fatalf("The iterator should have found %d new blocks but found %d", newBlocks, count)
   109  	}
   110  }
   111  
   112  func TestRetrieval(t *testing.T) {
   113  	rl := newTestChain(3)
   114  	rl.Append(ledger.CreateNextBlock(rl, []*cb.Envelope{&cb.Envelope{Payload: []byte("My Data")}}))
   115  	it, num := rl.Iterator(&ab.SeekPosition{Type: &ab.SeekPosition_Oldest{}})
   116  	if num != 0 {
   117  		t.Fatalf("Expected genesis block iterator, but got %d", num)
   118  	}
   119  	signal := it.ReadyChan()
   120  	select {
   121  	case <-signal:
   122  	default:
   123  		t.Fatalf("Should be ready for block read")
   124  	}
   125  	block, status := it.Next()
   126  	if status != cb.Status_SUCCESS {
   127  		t.Fatalf("Expected to successfully read the genesis block")
   128  	}
   129  	if block.Header.Number != 0 {
   130  		t.Fatalf("Expected to successfully retrieve the genesis block")
   131  	}
   132  	signal = it.ReadyChan()
   133  	select {
   134  	case <-signal:
   135  	default:
   136  		t.Fatalf("Should still be ready for block read")
   137  	}
   138  	block, status = it.Next()
   139  	if status != cb.Status_SUCCESS {
   140  		t.Fatalf("Expected to successfully read the second block")
   141  	}
   142  	if block.Header.Number != 1 {
   143  		t.Fatalf("Expected to successfully retrieve the second block but got block number %d", block.Header.Number)
   144  	}
   145  }
   146  
   147  func TestBlockedRetrieval(t *testing.T) {
   148  	rl := newTestChain(3)
   149  	it, num := rl.Iterator(&ab.SeekPosition{Type: &ab.SeekPosition_Specified{Specified: &ab.SeekSpecified{Number: 1}}})
   150  	if num != 1 {
   151  		t.Fatalf("Expected block iterator at 1, but got %d", num)
   152  	}
   153  	signal := it.ReadyChan()
   154  	select {
   155  	case <-signal:
   156  		t.Fatalf("Should not be ready for block read")
   157  	default:
   158  	}
   159  	rl.Append(ledger.CreateNextBlock(rl, []*cb.Envelope{&cb.Envelope{Payload: []byte("My Data")}}))
   160  	select {
   161  	case <-signal:
   162  	default:
   163  		t.Fatalf("Should now be ready for block read")
   164  	}
   165  	block, status := it.Next()
   166  	if status != cb.Status_SUCCESS {
   167  		t.Fatalf("Expected to successfully read the second block")
   168  	}
   169  	if block.Header.Number != 1 {
   170  		t.Fatalf("Expected to successfully retrieve the second block")
   171  	}
   172  }
   173  
   174  func TestIteratorPastEnd(t *testing.T) {
   175  	rl := newTestChain(3)
   176  	it, _ := rl.Iterator(&ab.SeekPosition{Type: &ab.SeekPosition_Specified{Specified: &ab.SeekSpecified{Number: 2}}})
   177  	if _, status := it.Next(); status != cb.Status_NOT_FOUND {
   178  		t.Fatalf("Expected block with status NOT_FOUND, but got %d", status)
   179  	}
   180  }
   181  
   182  func TestIteratorOldest(t *testing.T) {
   183  	rl := newTestChain(3)
   184  	// add enough block to roll off the genesis block
   185  	rl.Append(ledger.CreateNextBlock(rl, []*cb.Envelope{&cb.Envelope{Payload: []byte("My Data")}}))
   186  	rl.Append(ledger.CreateNextBlock(rl, []*cb.Envelope{&cb.Envelope{Payload: []byte("My Data")}}))
   187  	rl.Append(ledger.CreateNextBlock(rl, []*cb.Envelope{&cb.Envelope{Payload: []byte("My Data")}}))
   188  	_, num := rl.Iterator(&ab.SeekPosition{Type: &ab.SeekPosition_Specified{Specified: &ab.SeekSpecified{Number: 1}}})
   189  	if num != 1 {
   190  		t.Fatalf("Expected block iterator at 1, but got %d", num)
   191  	}
   192  }
   193  
   194  func TestAppendBadBLock(t *testing.T) {
   195  	rl := newTestChain(3)
   196  	t.Run("BadBlockNumber", func(t *testing.T) {
   197  		nextBlock := ledger.CreateNextBlock(rl, []*cb.Envelope{&cb.Envelope{Payload: []byte("My Data")}})
   198  		nextBlock.Header.Number = nextBlock.Header.Number + 1
   199  		if err := rl.Append(nextBlock); err == nil {
   200  			t.Fatalf("Expected Append to fail.")
   201  		}
   202  	})
   203  	t.Run("BadPreviousHash", func(t *testing.T) {
   204  		nextBlock := ledger.CreateNextBlock(rl, []*cb.Envelope{&cb.Envelope{Payload: []byte("My Data")}})
   205  		nextBlock.Header.PreviousHash = []byte("bad hash")
   206  		if err := rl.Append(nextBlock); err == nil {
   207  			t.Fatalf("Expected Append to fail.")
   208  		}
   209  	})
   210  }