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  }