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

     1  package snapshot
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"github.com/stretchr/testify/require"
     8  
     9  	"github.com/onflow/flow-go/model/flow"
    10  )
    11  
    12  func TestSnapshotTree(t *testing.T) {
    13  	id1 := flow.NewRegisterID(flow.HexToAddress("0x1"), "")
    14  	id2 := flow.NewRegisterID(flow.HexToAddress("0x2"), "")
    15  	id3 := flow.NewRegisterID(flow.HexToAddress("0x3"), "")
    16  	missingId := flow.NewRegisterID(flow.HexToAddress("0x99"), "")
    17  
    18  	value1v0 := flow.RegisterValue("1v0")
    19  
    20  	// entries:
    21  	// 1 -> 1v0
    22  	tree0 := NewSnapshotTree(
    23  		MapStorageSnapshot{
    24  			id1: value1v0,
    25  		})
    26  
    27  	expected0 := map[flow.RegisterID]flow.RegisterValue{
    28  		id1:       value1v0,
    29  		id2:       nil,
    30  		id3:       nil,
    31  		missingId: nil,
    32  	}
    33  
    34  	value2v1 := flow.RegisterValue("2v1")
    35  
    36  	tree1 := tree0.Append(
    37  		&ExecutionSnapshot{
    38  			WriteSet: map[flow.RegisterID]flow.RegisterValue{
    39  				id2: value2v1,
    40  			},
    41  		})
    42  
    43  	expected1 := map[flow.RegisterID]flow.RegisterValue{
    44  		id1:       value1v0,
    45  		id2:       value2v1,
    46  		id3:       nil,
    47  		missingId: nil,
    48  	}
    49  
    50  	value1v1 := flow.RegisterValue("1v1")
    51  	value3v1 := flow.RegisterValue("3v1")
    52  
    53  	tree2 := tree1.Append(
    54  		&ExecutionSnapshot{
    55  			WriteSet: map[flow.RegisterID]flow.RegisterValue{
    56  				id1: value1v1,
    57  				id3: value3v1,
    58  			},
    59  		})
    60  
    61  	expected2 := map[flow.RegisterID]flow.RegisterValue{
    62  		id1:       value1v1,
    63  		id2:       value2v1,
    64  		id3:       value3v1,
    65  		missingId: nil,
    66  	}
    67  
    68  	value2v2 := flow.RegisterValue("2v2")
    69  
    70  	tree3 := tree2.Append(
    71  		&ExecutionSnapshot{
    72  			WriteSet: map[flow.RegisterID]flow.RegisterValue{
    73  				id2: value2v2,
    74  			},
    75  		})
    76  
    77  	expected3 := map[flow.RegisterID]flow.RegisterValue{
    78  		id1:       value1v1,
    79  		id2:       value2v2,
    80  		id3:       value3v1,
    81  		missingId: nil,
    82  	}
    83  
    84  	expectedCompacted := map[flow.RegisterID]flow.RegisterValue{
    85  		id1:       value1v1,
    86  		id2:       value2v2,
    87  		id3:       value3v1,
    88  		missingId: nil,
    89  	}
    90  
    91  	compactedTree := tree3
    92  	numExtraUpdates := 2*compactThreshold + 1
    93  	for i := 0; i < numExtraUpdates; i++ {
    94  		value := []byte(fmt.Sprintf("compacted %d", i))
    95  		expectedCompacted[id3] = value
    96  		compactedTree = compactedTree.Append(
    97  			&ExecutionSnapshot{
    98  				WriteSet: map[flow.RegisterID]flow.RegisterValue{
    99  					id3: value,
   100  				},
   101  			})
   102  	}
   103  
   104  	check := func(
   105  		tree SnapshotTree,
   106  		expected map[flow.RegisterID]flow.RegisterValue,
   107  		compactedLogLen int,
   108  	) {
   109  		require.Len(t, tree.compactedLog, compactedLogLen)
   110  
   111  		for key, expectedValue := range expected {
   112  			value, err := tree.Get(key)
   113  			require.NoError(t, err)
   114  			require.Equal(t, value, expectedValue, string(expectedValue))
   115  		}
   116  	}
   117  
   118  	check(tree0, expected0, 0)
   119  	check(tree1, expected1, 1)
   120  	check(tree2, expected2, 2)
   121  	check(tree3, expected3, 3)
   122  	check(compactedTree, expectedCompacted, 4)
   123  
   124  	emptyTree := NewSnapshotTree(nil)
   125  	value, err := emptyTree.Get(id1)
   126  	require.NoError(t, err)
   127  	require.Nil(t, value)
   128  }