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 }