github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/common/ledger/blkstorage/blockfile_helper_test.go (about) 1 /* 2 Copyright hechain. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package blkstorage 8 9 import ( 10 "fmt" 11 "io/ioutil" 12 "os" 13 "path/filepath" 14 "testing" 15 16 "github.com/golang/protobuf/proto" 17 "github.com/hechain20/hechain/common/ledger/testutil" 18 "github.com/stretchr/testify/require" 19 ) 20 21 func TestConstructBlockfilesInfo(t *testing.T) { 22 ledgerid := "testLedger" 23 conf := NewConf(testPath(), 0) 24 blkStoreDir := conf.getLedgerBlockDir(ledgerid) 25 env := newTestEnv(t, conf) 26 require.NoError(t, os.MkdirAll(blkStoreDir, 0o755)) 27 defer env.Cleanup() 28 29 // constructBlockfilesInfo on an empty block folder should return blockfileInfo with noBlockFiles: true 30 blkfilesInfo, err := constructBlockfilesInfo(blkStoreDir) 31 require.NoError(t, err) 32 require.Equal(t, 33 &blockfilesInfo{ 34 noBlockFiles: true, 35 lastPersistedBlock: 0, 36 latestFileSize: 0, 37 latestFileNumber: 0, 38 }, 39 blkfilesInfo, 40 ) 41 42 w := newTestBlockfileWrapper(env, ledgerid) 43 defer w.close() 44 blockfileMgr := w.blockfileMgr 45 bg, gb := testutil.NewBlockGenerator(t, ledgerid, false) 46 47 // Add a few blocks and verify that blockfilesInfo derived from filesystem should be same as from the blockfile manager 48 blockfileMgr.addBlock(gb) 49 for _, blk := range bg.NextTestBlocks(3) { 50 blockfileMgr.addBlock(blk) 51 } 52 checkBlockfilesInfoFromFS(t, blkStoreDir, blockfileMgr.blockfilesInfo) 53 54 // Move the chain to new file and check blockfilesInfo derived from file system 55 blockfileMgr.moveToNextFile() 56 checkBlockfilesInfoFromFS(t, blkStoreDir, blockfileMgr.blockfilesInfo) 57 58 // Add a few blocks that would go to new file and verify that blockfilesInfo derived from filesystem should be same as from the blockfile manager 59 for _, blk := range bg.NextTestBlocks(3) { 60 blockfileMgr.addBlock(blk) 61 } 62 checkBlockfilesInfoFromFS(t, blkStoreDir, blockfileMgr.blockfilesInfo) 63 64 // Write a partial block (to simulate a crash) and verify that blockfilesInfo derived from filesystem should be same as from the blockfile manager 65 lastTestBlk := bg.NextTestBlocks(1)[0] 66 blockBytes, _, err := serializeBlock(lastTestBlk) 67 require.NoError(t, err) 68 partialByte := append(proto.EncodeVarint(uint64(len(blockBytes))), blockBytes[len(blockBytes)/2:]...) 69 blockfileMgr.currentFileWriter.append(partialByte, true) 70 checkBlockfilesInfoFromFS(t, blkStoreDir, blockfileMgr.blockfilesInfo) 71 72 // Close the block storage, drop the index and restart and verify 73 blkfilesInfoBeforeClose := blockfileMgr.blockfilesInfo 74 w.close() 75 env.provider.Close() 76 indexFolder := conf.getIndexDir() 77 require.NoError(t, os.RemoveAll(indexFolder)) 78 79 env = newTestEnv(t, conf) 80 w = newTestBlockfileWrapper(env, ledgerid) 81 blockfileMgr = w.blockfileMgr 82 require.Equal(t, blkfilesInfoBeforeClose, blockfileMgr.blockfilesInfo) 83 84 lastBlkIndexed, err := blockfileMgr.index.getLastBlockIndexed() 85 require.NoError(t, err) 86 require.Equal(t, uint64(6), lastBlkIndexed) 87 88 // Add the last block again after start and check blockfilesInfo again 89 require.NoError(t, blockfileMgr.addBlock(lastTestBlk)) 90 checkBlockfilesInfoFromFS(t, blkStoreDir, blockfileMgr.blockfilesInfo) 91 } 92 93 func TestBinarySearchBlockFileNum(t *testing.T) { 94 blockStoreRootDir := testPath() 95 blocks := testutil.ConstructTestBlocks(t, 100) 96 maxFileSie := int(0.1 * float64(testutilEstimateTotalSizeOnDisk(t, blocks))) 97 env := newTestEnv(t, NewConf(blockStoreRootDir, maxFileSie)) 98 defer env.Cleanup() 99 blkfileMgrWrapper := newTestBlockfileWrapper(env, "testLedger") 100 blkfileMgr := blkfileMgrWrapper.blockfileMgr 101 102 blkfileMgrWrapper.addBlocks(blocks) 103 104 ledgerDir := (&Conf{blockStorageDir: blockStoreRootDir}).getLedgerBlockDir("testLedger") 105 files, err := ioutil.ReadDir(ledgerDir) 106 require.NoError(t, err) 107 require.Len(t, files, 11) 108 109 for i := uint64(0); i < 100; i++ { 110 fileNum, err := binarySearchFileNumForBlock(ledgerDir, i) 111 require.NoError(t, err) 112 locFromIndex, err := blkfileMgr.index.getBlockLocByBlockNum(i) 113 require.NoError(t, err) 114 expectedFileNum := locFromIndex.fileSuffixNum 115 require.Equal(t, expectedFileNum, fileNum) 116 } 117 } 118 119 func TestIsBootstrappedFromSnapshot(t *testing.T) { 120 testDir, err := ioutil.TempDir("", "isbootstrappedfromsnapshot") 121 require.NoError(t, err) 122 defer os.RemoveAll(testDir) 123 124 t.Run("no_bootstrapping_snapshot_info_file", func(t *testing.T) { 125 // create chains directory for the ledger without bootstrappingSnapshotInfoFile 126 ledgerid := "testnosnapshotinfofile" 127 require.NoError(t, os.MkdirAll(filepath.Join(testDir, ChainsDir, ledgerid), 0o755)) 128 isFromSnapshot, err := IsBootstrappedFromSnapshot(testDir, ledgerid) 129 require.NoError(t, err) 130 require.False(t, isFromSnapshot) 131 }) 132 133 t.Run("with_bootstrapping_snapshot_info_file", func(t *testing.T) { 134 // create chains directory for the ledger with bootstrappingSnapshotInfoFile 135 ledgerid := "testwithsnapshotinfofile" 136 ledgerChainDir := filepath.Join(testDir, ChainsDir, ledgerid) 137 require.NoError(t, os.MkdirAll(ledgerChainDir, 0o755)) 138 file, err := os.Create(filepath.Join(ledgerChainDir, bootstrappingSnapshotInfoFile)) 139 require.NoError(t, err) 140 defer file.Close() 141 isFromSnapshot, err := IsBootstrappedFromSnapshot(testDir, ledgerid) 142 require.NoError(t, err) 143 require.True(t, isFromSnapshot) 144 }) 145 } 146 147 func TestGetLedgersBootstrappedFromSnapshot(t *testing.T) { 148 t.Run("no_bootstrapping_snapshot_info_file", func(t *testing.T) { 149 testDir, err := ioutil.TempDir("", "getledgersfromsnapshot_nosnapshot_info") 150 require.NoError(t, err) 151 defer os.RemoveAll(testDir) 152 153 // create chains directories for ledgers without bootstrappingSnapshotInfoFile 154 for i := 0; i < 5; i++ { 155 require.NoError(t, os.MkdirAll(filepath.Join(testDir, ChainsDir, fmt.Sprintf("ledger_%d", i)), 0o755)) 156 } 157 158 ledgersFromSnapshot, err := GetLedgersBootstrappedFromSnapshot(testDir) 159 require.NoError(t, err) 160 require.Equal(t, 0, len(ledgersFromSnapshot)) 161 }) 162 163 t.Run("with_bootstrapping_snapshot_info_file", func(t *testing.T) { 164 testDir, err := ioutil.TempDir("", "getledgersfromsnapshot_snapshot_info") 165 require.NoError(t, err) 166 defer os.RemoveAll(testDir) 167 168 // create chains directories for ledgers 169 // also create bootstrappingSnapshotInfoFile for ledger_0 and ledger_1 170 for i := 0; i < 5; i++ { 171 ledgerChainDir := filepath.Join(testDir, ChainsDir, fmt.Sprintf("ledger_%d", i)) 172 require.NoError(t, os.MkdirAll(ledgerChainDir, 0o755)) 173 if i < 2 { 174 file, err := os.Create(filepath.Join(ledgerChainDir, bootstrappingSnapshotInfoFile)) 175 require.NoError(t, err) 176 defer file.Close() 177 } 178 } 179 180 ledgersFromSnapshot, err := GetLedgersBootstrappedFromSnapshot(testDir) 181 require.NoError(t, err) 182 require.ElementsMatch(t, ledgersFromSnapshot, []string{"ledger_0", "ledger_1"}) 183 }) 184 } 185 186 func checkBlockfilesInfoFromFS(t *testing.T, blkStoreDir string, expected *blockfilesInfo) { 187 blkfilesInfo, err := constructBlockfilesInfo(blkStoreDir) 188 require.NoError(t, err) 189 require.Equal(t, expected, blkfilesInfo) 190 }