github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/fvm/storage/primary/snapshot_tree_test.go (about)

     1  package primary
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/stretchr/testify/require"
     7  
     8  	"github.com/onflow/flow-go/fvm/storage/logical"
     9  	"github.com/onflow/flow-go/fvm/storage/snapshot"
    10  	"github.com/onflow/flow-go/model/flow"
    11  )
    12  
    13  func TestTimestampedSnapshotTree(t *testing.T) {
    14  	// Test setup ("commit" 4 execution snapshots to the base tree)
    15  
    16  	baseSnapshotTime := logical.Time(5)
    17  
    18  	registerId0 := flow.RegisterID{
    19  		Owner: "",
    20  		Key:   "key0",
    21  	}
    22  	value0 := flow.RegisterValue([]byte("value0"))
    23  
    24  	tree0 := newTimestampedSnapshotTree(
    25  		snapshot.MapStorageSnapshot{
    26  			registerId0: value0,
    27  		},
    28  		baseSnapshotTime)
    29  
    30  	registerId1 := flow.RegisterID{
    31  		Owner: "",
    32  		Key:   "key1",
    33  	}
    34  	value1 := flow.RegisterValue([]byte("value1"))
    35  	writeSet1 := map[flow.RegisterID]flow.RegisterValue{
    36  		registerId1: value1,
    37  	}
    38  
    39  	tree1 := tree0.Append(
    40  		&snapshot.ExecutionSnapshot{
    41  			WriteSet: writeSet1,
    42  		})
    43  
    44  	registerId2 := flow.RegisterID{
    45  		Owner: "",
    46  		Key:   "key2",
    47  	}
    48  	value2 := flow.RegisterValue([]byte("value2"))
    49  	writeSet2 := map[flow.RegisterID]flow.RegisterValue{
    50  		registerId2: value2,
    51  	}
    52  
    53  	tree2 := tree1.Append(
    54  		&snapshot.ExecutionSnapshot{
    55  			WriteSet: writeSet2,
    56  		})
    57  
    58  	registerId3 := flow.RegisterID{
    59  		Owner: "",
    60  		Key:   "key3",
    61  	}
    62  	value3 := flow.RegisterValue([]byte("value3"))
    63  	writeSet3 := map[flow.RegisterID]flow.RegisterValue{
    64  		registerId3: value3,
    65  	}
    66  
    67  	tree3 := tree2.Append(
    68  		&snapshot.ExecutionSnapshot{
    69  			WriteSet: writeSet3,
    70  		})
    71  
    72  	registerId4 := flow.RegisterID{
    73  		Owner: "",
    74  		Key:   "key4",
    75  	}
    76  	value4 := flow.RegisterValue([]byte("value4"))
    77  	writeSet4 := map[flow.RegisterID]flow.RegisterValue{
    78  		registerId4: value4,
    79  	}
    80  
    81  	tree4 := tree3.Append(
    82  		&snapshot.ExecutionSnapshot{
    83  			WriteSet: writeSet4,
    84  		})
    85  
    86  	// Verify the trees internal values
    87  
    88  	trees := []timestampedSnapshotTree{tree0, tree1, tree2, tree3, tree4}
    89  	logs := snapshot.UpdateLog{writeSet1, writeSet2, writeSet3, writeSet4}
    90  
    91  	for i, tree := range trees {
    92  		require.Equal(t, baseSnapshotTime, tree.baseSnapshotTime)
    93  		require.Equal(
    94  			t,
    95  			baseSnapshotTime+logical.Time(i),
    96  			tree.SnapshotTime())
    97  		if i == 0 {
    98  			require.Nil(t, tree.fullLog)
    99  		} else {
   100  			require.Equal(t, logs[:i], tree.fullLog)
   101  		}
   102  
   103  		value, err := tree.Get(registerId0)
   104  		require.NoError(t, err)
   105  		require.Equal(t, value0, value)
   106  
   107  		value, err = tree.Get(registerId1)
   108  		require.NoError(t, err)
   109  		if i >= 1 {
   110  			require.Equal(t, value1, value)
   111  		} else {
   112  			require.Nil(t, value)
   113  		}
   114  
   115  		value, err = tree.Get(registerId2)
   116  		require.NoError(t, err)
   117  		if i >= 2 {
   118  			require.Equal(t, value2, value)
   119  		} else {
   120  			require.Nil(t, value)
   121  		}
   122  
   123  		value, err = tree.Get(registerId3)
   124  		require.NoError(t, err)
   125  		if i >= 3 {
   126  			require.Equal(t, value3, value)
   127  		} else {
   128  			require.Nil(t, value)
   129  		}
   130  
   131  		value, err = tree.Get(registerId4)
   132  		require.NoError(t, err)
   133  		if i == 4 {
   134  			require.Equal(t, value4, value)
   135  		} else {
   136  			require.Nil(t, value)
   137  		}
   138  	}
   139  
   140  	// Verify UpdatesSince returns
   141  
   142  	updates, err := tree0.UpdatesSince(baseSnapshotTime)
   143  	require.NoError(t, err)
   144  	require.Nil(t, updates)
   145  
   146  	_, err = tree4.UpdatesSince(baseSnapshotTime - 1)
   147  	require.ErrorContains(t, err, "missing update log range [4, 5)")
   148  
   149  	for i := 0; i < 5; i++ {
   150  		updates, err = tree4.UpdatesSince(baseSnapshotTime + logical.Time(i))
   151  		require.NoError(t, err)
   152  		require.Equal(t, logs[i:], updates)
   153  	}
   154  
   155  	snapshotTime := baseSnapshotTime + logical.Time(5)
   156  	require.Equal(t, tree4.SnapshotTime()+1, snapshotTime)
   157  
   158  	_, err = tree4.UpdatesSince(snapshotTime)
   159  	require.ErrorContains(t, err, "missing update log range (9, 10]")
   160  }
   161  
   162  func TestRebaseableTimestampedSnapshotTree(t *testing.T) {
   163  	registerId := flow.RegisterID{
   164  		Owner: "owner",
   165  		Key:   "key",
   166  	}
   167  
   168  	value1 := flow.RegisterValue([]byte("value1"))
   169  	value2 := flow.RegisterValue([]byte("value2"))
   170  
   171  	tree1 := newTimestampedSnapshotTree(
   172  		snapshot.MapStorageSnapshot{
   173  			registerId: value1,
   174  		},
   175  		0)
   176  
   177  	tree2 := newTimestampedSnapshotTree(
   178  		snapshot.MapStorageSnapshot{
   179  			registerId: value2,
   180  		},
   181  		0)
   182  
   183  	rebaseableTree := newRebaseableTimestampedSnapshotTree(tree1)
   184  	treeReference := rebaseableTree
   185  
   186  	value, err := treeReference.Get(registerId)
   187  	require.NoError(t, err)
   188  	require.Equal(t, value, value1)
   189  
   190  	rebaseableTree.Rebase(tree2)
   191  
   192  	value, err = treeReference.Get(registerId)
   193  	require.NoError(t, err)
   194  	require.Equal(t, value, value2)
   195  }