github.com/osdi23p228/fabric@v0.0.0-20221218062954-77808885f5db/common/ledger/blkstorage/blocks_itr_test.go (about)

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