github.com/sykesm/fabric@v1.1.0-preview.0.20200129034918-2aa12b1a0181/common/ledger/blkstorage/fsblkstorage/blocks_itr_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 "sync" 21 "testing" 22 "time" 23 24 "github.com/hyperledger/fabric-protos-go/common" 25 "github.com/hyperledger/fabric/common/ledger/testutil" 26 "github.com/stretchr/testify/assert" 27 ) 28 29 func TestBlocksItrBlockingNext(t *testing.T) { 30 env := newTestEnv(t, NewConf(testPath(), 0)) 31 defer env.Cleanup() 32 blkfileMgrWrapper := newTestBlockfileWrapper(env, "testLedger") 33 defer blkfileMgrWrapper.close() 34 blkfileMgr := blkfileMgrWrapper.blockfileMgr 35 36 blocks := testutil.ConstructTestBlocks(t, 10) 37 blkfileMgrWrapper.addBlocks(blocks[:5]) 38 39 itr, err := blkfileMgr.retrieveBlocks(1) 40 assert.NoError(t, err) 41 defer itr.Close() 42 readyChan := make(chan struct{}) 43 doneChan := make(chan bool) 44 go testIterateAndVerify(t, itr, blocks[1:], 4, readyChan, doneChan) 45 <-readyChan 46 testAppendBlocks(blkfileMgrWrapper, blocks[5:7]) 47 blkfileMgr.moveToNextFile() 48 time.Sleep(time.Millisecond * 10) 49 testAppendBlocks(blkfileMgrWrapper, blocks[7:]) 50 <-doneChan 51 } 52 53 func TestBlockItrClose(t *testing.T) { 54 env := newTestEnv(t, NewConf(testPath(), 0)) 55 defer env.Cleanup() 56 blkfileMgrWrapper := newTestBlockfileWrapper(env, "testLedger") 57 defer blkfileMgrWrapper.close() 58 blkfileMgr := blkfileMgrWrapper.blockfileMgr 59 60 blocks := testutil.ConstructTestBlocks(t, 5) 61 blkfileMgrWrapper.addBlocks(blocks) 62 63 itr, err := blkfileMgr.retrieveBlocks(1) 64 assert.NoError(t, err) 65 66 bh, _ := itr.Next() 67 assert.NotNil(t, bh) 68 itr.Close() 69 70 bh, err = itr.Next() 71 assert.NoError(t, err) 72 assert.Nil(t, bh) 73 } 74 75 func TestRaceToDeadlock(t *testing.T) { 76 env := newTestEnv(t, NewConf(testPath(), 0)) 77 defer env.Cleanup() 78 blkfileMgrWrapper := newTestBlockfileWrapper(env, "testLedger") 79 defer blkfileMgrWrapper.close() 80 blkfileMgr := blkfileMgrWrapper.blockfileMgr 81 82 blocks := testutil.ConstructTestBlocks(t, 5) 83 blkfileMgrWrapper.addBlocks(blocks) 84 85 for i := 0; i < 1000; i++ { 86 itr, err := blkfileMgr.retrieveBlocks(5) 87 if err != nil { 88 panic(err) 89 } 90 go func() { 91 itr.Next() 92 }() 93 itr.Close() 94 } 95 96 for i := 0; i < 1000; i++ { 97 itr, err := blkfileMgr.retrieveBlocks(5) 98 if err != nil { 99 panic(err) 100 } 101 go func() { 102 itr.Close() 103 }() 104 itr.Next() 105 } 106 } 107 108 func TestBlockItrCloseWithoutRetrieve(t *testing.T) { 109 env := newTestEnv(t, NewConf(testPath(), 0)) 110 defer env.Cleanup() 111 blkfileMgrWrapper := newTestBlockfileWrapper(env, "testLedger") 112 defer blkfileMgrWrapper.close() 113 blkfileMgr := blkfileMgrWrapper.blockfileMgr 114 blocks := testutil.ConstructTestBlocks(t, 5) 115 blkfileMgrWrapper.addBlocks(blocks) 116 117 itr, err := blkfileMgr.retrieveBlocks(2) 118 assert.NoError(t, err) 119 itr.Close() 120 } 121 122 func TestCloseMultipleItrsWaitForFutureBlock(t *testing.T) { 123 env := newTestEnv(t, NewConf(testPath(), 0)) 124 defer env.Cleanup() 125 blkfileMgrWrapper := newTestBlockfileWrapper(env, "testLedger") 126 defer blkfileMgrWrapper.close() 127 blkfileMgr := blkfileMgrWrapper.blockfileMgr 128 blocks := testutil.ConstructTestBlocks(t, 10) 129 blkfileMgrWrapper.addBlocks(blocks[:5]) 130 131 wg := &sync.WaitGroup{} 132 wg.Add(2) 133 itr1, err := blkfileMgr.retrieveBlocks(7) 134 assert.NoError(t, err) 135 // itr1 does not retrieve any block because it closes before new blocks are added 136 go iterateInBackground(t, itr1, 9, wg, []uint64{}) 137 138 itr2, err := blkfileMgr.retrieveBlocks(8) 139 assert.NoError(t, err) 140 // itr2 retrieves two blocks 8 and 9. Because it started waiting for 8 and quits at 9 141 go iterateInBackground(t, itr2, 9, wg, []uint64{8, 9}) 142 143 // sleep for the background iterators to get started 144 time.Sleep(2 * time.Second) 145 itr1.Close() 146 blkfileMgrWrapper.addBlocks(blocks[5:]) 147 wg.Wait() 148 } 149 150 func iterateInBackground(t *testing.T, itr *blocksItr, quitAfterBlkNum uint64, wg *sync.WaitGroup, expectedBlockNums []uint64) { 151 defer wg.Done() 152 retrievedBlkNums := []uint64{} 153 defer func() { assert.Equal(t, expectedBlockNums, retrievedBlkNums) }() 154 155 for { 156 blk, err := itr.Next() 157 assert.NoError(t, err) 158 if blk == nil { 159 return 160 } 161 blkNum := blk.(*common.Block).Header.Number 162 retrievedBlkNums = append(retrievedBlkNums, blkNum) 163 t.Logf("blk.Num=%d", blk.(*common.Block).Header.Number) 164 if blkNum == quitAfterBlkNum { 165 return 166 } 167 } 168 } 169 170 func testIterateAndVerify(t *testing.T, itr *blocksItr, blocks []*common.Block, readyAt int, readyChan chan<- struct{}, doneChan chan bool) { 171 blocksIterated := 0 172 for { 173 t.Logf("blocksIterated: %v", blocksIterated) 174 block, err := itr.Next() 175 assert.NoError(t, err) 176 assert.Equal(t, blocks[blocksIterated], block) 177 blocksIterated++ 178 if blocksIterated == readyAt { 179 close(readyChan) 180 } 181 if blocksIterated == len(blocks) { 182 break 183 } 184 } 185 doneChan <- true 186 } 187 188 func testAppendBlocks(blkfileMgrWrapper *testBlockfileMgrWrapper, blocks []*common.Block) { 189 blkfileMgrWrapper.addBlocks(blocks) 190 }