github.com/MetalBlockchain/metalgo@v1.11.9/snow/consensus/snowball/nnary_snowflake_test.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package snowball
     5  
     6  import (
     7  	"testing"
     8  
     9  	"github.com/stretchr/testify/require"
    10  
    11  	"github.com/MetalBlockchain/metalgo/ids"
    12  )
    13  
    14  func TestNnarySnowflake(t *testing.T) {
    15  	require := require.New(t)
    16  
    17  	alphaPreference, alphaConfidence := 1, 2
    18  	beta := 2
    19  	terminationConditions := newSingleTerminationCondition(alphaConfidence, beta)
    20  
    21  	sf := newNnarySnowflake(alphaPreference, terminationConditions, Red)
    22  	sf.Add(Blue)
    23  	sf.Add(Green)
    24  
    25  	require.Equal(Red, sf.Preference())
    26  	require.False(sf.Finalized())
    27  
    28  	sf.RecordPoll(alphaConfidence, Blue)
    29  	require.Equal(Blue, sf.Preference())
    30  	require.False(sf.Finalized())
    31  
    32  	sf.RecordPoll(alphaPreference, Red)
    33  	require.Equal(Red, sf.Preference())
    34  	require.False(sf.Finalized())
    35  
    36  	sf.RecordPoll(alphaConfidence, Red)
    37  	require.Equal(Red, sf.Preference())
    38  	require.False(sf.Finalized())
    39  
    40  	sf.RecordPoll(alphaConfidence, Red)
    41  	require.Equal(Red, sf.Preference())
    42  	require.True(sf.Finalized())
    43  
    44  	sf.RecordPoll(alphaPreference, Blue)
    45  	require.Equal(Red, sf.Preference())
    46  	require.True(sf.Finalized())
    47  
    48  	sf.RecordPoll(alphaConfidence, Blue)
    49  	require.Equal(Red, sf.Preference())
    50  	require.True(sf.Finalized())
    51  }
    52  
    53  func TestNnarySnowflakeConfidenceReset(t *testing.T) {
    54  	require := require.New(t)
    55  
    56  	alphaPreference, alphaConfidence := 1, 2
    57  	beta := 4
    58  	terminationConditions := newSingleTerminationCondition(alphaConfidence, beta)
    59  
    60  	sf := newNnarySnowflake(alphaPreference, terminationConditions, Red)
    61  	sf.Add(Blue)
    62  	sf.Add(Green)
    63  
    64  	require.Equal(Red, sf.Preference())
    65  	require.False(sf.Finalized())
    66  
    67  	// Increase Blue's confidence without finalizing
    68  	for i := 0; i < beta-1; i++ {
    69  		sf.RecordPoll(alphaConfidence, Blue)
    70  		require.Equal(Blue, sf.Preference())
    71  		require.False(sf.Finalized())
    72  	}
    73  
    74  	// Increase Red's confidence without finalizing
    75  	for i := 0; i < beta-1; i++ {
    76  		sf.RecordPoll(alphaConfidence, Red)
    77  		require.Equal(Red, sf.Preference())
    78  		require.False(sf.Finalized())
    79  	}
    80  
    81  	// One more round of voting for Red should accept Red
    82  	sf.RecordPoll(alphaConfidence, Red)
    83  	require.Equal(Red, sf.Preference())
    84  	require.True(sf.Finalized())
    85  }
    86  
    87  func TestVirtuousNnarySnowflake(t *testing.T) {
    88  	require := require.New(t)
    89  
    90  	alphaPreference, alphaConfidence := 1, 2
    91  	beta := 2
    92  	terminationConditions := newSingleTerminationCondition(alphaConfidence, beta)
    93  
    94  	sb := newNnarySnowflake(alphaPreference, terminationConditions, Red)
    95  	require.Equal(Red, sb.Preference())
    96  	require.False(sb.Finalized())
    97  
    98  	sb.RecordPoll(alphaConfidence, Red)
    99  	require.Equal(Red, sb.Preference())
   100  	require.False(sb.Finalized())
   101  
   102  	sb.RecordPoll(alphaConfidence, Red)
   103  	require.Equal(Red, sb.Preference())
   104  	require.True(sb.Finalized())
   105  }
   106  
   107  type nnarySnowflakeTest struct {
   108  	require *require.Assertions
   109  
   110  	nnarySnowflake
   111  }
   112  
   113  func newNnarySnowflakeTest(t *testing.T, alphaPreference int, terminationConditions []terminationCondition) snowflakeTest[ids.ID] {
   114  	require := require.New(t)
   115  
   116  	return &nnarySnowflakeTest{
   117  		require:        require,
   118  		nnarySnowflake: newNnarySnowflake(alphaPreference, terminationConditions, Red),
   119  	}
   120  }
   121  
   122  func (sf *nnarySnowflakeTest) RecordPoll(count int, choice ids.ID) {
   123  	sf.nnarySnowflake.RecordPoll(count, choice)
   124  }
   125  
   126  func (sf *nnarySnowflakeTest) AssertEqual(expectedConfidences []int, expectedFinalized bool, expectedPreference ids.ID) {
   127  	sf.require.Equal(expectedPreference, sf.Preference())
   128  	sf.require.Equal(expectedConfidences, sf.nnarySnowflake.confidence)
   129  	sf.require.Equal(expectedFinalized, sf.Finalized())
   130  }
   131  
   132  func TestNnarySnowflakeErrorDrivenSingleChoice(t *testing.T) {
   133  	for _, test := range getErrorDrivenSnowflakeSingleChoiceSuite[ids.ID]() {
   134  		t.Run(test.name, func(t *testing.T) {
   135  			test.f(t, newNnarySnowflakeTest, Red)
   136  		})
   137  	}
   138  }
   139  
   140  func TestNnarySnowflakeErrorDrivenMultiChoice(t *testing.T) {
   141  	for _, test := range getErrorDrivenSnowflakeMultiChoiceSuite[ids.ID]() {
   142  		t.Run(test.name, func(t *testing.T) {
   143  			test.f(t, newNnarySnowflakeTest, Red, Green)
   144  		})
   145  	}
   146  }