github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/state/protocol/inmem/convert_test.go (about) 1 package inmem_test 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "testing" 7 8 "github.com/dgraph-io/badger/v2" 9 "github.com/stretchr/testify/assert" 10 "github.com/stretchr/testify/require" 11 12 "github.com/onflow/flow-go/model/flow" 13 "github.com/onflow/flow-go/state/protocol" 14 bprotocol "github.com/onflow/flow-go/state/protocol/badger" 15 "github.com/onflow/flow-go/state/protocol/inmem" 16 "github.com/onflow/flow-go/state/protocol/util" 17 "github.com/onflow/flow-go/utils/unittest" 18 ) 19 20 // TestFromSnapshot tests that we are able to convert a database-backed snapshot 21 // to a memory-backed snapshot. 22 func TestFromSnapshot(t *testing.T) { 23 identities := unittest.IdentityListFixture(10, unittest.WithAllRoles()) 24 rootSnapshot := unittest.RootSnapshotFixture(identities) 25 26 util.RunWithFullProtocolStateAndMutator(t, rootSnapshot, func(db *badger.DB, fullState *bprotocol.ParticipantState, mutableState protocol.MutableProtocolState) { 27 state := fullState.FollowerState 28 epochBuilder := unittest.NewEpochBuilder(t, mutableState, state) 29 // build epoch 1 (prepare epoch 2) 30 epochBuilder. 31 BuildEpoch(). 32 CompleteEpoch() 33 // build epoch 2 (prepare epoch 3) 34 epochBuilder. 35 BuildEpoch(). 36 CompleteEpoch() 37 38 // get heights of each phase in built epochs 39 epoch1, ok := epochBuilder.EpochHeights(1) 40 require.True(t, ok) 41 epoch2, ok := epochBuilder.EpochHeights(2) 42 require.True(t, ok) 43 44 // test that we are able to retrieve an in-memory version of root snapshot 45 t.Run("root snapshot", func(t *testing.T) { 46 root := state.Params().FinalizedRoot() 47 expected := state.AtHeight(root.Height) 48 actual, err := inmem.FromSnapshot(expected) 49 require.NoError(t, err) 50 assertSnapshotsEqual(t, expected, actual) 51 testEncodeDecode(t, actual) 52 }) 53 54 // test getting an in-memory snapshot for all phase of epoch 1 55 t.Run("epoch 1", func(t *testing.T) { 56 t.Run("staking phase", func(t *testing.T) { 57 expected := state.AtHeight(epoch1.Staking) 58 actual, err := inmem.FromSnapshot(expected) 59 require.NoError(t, err) 60 assertSnapshotsEqual(t, expected, actual) 61 testEncodeDecode(t, actual) 62 }) 63 t.Run("setup phase", func(t *testing.T) { 64 expected := state.AtHeight(epoch1.Setup) 65 actual, err := inmem.FromSnapshot(expected) 66 require.NoError(t, err) 67 assertSnapshotsEqual(t, expected, actual) 68 testEncodeDecode(t, actual) 69 }) 70 t.Run("committed phase", func(t *testing.T) { 71 expected := state.AtHeight(epoch1.Committed) 72 actual, err := inmem.FromSnapshot(expected) 73 require.NoError(t, err) 74 assertSnapshotsEqual(t, expected, actual) 75 testEncodeDecode(t, actual) 76 }) 77 }) 78 79 // test getting an in-memory snapshot for all phase of epoch 2 80 t.Run("epoch 2", func(t *testing.T) { 81 t.Run("staking phase", func(t *testing.T) { 82 expected := state.AtHeight(epoch2.Staking) 83 actual, err := inmem.FromSnapshot(expected) 84 require.NoError(t, err) 85 assertSnapshotsEqual(t, expected, actual) 86 testEncodeDecode(t, actual) 87 }) 88 t.Run("setup phase", func(t *testing.T) { 89 expected := state.AtHeight(epoch2.Setup) 90 actual, err := inmem.FromSnapshot(expected) 91 require.NoError(t, err) 92 assertSnapshotsEqual(t, expected, actual) 93 testEncodeDecode(t, actual) 94 }) 95 t.Run("committed phase", func(t *testing.T) { 96 expected := state.AtHeight(epoch2.Committed) 97 actual, err := inmem.FromSnapshot(expected) 98 require.NoError(t, err) 99 assertSnapshotsEqual(t, expected, actual) 100 testEncodeDecode(t, actual) 101 }) 102 }) 103 104 // ensure last version beacon is included 105 t.Run("version beacon", func(t *testing.T) { 106 expectedVB := &flow.SealedVersionBeacon{ 107 VersionBeacon: unittest.VersionBeaconFixture( 108 unittest.WithBoundaries( 109 flow.VersionBoundary{ 110 BlockHeight: 1012, 111 Version: "1.2.3", 112 }), 113 ), 114 } 115 unittest.AddVersionBeacon(t, expectedVB.VersionBeacon, state) 116 117 expected := state.Final() 118 head, err := expected.Head() 119 require.NoError(t, err) 120 121 expectedVB.SealHeight = head.Height 122 123 actual, err := inmem.FromSnapshot(expected) 124 require.NoError(t, err) 125 assertSnapshotsEqual(t, expected, actual) 126 testEncodeDecode(t, actual) 127 128 actualVB, err := actual.VersionBeacon() 129 require.NoError(t, err) 130 require.Equal(t, expectedVB, actualVB) 131 }) 132 }) 133 } 134 135 // checks that a snapshot is equivalent after encoding and decoding 136 func testEncodeDecode(t *testing.T, snap *inmem.Snapshot) { 137 138 bz, err := json.Marshal(snap.Encodable()) 139 require.NoError(t, err) 140 141 var encoded inmem.EncodableSnapshot 142 err = json.Unmarshal(bz, &encoded) 143 require.NoError(t, err) 144 145 fromEncoded := inmem.SnapshotFromEncodable(encoded) 146 assertSnapshotsEqual(t, snap, fromEncoded) 147 } 148 149 // checks that 2 snapshots are equivalent by converting to a serializable 150 // representation and comparing the serializations 151 func snapshotsEqual(t *testing.T, snap1, snap2 protocol.Snapshot) bool { 152 enc1, err := inmem.FromSnapshot(snap1) 153 require.NoError(t, err) 154 enc2, err := inmem.FromSnapshot(snap2) 155 require.NoError(t, err) 156 157 bz1, err := json.Marshal(enc1.Encodable()) 158 require.NoError(t, err) 159 bz2, err := json.Marshal(enc2.Encodable()) 160 require.NoError(t, err) 161 162 return bytes.Equal(bz1, bz2) 163 } 164 165 func assertSnapshotsEqual(t *testing.T, snap1, snap2 protocol.Snapshot) { 166 assert.True(t, snapshotsEqual(t, snap1, snap2)) 167 }