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 }