github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/state/protocol/util_test.go (about) 1 package protocol_test 2 3 import ( 4 "errors" 5 "math/rand" 6 "testing" 7 8 "github.com/stretchr/testify/assert" 9 "github.com/stretchr/testify/mock" 10 "github.com/stretchr/testify/require" 11 12 "github.com/onflow/flow-go/model/flow" 13 "github.com/onflow/flow-go/state/protocol" 14 "github.com/onflow/flow-go/storage" 15 storagemock "github.com/onflow/flow-go/storage/mock" 16 "github.com/onflow/flow-go/utils/unittest" 17 ) 18 19 func TestIsSporkRootSnapshot(t *testing.T) { 20 t.Run("spork root", func(t *testing.T) { 21 snapshot := unittest.RootSnapshotFixture(unittest.IdentityListFixture(10, unittest.WithAllRoles())) 22 isSporkRoot, err := protocol.IsSporkRootSnapshot(snapshot) 23 require.NoError(t, err) 24 assert.True(t, isSporkRoot) 25 }) 26 27 t.Run("other snapshot", func(t *testing.T) { 28 snapshot := unittest.RootSnapshotFixture(unittest.IdentityListFixture(10, unittest.WithAllRoles())) 29 snapshot.Encodable().Head.Height += 1 // modify head height to break equivalence with spork root block height 30 isSporkRoot, err := protocol.IsSporkRootSnapshot(snapshot) 31 require.NoError(t, err) 32 assert.False(t, isSporkRoot) 33 }) 34 } 35 36 // TestOrderedSeals tests that protocol.OrderedSeals returns a list of ordered seals for a payload. 37 func TestOrderedSeals(t *testing.T) { 38 t.Run("empty payload", func(t *testing.T) { 39 payload := flow.EmptyPayload() 40 headers := storagemock.NewHeaders(t) 41 42 ordered, err := protocol.OrderedSeals(payload.Seals, headers) 43 require.NoError(t, err) 44 require.Empty(t, ordered) 45 }) 46 t.Run("block not found error", func(t *testing.T) { 47 headers := storagemock.NewHeaders(t) 48 seals := unittest.Seal.Fixtures(10) 49 payload := unittest.PayloadFixture(unittest.WithSeals(seals...)) 50 headers.On("ByBlockID", mock.Anything).Return(nil, storage.ErrNotFound) 51 52 ordered, err := protocol.OrderedSeals(payload.Seals, headers) 53 require.ErrorIs(t, err, storage.ErrNotFound) 54 require.Empty(t, ordered) 55 }) 56 t.Run("unexpected error", func(t *testing.T) { 57 headers := storagemock.NewHeaders(t) 58 seals := unittest.Seal.Fixtures(10) 59 payload := unittest.PayloadFixture(unittest.WithSeals(seals...)) 60 exception := errors.New("exception") 61 headers.On("ByBlockID", mock.Anything).Return(nil, exception) 62 63 ordered, err := protocol.OrderedSeals(payload.Seals, headers) 64 require.ErrorIs(t, err, exception) 65 require.Empty(t, ordered) 66 }) 67 t.Run("already ordered", func(t *testing.T) { 68 headers := storagemock.NewHeaders(t) 69 70 blocks := unittest.ChainFixtureFrom(10, unittest.BlockHeaderFixture()) 71 seals := unittest.Seal.Fixtures(10) 72 for i, seal := range seals { 73 seal.BlockID = blocks[i].ID() 74 headers.On("ByBlockID", seal.BlockID).Return(blocks[i].Header, nil) 75 } 76 payload := unittest.PayloadFixture(unittest.WithSeals(seals...)) 77 78 ordered, err := protocol.OrderedSeals(payload.Seals, headers) 79 require.NoError(t, err) 80 require.Equal(t, seals, ordered) 81 }) 82 t.Run("unordered", func(t *testing.T) { 83 headers := storagemock.NewHeaders(t) 84 85 blocks := unittest.ChainFixtureFrom(10, flow.Genesis(flow.Localnet).Header) 86 orderedSeals := unittest.Seal.Fixtures(len(blocks)) 87 for i, seal := range orderedSeals { 88 seal.BlockID = blocks[i].ID() 89 headers.On("ByBlockID", seal.BlockID).Return(blocks[i].Header, nil) 90 } 91 unorderedSeals := make([]*flow.Seal, len(orderedSeals)) 92 copy(unorderedSeals, orderedSeals) 93 // randomly re-order seals 94 rand.Shuffle(len(unorderedSeals), func(i, j int) { 95 unorderedSeals[i], unorderedSeals[j] = unorderedSeals[j], unorderedSeals[i] 96 }) 97 payload := unittest.PayloadFixture(unittest.WithSeals(unorderedSeals...)) 98 99 ordered, err := protocol.OrderedSeals(payload.Seals, headers) 100 require.NoError(t, err) 101 require.Equal(t, orderedSeals, ordered) 102 }) 103 }