github.com/koko1123/flow-go-1@v0.29.6/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/v3"
     9  	"github.com/stretchr/testify/assert"
    10  	"github.com/stretchr/testify/require"
    11  
    12  	"github.com/koko1123/flow-go-1/state/protocol"
    13  	bprotocol "github.com/koko1123/flow-go-1/state/protocol/badger"
    14  	"github.com/koko1123/flow-go-1/state/protocol/inmem"
    15  	"github.com/koko1123/flow-go-1/state/protocol/util"
    16  	"github.com/koko1123/flow-go-1/utils/unittest"
    17  )
    18  
    19  // TestFromSnapshot tests that we are able to convert a database-backed snapshot
    20  // to a memory-backed snapshot.
    21  func TestFromSnapshot(t *testing.T) {
    22  	identities := unittest.IdentityListFixture(10, unittest.WithAllRoles())
    23  	rootSnapshot := unittest.RootSnapshotFixture(identities)
    24  
    25  	util.RunWithFollowerProtocolState(t, rootSnapshot, func(db *badger.DB, state *bprotocol.FollowerState) {
    26  
    27  		epochBuilder := unittest.NewEpochBuilder(t, state)
    28  		// build epoch 1 (prepare epoch 2)
    29  		epochBuilder.
    30  			BuildEpoch().
    31  			CompleteEpoch()
    32  		// build epoch 2 (prepare epoch 3)
    33  		epochBuilder.
    34  			BuildEpoch().
    35  			CompleteEpoch()
    36  
    37  		// get heights of each phase in built epochs
    38  		epoch1, ok := epochBuilder.EpochHeights(1)
    39  		require.True(t, ok)
    40  		epoch2, ok := epochBuilder.EpochHeights(2)
    41  		require.True(t, ok)
    42  
    43  		// test that we are able retrieve an in-memory version of root snapshot
    44  		t.Run("root snapshot", func(t *testing.T) {
    45  			root, err := state.Params().Root()
    46  			require.NoError(t, err)
    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  }
   105  
   106  // checks that a snapshot is equivalent after encoding and decoding
   107  func testEncodeDecode(t *testing.T, snap *inmem.Snapshot) {
   108  
   109  	bz, err := json.Marshal(snap.Encodable())
   110  	require.NoError(t, err)
   111  
   112  	var encoded inmem.EncodableSnapshot
   113  	err = json.Unmarshal(bz, &encoded)
   114  	require.NoError(t, err)
   115  
   116  	fromEncoded := inmem.SnapshotFromEncodable(encoded)
   117  	assertSnapshotsEqual(t, snap, fromEncoded)
   118  }
   119  
   120  // checks that 2 snapshots are equivalent by converting to a serializable
   121  // representation and comparing the serializations
   122  func snapshotsEqual(t *testing.T, snap1, snap2 protocol.Snapshot) bool {
   123  	enc1, err := inmem.FromSnapshot(snap1)
   124  	require.NoError(t, err)
   125  	enc2, err := inmem.FromSnapshot(snap2)
   126  	require.NoError(t, err)
   127  
   128  	bz1, err := json.Marshal(enc1.Encodable())
   129  	require.NoError(t, err)
   130  	bz2, err := json.Marshal(enc2.Encodable())
   131  	require.NoError(t, err)
   132  
   133  	return bytes.Equal(bz1, bz2)
   134  }
   135  
   136  func assertSnapshotsEqual(t *testing.T, snap1, snap2 protocol.Snapshot) {
   137  	assert.True(t, snapshotsEqual(t, snap1, snap2))
   138  }