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