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