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 }