github.com/tenywen/fabric@v1.0.0-beta.0.20170620030522-a5b1ed380643/common/ledger/blkstorage/fsblkstorage/blockfile_mgr_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 fsblkstorage
    18  
    19  import (
    20  	"fmt"
    21  	"testing"
    22  
    23  	"github.com/golang/protobuf/proto"
    24  	"github.com/hyperledger/fabric/common/ledger/testutil"
    25  
    26  	"github.com/hyperledger/fabric/protos/common"
    27  	putil "github.com/hyperledger/fabric/protos/utils"
    28  )
    29  
    30  func TestBlockfileMgrBlockReadWrite(t *testing.T) {
    31  	env := newTestEnv(t, NewConf(testPath(), 0))
    32  	defer env.Cleanup()
    33  	blkfileMgrWrapper := newTestBlockfileWrapper(env, "testLedger")
    34  	defer blkfileMgrWrapper.close()
    35  	blocks := testutil.ConstructTestBlocks(t, 10)
    36  	blkfileMgrWrapper.addBlocks(blocks)
    37  	blkfileMgrWrapper.testGetBlockByHash(blocks)
    38  	blkfileMgrWrapper.testGetBlockByNumber(blocks, 0)
    39  }
    40  
    41  func TestBlockfileMgrCrashDuringWriting(t *testing.T) {
    42  	testBlockfileMgrCrashDuringWriting(t, 10, 2, 1000, 10)
    43  	testBlockfileMgrCrashDuringWriting(t, 10, 2, 1000, 1)
    44  	testBlockfileMgrCrashDuringWriting(t, 10, 2, 1000, 0)
    45  	testBlockfileMgrCrashDuringWriting(t, 0, 0, 1000, 10)
    46  	testBlockfileMgrCrashDuringWriting(t, 0, 5, 1000, 10)
    47  }
    48  
    49  func testBlockfileMgrCrashDuringWriting(t *testing.T, numBlocksBeforeCheckpoint int,
    50  	numBlocksAfterCheckpoint int, numLastBlockBytes int, numPartialBytesToWrite int) {
    51  	env := newTestEnv(t, NewConf(testPath(), 0))
    52  	defer env.Cleanup()
    53  	ledgerid := "testLedger"
    54  	blkfileMgrWrapper := newTestBlockfileWrapper(env, ledgerid)
    55  	bg, gb := testutil.NewBlockGenerator(t, ledgerid, false)
    56  
    57  	// create all necessary blocks
    58  	totalBlocks := numBlocksBeforeCheckpoint + numBlocksAfterCheckpoint
    59  	allBlocks := []*common.Block{gb}
    60  	allBlocks = append(allBlocks, bg.NextTestBlocks(totalBlocks+1)...)
    61  
    62  	// identify the blocks that are to be added beforeCP, afterCP, and after restart
    63  	blocksBeforeCP := []*common.Block{}
    64  	blocksAfterCP := []*common.Block{}
    65  	if numBlocksBeforeCheckpoint != 0 {
    66  		blocksBeforeCP = allBlocks[0:numBlocksBeforeCheckpoint]
    67  	}
    68  	if numBlocksAfterCheckpoint != 0 {
    69  		blocksAfterCP = allBlocks[numBlocksBeforeCheckpoint : numBlocksBeforeCheckpoint+numBlocksAfterCheckpoint]
    70  	}
    71  	blocksAfterRestart := allBlocks[numBlocksBeforeCheckpoint+numBlocksAfterCheckpoint:]
    72  
    73  	// add blocks before cp
    74  	blkfileMgrWrapper.addBlocks(blocksBeforeCP)
    75  	currentCPInfo := blkfileMgrWrapper.blockfileMgr.cpInfo
    76  	cpInfo1 := &checkpointInfo{
    77  		currentCPInfo.latestFileChunkSuffixNum,
    78  		currentCPInfo.latestFileChunksize,
    79  		currentCPInfo.isChainEmpty,
    80  		currentCPInfo.lastBlockNumber}
    81  
    82  	// add blocks after cp
    83  	blkfileMgrWrapper.addBlocks(blocksAfterCP)
    84  	cpInfo2 := blkfileMgrWrapper.blockfileMgr.cpInfo
    85  
    86  	// simulate a crash scenario
    87  	lastBlockBytes := []byte{}
    88  	encodedLen := proto.EncodeVarint(uint64(numLastBlockBytes))
    89  	randomBytes := testutil.ConstructRandomBytes(t, numLastBlockBytes)
    90  	lastBlockBytes = append(lastBlockBytes, encodedLen...)
    91  	lastBlockBytes = append(lastBlockBytes, randomBytes...)
    92  	partialBytes := lastBlockBytes[:numPartialBytesToWrite]
    93  	blkfileMgrWrapper.blockfileMgr.currentFileWriter.append(partialBytes, true)
    94  	blkfileMgrWrapper.blockfileMgr.saveCurrentInfo(cpInfo1, true)
    95  	blkfileMgrWrapper.close()
    96  
    97  	// simulate a start after a crash
    98  	blkfileMgrWrapper = newTestBlockfileWrapper(env, ledgerid)
    99  	defer blkfileMgrWrapper.close()
   100  	cpInfo3 := blkfileMgrWrapper.blockfileMgr.cpInfo
   101  	testutil.AssertEquals(t, cpInfo3, cpInfo2)
   102  
   103  	// add fresh blocks after restart
   104  	blkfileMgrWrapper.addBlocks(blocksAfterRestart)
   105  	testBlockfileMgrBlockIterator(t, blkfileMgrWrapper.blockfileMgr, 0, len(allBlocks)-1, allBlocks)
   106  }
   107  
   108  func TestBlockfileMgrBlockIterator(t *testing.T) {
   109  	env := newTestEnv(t, NewConf(testPath(), 0))
   110  	defer env.Cleanup()
   111  	blkfileMgrWrapper := newTestBlockfileWrapper(env, "testLedger")
   112  	defer blkfileMgrWrapper.close()
   113  	blocks := testutil.ConstructTestBlocks(t, 10)
   114  	blkfileMgrWrapper.addBlocks(blocks)
   115  	testBlockfileMgrBlockIterator(t, blkfileMgrWrapper.blockfileMgr, 0, 7, blocks[0:8])
   116  }
   117  
   118  func testBlockfileMgrBlockIterator(t *testing.T, blockfileMgr *blockfileMgr,
   119  	firstBlockNum int, lastBlockNum int, expectedBlocks []*common.Block) {
   120  	itr, err := blockfileMgr.retrieveBlocks(uint64(firstBlockNum))
   121  	defer itr.Close()
   122  	testutil.AssertNoError(t, err, "Error while getting blocks iterator")
   123  	numBlocksItrated := 0
   124  	for {
   125  		block, err := itr.Next()
   126  		testutil.AssertNoError(t, err, fmt.Sprintf("Error while getting block number [%d] from iterator", numBlocksItrated))
   127  		testutil.AssertEquals(t, block, expectedBlocks[numBlocksItrated])
   128  		numBlocksItrated++
   129  		if numBlocksItrated == lastBlockNum-firstBlockNum+1 {
   130  			break
   131  		}
   132  	}
   133  	testutil.AssertEquals(t, numBlocksItrated, lastBlockNum-firstBlockNum+1)
   134  }
   135  
   136  func TestBlockfileMgrBlockchainInfo(t *testing.T) {
   137  	env := newTestEnv(t, NewConf(testPath(), 0))
   138  	defer env.Cleanup()
   139  	blkfileMgrWrapper := newTestBlockfileWrapper(env, "testLedger")
   140  	defer blkfileMgrWrapper.close()
   141  
   142  	bcInfo := blkfileMgrWrapper.blockfileMgr.getBlockchainInfo()
   143  	testutil.AssertEquals(t, bcInfo, &common.BlockchainInfo{Height: 0, CurrentBlockHash: nil, PreviousBlockHash: nil})
   144  
   145  	blocks := testutil.ConstructTestBlocks(t, 10)
   146  	blkfileMgrWrapper.addBlocks(blocks)
   147  	bcInfo = blkfileMgrWrapper.blockfileMgr.getBlockchainInfo()
   148  	testutil.AssertEquals(t, bcInfo.Height, uint64(10))
   149  }
   150  
   151  func TestBlockfileMgrGetTxById(t *testing.T) {
   152  	env := newTestEnv(t, NewConf(testPath(), 0))
   153  	defer env.Cleanup()
   154  	blkfileMgrWrapper := newTestBlockfileWrapper(env, "testLedger")
   155  	defer blkfileMgrWrapper.close()
   156  	blocks := testutil.ConstructTestBlocks(t, 2)
   157  	blkfileMgrWrapper.addBlocks(blocks)
   158  	for _, blk := range blocks {
   159  		for j, txEnvelopeBytes := range blk.Data.Data {
   160  			// blockNum starts with 0
   161  			txID, err := extractTxID(blk.Data.Data[j])
   162  			testutil.AssertNoError(t, err, "")
   163  			txEnvelopeFromFileMgr, err := blkfileMgrWrapper.blockfileMgr.retrieveTransactionByID(txID)
   164  			testutil.AssertNoError(t, err, "Error while retrieving tx from blkfileMgr")
   165  			txEnvelope, err := putil.GetEnvelopeFromBlock(txEnvelopeBytes)
   166  			testutil.AssertNoError(t, err, "Error while unmarshalling tx")
   167  			testutil.AssertEquals(t, txEnvelopeFromFileMgr, txEnvelope)
   168  		}
   169  	}
   170  }
   171  
   172  func TestBlockfileMgrGetTxByBlockNumTranNum(t *testing.T) {
   173  	env := newTestEnv(t, NewConf(testPath(), 0))
   174  	defer env.Cleanup()
   175  	blkfileMgrWrapper := newTestBlockfileWrapper(env, "testLedger")
   176  	defer blkfileMgrWrapper.close()
   177  	blocks := testutil.ConstructTestBlocks(t, 10)
   178  	blkfileMgrWrapper.addBlocks(blocks)
   179  	for blockIndex, blk := range blocks {
   180  		for tranIndex, txEnvelopeBytes := range blk.Data.Data {
   181  			// blockNum and tranNum both start with 0
   182  			txEnvelopeFromFileMgr, err := blkfileMgrWrapper.blockfileMgr.retrieveTransactionByBlockNumTranNum(uint64(blockIndex), uint64(tranIndex))
   183  			testutil.AssertNoError(t, err, "Error while retrieving tx from blkfileMgr")
   184  			txEnvelope, err := putil.GetEnvelopeFromBlock(txEnvelopeBytes)
   185  			testutil.AssertNoError(t, err, "Error while unmarshalling tx")
   186  			testutil.AssertEquals(t, txEnvelopeFromFileMgr, txEnvelope)
   187  		}
   188  	}
   189  }
   190  
   191  func TestBlockfileMgrRestart(t *testing.T) {
   192  	env := newTestEnv(t, NewConf(testPath(), 0))
   193  	defer env.Cleanup()
   194  	ledgerid := "testLedger"
   195  	blkfileMgrWrapper := newTestBlockfileWrapper(env, ledgerid)
   196  	blocks := testutil.ConstructTestBlocks(t, 10)
   197  	blkfileMgrWrapper.addBlocks(blocks)
   198  	expectedHeight := uint64(10)
   199  	testutil.AssertEquals(t, blkfileMgrWrapper.blockfileMgr.getBlockchainInfo().Height, expectedHeight)
   200  	blkfileMgrWrapper.close()
   201  
   202  	blkfileMgrWrapper = newTestBlockfileWrapper(env, ledgerid)
   203  	defer blkfileMgrWrapper.close()
   204  	testutil.AssertEquals(t, int(blkfileMgrWrapper.blockfileMgr.cpInfo.lastBlockNumber), 9)
   205  	blkfileMgrWrapper.testGetBlockByHash(blocks)
   206  	testutil.AssertEquals(t, blkfileMgrWrapper.blockfileMgr.getBlockchainInfo().Height, expectedHeight)
   207  }
   208  
   209  func TestBlockfileMgrFileRolling(t *testing.T) {
   210  	blocks := testutil.ConstructTestBlocks(t, 200)
   211  	size := 0
   212  	for _, block := range blocks[:100] {
   213  		by, _, err := serializeBlock(block)
   214  		testutil.AssertNoError(t, err, "Error while serializing block")
   215  		blockBytesSize := len(by)
   216  		encodedLen := proto.EncodeVarint(uint64(blockBytesSize))
   217  		size += blockBytesSize + len(encodedLen)
   218  	}
   219  
   220  	maxFileSie := int(0.75 * float64(size))
   221  	env := newTestEnv(t, NewConf(testPath(), maxFileSie))
   222  	defer env.Cleanup()
   223  	ledgerid := "testLedger"
   224  	blkfileMgrWrapper := newTestBlockfileWrapper(env, ledgerid)
   225  	blkfileMgrWrapper.addBlocks(blocks[:100])
   226  	testutil.AssertEquals(t, blkfileMgrWrapper.blockfileMgr.cpInfo.latestFileChunkSuffixNum, 1)
   227  	blkfileMgrWrapper.testGetBlockByHash(blocks[:100])
   228  	blkfileMgrWrapper.close()
   229  
   230  	blkfileMgrWrapper = newTestBlockfileWrapper(env, ledgerid)
   231  	defer blkfileMgrWrapper.close()
   232  	blkfileMgrWrapper.addBlocks(blocks[100:])
   233  	testutil.AssertEquals(t, blkfileMgrWrapper.blockfileMgr.cpInfo.latestFileChunkSuffixNum, 2)
   234  	blkfileMgrWrapper.testGetBlockByHash(blocks[100:])
   235  }
   236  
   237  func TestBlockfileMgrGetBlockByTxID(t *testing.T) {
   238  	env := newTestEnv(t, NewConf(testPath(), 0))
   239  	defer env.Cleanup()
   240  	blkfileMgrWrapper := newTestBlockfileWrapper(env, "testLedger")
   241  	defer blkfileMgrWrapper.close()
   242  	blocks := testutil.ConstructTestBlocks(t, 10)
   243  	blkfileMgrWrapper.addBlocks(blocks)
   244  	for _, blk := range blocks {
   245  		for j := range blk.Data.Data {
   246  			// blockNum starts with 1
   247  			txID, err := extractTxID(blk.Data.Data[j])
   248  			testutil.AssertNoError(t, err, "")
   249  
   250  			blockFromFileMgr, err := blkfileMgrWrapper.blockfileMgr.retrieveBlockByTxID(txID)
   251  			testutil.AssertNoError(t, err, "Error while retrieving block from blkfileMgr")
   252  			testutil.AssertEquals(t, blockFromFileMgr, blk)
   253  		}
   254  	}
   255  }