github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/consensus/recovery/recover_test.go (about)

     1  package recovery
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/stretchr/testify/require"
     7  
     8  	"github.com/onflow/flow-go/consensus/hotstuff/model"
     9  	"github.com/onflow/flow-go/model/flow"
    10  	"github.com/onflow/flow-go/utils/unittest"
    11  )
    12  
    13  func TestRecover(t *testing.T) {
    14  	finalized := unittest.BlockHeaderFixture()
    15  	blocks := unittest.ChainFixtureFrom(100, finalized)
    16  	pending := make([]*flow.Header, 0)
    17  	for _, b := range blocks {
    18  		pending = append(pending, b.Header)
    19  	}
    20  
    21  	// Recover with `pending` blocks and record what blocks are forwarded to `onProposal`
    22  	recovered := make([]*model.Proposal, 0)
    23  	scanner := func(block *model.Proposal) error {
    24  		recovered = append(recovered, block)
    25  		return nil
    26  	}
    27  	err := Recover(unittest.Logger(), pending, scanner)
    28  	require.NoError(t, err)
    29  
    30  	// should forward blocks in exact order, just converting flow.Header to pending block
    31  	require.Len(t, recovered, len(pending))
    32  	for i, r := range recovered {
    33  		require.Equal(t, model.ProposalFromFlow(pending[i]), r)
    34  	}
    35  }
    36  
    37  func TestRecoverEmptyInput(t *testing.T) {
    38  	scanner := func(block *model.Proposal) error {
    39  		require.Fail(t, "no proposal expected")
    40  		return nil
    41  	}
    42  	err := Recover(unittest.Logger(), []*flow.Header{}, scanner)
    43  	require.NoError(t, err)
    44  }
    45  
    46  func TestCollector(t *testing.T) {
    47  	t.Run("empty retrieve", func(t *testing.T) {
    48  		c := NewCollector[string]()
    49  		require.Empty(t, c.Retrieve())
    50  	})
    51  
    52  	t.Run("append", func(t *testing.T) {
    53  		c := NewCollector[string]()
    54  		strings := []string{"a", "b", "c"}
    55  		appended := 0
    56  		for _, s := range strings {
    57  			c.Append(s)
    58  			appended++
    59  			require.Equal(t, strings[:appended], c.Retrieve())
    60  		}
    61  	})
    62  
    63  	t.Run("append multiple", func(t *testing.T) {
    64  		c := NewCollector[string]()
    65  		strings := []string{"a", "b", "c", "d", "e"}
    66  
    67  		c.Append(strings[0], strings[1])
    68  		require.Equal(t, strings[:2], c.Retrieve())
    69  
    70  		c.Append(strings[2], strings[3], strings[4])
    71  		require.Equal(t, strings, c.Retrieve())
    72  	})
    73  
    74  	t.Run("safely passed by value", func(t *testing.T) {
    75  		strings := []string{"a", "b"}
    76  		c := NewCollector[string]()
    77  		c.Append(strings[0])
    78  
    79  		// pass by value
    80  		c2 := c
    81  		require.Equal(t, strings[:1], c2.Retrieve())
    82  
    83  		// add to original; change could be reflected by c2:
    84  		c.Append(strings[1])
    85  		require.Equal(t, strings, c2.Retrieve())
    86  	})
    87  
    88  	t.Run("append after retrieve", func(t *testing.T) {
    89  		c := NewCollector[string]()
    90  		strings := []string{"a", "b", "c", "d", "e"}
    91  
    92  		c.Append(strings[0], strings[1])
    93  		retrieved := c.Retrieve()
    94  		require.Equal(t, strings[:2], retrieved)
    95  
    96  		// appending further elements shouldn't affect previously retrieved list
    97  		c.Append(strings[2], strings[3], strings[4])
    98  		require.Equal(t, strings[:2], retrieved)
    99  		require.Equal(t, strings, c.Retrieve())
   100  	})
   101  }