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 }