github.com/onflow/atree@v0.6.0/storage_test.go (about)

     1  /*
     2   * Atree - Scalable Arrays and Ordered Maps
     3   *
     4   * Copyright 2021-2022 Dapper Labs, Inc.
     5   *
     6   * Licensed under the Apache License, Version 2.0 (the "License");
     7   * you may not use this file except in compliance with the License.
     8   * You may obtain a copy of the License at
     9   *
    10   *   http://www.apache.org/licenses/LICENSE-2.0
    11   *
    12   * Unless required by applicable law or agreed to in writing, software
    13   * distributed under the License is distributed on an "AS IS" BASIS,
    14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    15   * See the License for the specific language governing permissions and
    16   * limitations under the License.
    17   */
    18  
    19  package atree
    20  
    21  import (
    22  	"errors"
    23  	"math/rand"
    24  	"runtime"
    25  	"strings"
    26  	"testing"
    27  
    28  	"github.com/fxamacker/cbor/v2"
    29  	"github.com/stretchr/testify/require"
    30  )
    31  
    32  func TestStorageIndexNext(t *testing.T) {
    33  	index := StorageIndex{0, 0, 0, 0, 0, 0, 0, 1}
    34  	want := StorageIndex{0, 0, 0, 0, 0, 0, 0, 2}
    35  	require.Equal(t, want, index.Next())
    36  }
    37  
    38  func TestNewStorageID(t *testing.T) {
    39  	t.Run("temp address", func(t *testing.T) {
    40  		want := StorageID{Address: Address{}, Index: StorageIndex{1}}
    41  		require.Equal(t, want, NewStorageID(Address{}, StorageIndex{1}))
    42  	})
    43  	t.Run("perm address", func(t *testing.T) {
    44  		want := StorageID{Address: Address{1}, Index: StorageIndex{1}}
    45  		require.Equal(t, want, NewStorageID(Address{1}, StorageIndex{1}))
    46  	})
    47  }
    48  
    49  func TestNewStorageIDFromRawBytes(t *testing.T) {
    50  	t.Run("data length < storage id size", func(t *testing.T) {
    51  		var fatalError *FatalError
    52  		var storageIDError *StorageIDError
    53  
    54  		id, err := NewStorageIDFromRawBytes(nil)
    55  		require.Equal(t, StorageIDUndefined, id)
    56  		require.Equal(t, 1, errorCategorizationCount(err))
    57  		require.ErrorAs(t, err, &fatalError)
    58  		require.ErrorAs(t, err, &storageIDError)
    59  		require.ErrorAs(t, fatalError, &storageIDError)
    60  
    61  		id, err = NewStorageIDFromRawBytes([]byte{0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2})
    62  		require.Equal(t, StorageIDUndefined, id)
    63  		require.Equal(t, 1, errorCategorizationCount(err))
    64  		require.ErrorAs(t, err, &fatalError)
    65  		require.ErrorAs(t, err, &storageIDError)
    66  		require.ErrorAs(t, fatalError, &storageIDError)
    67  	})
    68  
    69  	t.Run("data length == storage id size", func(t *testing.T) {
    70  		id, err := NewStorageIDFromRawBytes([]byte{0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2})
    71  
    72  		want := StorageID{
    73  			Address: Address{0, 0, 0, 0, 0, 0, 0, 1},
    74  			Index:   StorageIndex{0, 0, 0, 0, 0, 0, 0, 2},
    75  		}
    76  		require.Equal(t, want, id)
    77  		require.NoError(t, err)
    78  	})
    79  	t.Run("data length > storage id size", func(t *testing.T) {
    80  		id, err := NewStorageIDFromRawBytes([]byte{0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 1, 2, 3, 4, 5, 6, 7, 8})
    81  
    82  		want := StorageID{
    83  			Address: Address{0, 0, 0, 0, 0, 0, 0, 1},
    84  			Index:   StorageIndex{0, 0, 0, 0, 0, 0, 0, 2},
    85  		}
    86  		require.Equal(t, want, id)
    87  		require.NoError(t, err)
    88  	})
    89  }
    90  
    91  func TestStorageIDToRawBytes(t *testing.T) {
    92  	t.Run("buffer nil", func(t *testing.T) {
    93  		var fatalError *FatalError
    94  		var storageIDError *StorageIDError
    95  
    96  		size, err := StorageIDUndefined.ToRawBytes(nil)
    97  		require.Equal(t, 0, size)
    98  		require.Equal(t, 1, errorCategorizationCount(err))
    99  		require.ErrorAs(t, err, &fatalError)
   100  		require.ErrorAs(t, err, &storageIDError)
   101  		require.ErrorAs(t, fatalError, &storageIDError)
   102  	})
   103  
   104  	t.Run("buffer too short", func(t *testing.T) {
   105  		var fatalError *FatalError
   106  		var storageIDError *StorageIDError
   107  
   108  		b := make([]byte, 8)
   109  		size, err := StorageIDUndefined.ToRawBytes(b)
   110  		require.Equal(t, 0, size)
   111  		require.Equal(t, 1, errorCategorizationCount(err))
   112  		require.ErrorAs(t, err, &fatalError)
   113  		require.ErrorAs(t, err, &storageIDError)
   114  		require.ErrorAs(t, fatalError, &storageIDError)
   115  	})
   116  
   117  	t.Run("undefined", func(t *testing.T) {
   118  		b := make([]byte, storageIDSize)
   119  		size, err := StorageIDUndefined.ToRawBytes(b)
   120  		require.NoError(t, err)
   121  
   122  		want := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
   123  		require.Equal(t, want, b)
   124  		require.Equal(t, storageIDSize, size)
   125  	})
   126  
   127  	t.Run("temp address", func(t *testing.T) {
   128  		id := NewStorageID(Address{0, 0, 0, 0, 0, 0, 0, 0}, StorageIndex{0, 0, 0, 0, 0, 0, 0, 1})
   129  		b := make([]byte, storageIDSize)
   130  		size, err := id.ToRawBytes(b)
   131  		require.NoError(t, err)
   132  
   133  		want := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
   134  		require.Equal(t, want, b)
   135  		require.Equal(t, storageIDSize, size)
   136  	})
   137  
   138  	t.Run("temp index", func(t *testing.T) {
   139  		id := NewStorageID(Address{0, 0, 0, 0, 0, 0, 0, 1}, StorageIndex{0, 0, 0, 0, 0, 0, 0, 0})
   140  		b := make([]byte, storageIDSize)
   141  		size, err := id.ToRawBytes(b)
   142  		require.NoError(t, err)
   143  
   144  		want := []byte{0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}
   145  		require.Equal(t, want, b)
   146  		require.Equal(t, storageIDSize, size)
   147  	})
   148  
   149  	t.Run("perm", func(t *testing.T) {
   150  		id := NewStorageID(Address{0, 0, 0, 0, 0, 0, 0, 1}, StorageIndex{0, 0, 0, 0, 0, 0, 0, 2})
   151  		b := make([]byte, storageIDSize)
   152  		size, err := id.ToRawBytes(b)
   153  		require.NoError(t, err)
   154  
   155  		want := []byte{0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2}
   156  		require.Equal(t, want, b)
   157  		require.Equal(t, storageIDSize, size)
   158  	})
   159  }
   160  
   161  func TestStorageIDAddressAsUint64(t *testing.T) {
   162  	t.Run("temp", func(t *testing.T) {
   163  		id := NewStorageID(Address{}, StorageIndex{1})
   164  		require.Equal(t, uint64(0), id.AddressAsUint64())
   165  	})
   166  	t.Run("perm", func(t *testing.T) {
   167  		id := NewStorageID(Address{0, 0, 0, 0, 0, 0, 0, 1}, StorageIndex{1})
   168  		require.Equal(t, uint64(1), id.AddressAsUint64())
   169  	})
   170  }
   171  
   172  func TestStorageIDIndexAsUint64(t *testing.T) {
   173  	t.Run("temp", func(t *testing.T) {
   174  		id := NewStorageID(Address{}, StorageIndex{})
   175  		require.Equal(t, uint64(0), id.IndexAsUint64())
   176  	})
   177  	t.Run("perm", func(t *testing.T) {
   178  		id := NewStorageID(Address{}, StorageIndex{0, 0, 0, 0, 0, 0, 0, 1})
   179  		require.Equal(t, uint64(1), id.IndexAsUint64())
   180  	})
   181  }
   182  
   183  func TestStorageIDValid(t *testing.T) {
   184  	t.Run("undefined", func(t *testing.T) {
   185  		id := StorageIDUndefined
   186  		err := id.Valid()
   187  
   188  		var fatalError *FatalError
   189  		var storageIDError *StorageIDError
   190  		require.Equal(t, 1, errorCategorizationCount(err))
   191  		require.ErrorAs(t, err, &fatalError)
   192  		require.ErrorAs(t, err, &storageIDError)
   193  		require.ErrorAs(t, fatalError, &storageIDError)
   194  	})
   195  	t.Run("temp index", func(t *testing.T) {
   196  		id := StorageID{Address: Address{1}, Index: StorageIndexUndefined}
   197  		err := id.Valid()
   198  
   199  		var fatalError *FatalError
   200  		var storageIDError *StorageIDError
   201  		require.Equal(t, 1, errorCategorizationCount(err))
   202  		require.ErrorAs(t, err, &fatalError)
   203  		require.ErrorAs(t, err, &storageIDError)
   204  		require.ErrorAs(t, fatalError, &storageIDError)
   205  	})
   206  	t.Run("temp address", func(t *testing.T) {
   207  		id := StorageID{Address: AddressUndefined, Index: StorageIndex{1}}
   208  		require.NoError(t, id.Valid())
   209  	})
   210  	t.Run("valid", func(t *testing.T) {
   211  		id := StorageID{Address: Address{1}, Index: StorageIndex{2}}
   212  		require.NoError(t, id.Valid())
   213  	})
   214  }
   215  
   216  func TestStorageIDCompare(t *testing.T) {
   217  	t.Run("same", func(t *testing.T) {
   218  		id1 := NewStorageID(Address{1}, StorageIndex{1})
   219  		id2 := NewStorageID(Address{1}, StorageIndex{1})
   220  		require.Equal(t, 0, id1.Compare(id2))
   221  		require.Equal(t, 0, id2.Compare(id1))
   222  	})
   223  
   224  	t.Run("different address", func(t *testing.T) {
   225  		id1 := NewStorageID(Address{1}, StorageIndex{1})
   226  		id2 := NewStorageID(Address{2}, StorageIndex{1})
   227  		require.Equal(t, -1, id1.Compare(id2))
   228  		require.Equal(t, 1, id2.Compare(id1))
   229  	})
   230  
   231  	t.Run("different index", func(t *testing.T) {
   232  		id1 := NewStorageID(Address{1}, StorageIndex{1})
   233  		id2 := NewStorageID(Address{1}, StorageIndex{2})
   234  		require.Equal(t, -1, id1.Compare(id2))
   235  		require.Equal(t, 1, id2.Compare(id1))
   236  	})
   237  
   238  	t.Run("different address and index", func(t *testing.T) {
   239  		id1 := NewStorageID(Address{1}, StorageIndex{1})
   240  		id2 := NewStorageID(Address{2}, StorageIndex{2})
   241  		require.Equal(t, -1, id1.Compare(id2))
   242  		require.Equal(t, 1, id2.Compare(id1))
   243  	})
   244  }
   245  
   246  func TestLedgerBaseStorageStore(t *testing.T) {
   247  	ledger := newTestLedger()
   248  	baseStorage := NewLedgerBaseStorage(ledger)
   249  
   250  	bytesStored := 0
   251  	values := map[StorageID][]byte{
   252  		{Address{1}, StorageIndex{1}}: {1, 2, 3},
   253  		{Address{1}, StorageIndex{2}}: {4, 5, 6},
   254  	}
   255  
   256  	// Store values
   257  	for id, value := range values {
   258  		err := baseStorage.Store(id, value)
   259  		bytesStored += len(value)
   260  		require.NoError(t, err)
   261  	}
   262  
   263  	// Overwrite stored values
   264  	for id := range values {
   265  		values[id] = append(values[id], []byte{1, 2, 3}...)
   266  		bytesStored += len(values[id])
   267  		err := baseStorage.Store(id, values[id])
   268  		require.NoError(t, err)
   269  	}
   270  
   271  	require.Equal(t, bytesStored, baseStorage.BytesStored())
   272  	require.Equal(t, 0, baseStorage.BytesRetrieved())
   273  
   274  	iterator := ledger.Iterator()
   275  
   276  	count := 0
   277  	for {
   278  		owner, key, value := iterator()
   279  		if owner == nil {
   280  			break
   281  		}
   282  		var id StorageID
   283  		copy(id.Address[:], owner)
   284  		copy(id.Index[:], key[1:])
   285  
   286  		require.True(t, LedgerKeyIsSlabKey(string(key)))
   287  		require.Equal(t, values[id], value)
   288  
   289  		count++
   290  	}
   291  	require.Equal(t, len(values), count)
   292  }
   293  
   294  func TestLedgerBaseStorageRetrieve(t *testing.T) {
   295  	ledger := newTestLedger()
   296  	baseStorage := NewLedgerBaseStorage(ledger)
   297  
   298  	id := StorageID{Address: Address{1}, Index: StorageIndex{1}}
   299  	value := []byte{1, 2, 3}
   300  	bytesStored := 0
   301  	bytesRetrieved := 0
   302  
   303  	// Retrieve value from empty storage
   304  	b, found, err := baseStorage.Retrieve(id)
   305  	require.NoError(t, err)
   306  	require.False(t, found)
   307  	require.Equal(t, 0, len(b))
   308  
   309  	bytesStored += len(value)
   310  	err = baseStorage.Store(id, value)
   311  	require.NoError(t, err)
   312  
   313  	// Retrieve stored value
   314  	b, found, err = baseStorage.Retrieve(id)
   315  	bytesRetrieved += len(b)
   316  	require.NoError(t, err)
   317  	require.True(t, found)
   318  	require.Equal(t, value, b)
   319  
   320  	// Retrieve non-existent value
   321  	id = StorageID{Address: Address{1}, Index: StorageIndex{2}}
   322  	b, found, err = baseStorage.Retrieve(id)
   323  	require.NoError(t, err)
   324  	require.False(t, found)
   325  	require.Nil(t, b)
   326  
   327  	require.Equal(t, bytesStored, baseStorage.BytesStored())
   328  	require.Equal(t, bytesRetrieved, baseStorage.BytesRetrieved())
   329  }
   330  
   331  func TestLedgerBaseStorageRemove(t *testing.T) {
   332  	ledger := newTestLedger()
   333  	baseStorage := NewLedgerBaseStorage(ledger)
   334  
   335  	id := StorageID{Address: Address{1}, Index: StorageIndex{1}}
   336  	value := []byte{1, 2, 3}
   337  
   338  	// Remove value from empty storage
   339  	err := baseStorage.Remove(id)
   340  	require.NoError(t, err)
   341  
   342  	err = baseStorage.Store(id, value)
   343  	require.NoError(t, err)
   344  
   345  	// Remove stored value
   346  	err = baseStorage.Remove(id)
   347  	require.NoError(t, err)
   348  
   349  	// Remove removed value
   350  	err = baseStorage.Remove(id)
   351  	require.NoError(t, err)
   352  
   353  	// Remove non-existent value
   354  	err = baseStorage.Remove(StorageID{Address: id.Address, Index: id.Index.Next()})
   355  	require.NoError(t, err)
   356  
   357  	// Retrieve removed value
   358  	slab, found, err := baseStorage.Retrieve(id)
   359  	require.NoError(t, err)
   360  	require.False(t, found)
   361  	require.Nil(t, slab)
   362  
   363  	iterator := ledger.Iterator()
   364  
   365  	count := 0
   366  	for {
   367  		owner, key, value := iterator()
   368  		if owner == nil {
   369  			break
   370  		}
   371  		var id StorageID
   372  		copy(id.Address[:], owner)
   373  		copy(id.Index[:], key[1:])
   374  
   375  		require.True(t, LedgerKeyIsSlabKey(string(key)))
   376  		require.Nil(t, value)
   377  
   378  		count++
   379  	}
   380  	require.Equal(t, 2, count)
   381  }
   382  
   383  func TestLedgerBaseStorageGenerateStorageID(t *testing.T) {
   384  	ledger := newTestLedger()
   385  	baseStorage := NewLedgerBaseStorage(ledger)
   386  
   387  	address1 := Address{1}
   388  	address2 := Address{2}
   389  
   390  	id, err := baseStorage.GenerateStorageID(address1)
   391  	require.NoError(t, err)
   392  	require.Equal(t, address1, id.Address)
   393  	require.Equal(t, StorageIndex{0, 0, 0, 0, 0, 0, 0, 1}, id.Index)
   394  
   395  	id, err = baseStorage.GenerateStorageID(address1)
   396  	require.NoError(t, err)
   397  	require.Equal(t, address1, id.Address)
   398  	require.Equal(t, StorageIndex{0, 0, 0, 0, 0, 0, 0, 2}, id.Index)
   399  
   400  	id, err = baseStorage.GenerateStorageID(address2)
   401  	require.NoError(t, err)
   402  	require.Equal(t, address2, id.Address)
   403  	require.Equal(t, StorageIndex{0, 0, 0, 0, 0, 0, 0, 1}, id.Index)
   404  }
   405  
   406  func TestBasicSlabStorageStore(t *testing.T) {
   407  	storage := NewBasicSlabStorage(nil, nil, nil, nil)
   408  
   409  	r := newRand(t)
   410  	address := Address{1}
   411  	slabs := map[StorageID]Slab{
   412  		{address, StorageIndex{1}}: generateRandomSlab(address, r),
   413  		{address, StorageIndex{2}}: generateRandomSlab(address, r),
   414  	}
   415  
   416  	// Store values
   417  	for id, slab := range slabs {
   418  		err := storage.Store(id, slab)
   419  		require.NoError(t, err)
   420  	}
   421  
   422  	// Overwrite stored values
   423  	for id := range slabs {
   424  		slab := generateRandomSlab(id.Address, r)
   425  		slabs[id] = slab
   426  		err := storage.Store(id, slab)
   427  		require.NoError(t, err)
   428  	}
   429  
   430  	require.Equal(t, len(slabs), storage.Count())
   431  
   432  	// Retrieve slabs
   433  	for id, want := range slabs {
   434  		slab, found, err := storage.Retrieve(id)
   435  		require.NoError(t, err)
   436  		require.True(t, found)
   437  		require.Equal(t, want, slab)
   438  	}
   439  }
   440  
   441  func TestBasicSlabStorageRetrieve(t *testing.T) {
   442  	storage := NewBasicSlabStorage(nil, nil, nil, nil)
   443  
   444  	r := newRand(t)
   445  	id := StorageID{Address{1}, StorageIndex{1}}
   446  	slab := generateRandomSlab(id.Address, r)
   447  
   448  	// Retrieve value from empty storage
   449  	retrievedSlab, found, err := storage.Retrieve(id)
   450  	require.NoError(t, err)
   451  	require.False(t, found)
   452  	require.Nil(t, retrievedSlab)
   453  
   454  	err = storage.Store(id, slab)
   455  	require.NoError(t, err)
   456  
   457  	// Retrieve stored value
   458  	retrievedSlab, found, err = storage.Retrieve(id)
   459  	require.NoError(t, err)
   460  	require.True(t, found)
   461  	require.Equal(t, slab, retrievedSlab)
   462  
   463  	// Retrieve non-existent value
   464  	id = StorageID{Address: Address{1}, Index: StorageIndex{2}}
   465  	retrievedSlab, found, err = storage.Retrieve(id)
   466  	require.NoError(t, err)
   467  	require.False(t, found)
   468  	require.Nil(t, retrievedSlab)
   469  }
   470  
   471  func TestBasicSlabStorageRemove(t *testing.T) {
   472  	storage := NewBasicSlabStorage(nil, nil, nil, nil)
   473  
   474  	r := newRand(t)
   475  	id := StorageID{Address{1}, StorageIndex{1}}
   476  	slab := generateRandomSlab(id.Address, r)
   477  
   478  	// Remove value from empty storage
   479  	err := storage.Remove(id)
   480  	require.NoError(t, err)
   481  
   482  	err = storage.Store(id, slab)
   483  	require.NoError(t, err)
   484  
   485  	// Remove stored value
   486  	err = storage.Remove(id)
   487  	require.NoError(t, err)
   488  
   489  	// Remove removed value
   490  	err = storage.Remove(id)
   491  	require.NoError(t, err)
   492  
   493  	// Remove non-existent value
   494  	err = storage.Remove(StorageID{Address: id.Address, Index: id.Index.Next()})
   495  	require.NoError(t, err)
   496  
   497  	// Retrieve removed value
   498  	slab, found, err := storage.Retrieve(id)
   499  	require.NoError(t, err)
   500  	require.False(t, found)
   501  	require.Nil(t, slab)
   502  
   503  	require.Equal(t, 0, storage.Count())
   504  }
   505  
   506  func TestBasicSlabStorageGenerateStorageID(t *testing.T) {
   507  	storage := NewBasicSlabStorage(nil, nil, nil, nil)
   508  
   509  	address1 := Address{1}
   510  	address2 := Address{2}
   511  
   512  	id, err := storage.GenerateStorageID(address1)
   513  	require.NoError(t, err)
   514  	require.Equal(t, address1, id.Address)
   515  	require.Equal(t, StorageIndex{0, 0, 0, 0, 0, 0, 0, 1}, id.Index)
   516  
   517  	id, err = storage.GenerateStorageID(address1)
   518  	require.NoError(t, err)
   519  	require.Equal(t, address1, id.Address)
   520  	require.Equal(t, StorageIndex{0, 0, 0, 0, 0, 0, 0, 2}, id.Index)
   521  
   522  	id, err = storage.GenerateStorageID(address2)
   523  	require.NoError(t, err)
   524  	require.Equal(t, address2, id.Address)
   525  	require.Equal(t, StorageIndex{0, 0, 0, 0, 0, 0, 0, 1}, id.Index)
   526  }
   527  
   528  func TestBasicSlabStorageStorageIDs(t *testing.T) {
   529  	r := newRand(t)
   530  	address := Address{1}
   531  	index := StorageIndex{0, 0, 0, 0, 0, 0, 0, 0}
   532  	wantIDs := map[StorageID]bool{
   533  		{Address: address, Index: index.Next()}: true,
   534  		{Address: address, Index: index.Next()}: true,
   535  		{Address: address, Index: index.Next()}: true,
   536  	}
   537  
   538  	storage := NewBasicSlabStorage(nil, nil, nil, nil)
   539  
   540  	// Get storage ids from empty storgae
   541  	ids := storage.StorageIDs()
   542  	require.Equal(t, 0, len(ids))
   543  
   544  	// Store values
   545  	for id := range wantIDs {
   546  		err := storage.Store(id, generateRandomSlab(id.Address, r))
   547  		require.NoError(t, err)
   548  	}
   549  
   550  	// Get storage ids from non-empty storgae
   551  	ids = storage.StorageIDs()
   552  	require.Equal(t, len(wantIDs), len(ids))
   553  
   554  	for _, id := range ids {
   555  		require.True(t, wantIDs[id])
   556  	}
   557  }
   558  
   559  func TestBasicSlabStorageSlabIterat(t *testing.T) {
   560  	r := newRand(t)
   561  	address := Address{1}
   562  	index := StorageIndex{0, 0, 0, 0, 0, 0, 0, 0}
   563  
   564  	id1 := StorageID{Address: address, Index: index.Next()}
   565  	id2 := StorageID{Address: address, Index: index.Next()}
   566  	id3 := StorageID{Address: address, Index: index.Next()}
   567  
   568  	want := map[StorageID]Slab{
   569  		id1: generateRandomSlab(id1.Address, r),
   570  		id2: generateRandomSlab(id2.Address, r),
   571  		id3: generateRandomSlab(id3.Address, r),
   572  	}
   573  
   574  	storage := NewBasicSlabStorage(nil, nil, nil, nil)
   575  
   576  	// Store values
   577  	for id, slab := range want {
   578  		err := storage.Store(id, slab)
   579  		require.NoError(t, err)
   580  	}
   581  
   582  	iterator, err := storage.SlabIterator()
   583  	require.NoError(t, err)
   584  
   585  	count := 0
   586  	for {
   587  		id, slab := iterator()
   588  		if id == StorageIDUndefined {
   589  			break
   590  		}
   591  		require.NotNil(t, want[id])
   592  		require.Equal(t, want[id], slab)
   593  		count++
   594  	}
   595  	require.Equal(t, len(want), count)
   596  }
   597  
   598  func TestPersistentStorage(t *testing.T) {
   599  
   600  	encMode, err := cbor.EncOptions{}.EncMode()
   601  	require.NoError(t, err)
   602  
   603  	decMode, err := cbor.DecOptions{}.DecMode()
   604  	require.NoError(t, err)
   605  
   606  	t.Run("empty storage", func(t *testing.T) {
   607  		baseStorage := NewInMemBaseStorage()
   608  		storage := NewPersistentSlabStorage(baseStorage, encMode, decMode, nil, nil)
   609  
   610  		tempStorageID, err := NewStorageIDFromRawBytes([]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1})
   611  		require.NoError(t, err)
   612  
   613  		permStorageID, err := NewStorageIDFromRawBytes([]byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1})
   614  		require.NoError(t, err)
   615  
   616  		_, found, err := storage.Retrieve(tempStorageID)
   617  		require.NoError(t, err)
   618  		require.False(t, found)
   619  
   620  		_, found, err = storage.Retrieve(permStorageID)
   621  		require.NoError(t, err)
   622  		require.False(t, found)
   623  
   624  		require.Equal(t, uint(0), storage.DeltasWithoutTempAddresses())
   625  		require.Equal(t, uint(0), storage.Deltas())
   626  		require.Equal(t, uint64(0), storage.DeltasSizeWithoutTempAddresses())
   627  	})
   628  
   629  	t.Run("temp address", func(t *testing.T) {
   630  
   631  		r := newRand(t)
   632  
   633  		baseStorage := NewInMemBaseStorage()
   634  		storage := NewPersistentSlabStorage(baseStorage, encMode, decMode, nil, nil)
   635  
   636  		tempStorageID, err := NewStorageIDFromRawBytes([]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1})
   637  		require.NoError(t, err)
   638  
   639  		permStorageID, err := NewStorageIDFromRawBytes([]byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1})
   640  		require.NoError(t, err)
   641  
   642  		slab1 := generateRandomSlab(tempStorageID.Address, r)
   643  		slab2 := generateRandomSlab(permStorageID.Address, r)
   644  
   645  		// no temp ids should be in the base storage
   646  		err = storage.Store(tempStorageID, slab1)
   647  		require.NoError(t, err)
   648  		require.Equal(t, uint64(0), storage.DeltasSizeWithoutTempAddresses())
   649  
   650  		err = storage.Store(permStorageID, slab2)
   651  		require.NoError(t, err)
   652  
   653  		require.Equal(t, uint(1), storage.DeltasWithoutTempAddresses())
   654  		require.Equal(t, uint(2), storage.Deltas())
   655  		require.True(t, storage.DeltasSizeWithoutTempAddresses() > 0)
   656  		require.Equal(t, uint64(slab2.ByteSize()), storage.DeltasSizeWithoutTempAddresses())
   657  
   658  		err = storage.Commit()
   659  		require.NoError(t, err)
   660  
   661  		require.Equal(t, uint(0), storage.DeltasWithoutTempAddresses())
   662  		require.Equal(t, uint(1), storage.Deltas())
   663  		require.Equal(t, uint64(0), storage.DeltasSizeWithoutTempAddresses())
   664  
   665  		// Slab with temp storage id is NOT persisted in base storage.
   666  		_, found, err := baseStorage.Retrieve(tempStorageID)
   667  		require.NoError(t, err)
   668  		require.False(t, found)
   669  
   670  		// Slab with temp storage id is cached in storage.
   671  		_, found, err = storage.Retrieve(tempStorageID)
   672  		require.NoError(t, err)
   673  		require.True(t, found)
   674  
   675  		// Slab with perm storage id is persisted in base storage.
   676  		_, found, err = baseStorage.Retrieve(permStorageID)
   677  		require.NoError(t, err)
   678  		require.True(t, found)
   679  
   680  		// Slab with perm storage id is cached in storage.
   681  		_, found, err = storage.Retrieve(permStorageID)
   682  		require.NoError(t, err)
   683  		require.True(t, found)
   684  
   685  		// Remove slab with perm storage id
   686  		err = storage.Remove(permStorageID)
   687  		require.NoError(t, err)
   688  
   689  		// Remove slab with temp storage id
   690  		err = storage.Remove(tempStorageID)
   691  		require.NoError(t, err)
   692  
   693  		require.Equal(t, uint(1), storage.DeltasWithoutTempAddresses())
   694  		require.Equal(t, uint64(0), storage.DeltasSizeWithoutTempAddresses())
   695  
   696  		err = storage.Commit()
   697  		require.NoError(t, err)
   698  
   699  		// Slab with perm storage id is removed from base storage.
   700  		_, found, err = baseStorage.Retrieve(permStorageID)
   701  		require.NoError(t, err)
   702  		require.False(t, found)
   703  
   704  		// Slab with perm storage id is removed from cache in storage.
   705  		_, found, err = storage.Retrieve(permStorageID)
   706  		require.NoError(t, err)
   707  		require.False(t, found)
   708  
   709  		// Slab with temp storage id is removed from cache in storage.
   710  		_, found, err = storage.Retrieve(tempStorageID)
   711  		require.NoError(t, err)
   712  		require.False(t, found)
   713  
   714  		require.Equal(t, uint(0), storage.DeltasWithoutTempAddresses())
   715  		require.Equal(t, uint(1), storage.Deltas())
   716  		require.Equal(t, uint64(0), storage.DeltasSizeWithoutTempAddresses())
   717  	})
   718  
   719  	t.Run("commit", func(t *testing.T) {
   720  		numberOfAccounts := 100
   721  		numberOfSlabsPerAccount := 10
   722  
   723  		r := newRand(t)
   724  		baseStorage := newAccessOrderTrackerBaseStorage()
   725  		storage := NewPersistentSlabStorage(baseStorage, encMode, decMode, nil, nil)
   726  		baseStorage2 := newAccessOrderTrackerBaseStorage()
   727  		storageWithFastCommit := NewPersistentSlabStorage(baseStorage2, encMode, decMode, nil, nil)
   728  
   729  		simpleMap := make(map[StorageID][]byte)
   730  		slabSize := uint64(0)
   731  		// test random updates apply commit and check the order of committed values
   732  		for i := 0; i < numberOfAccounts; i++ {
   733  			for j := 0; j < numberOfSlabsPerAccount; j++ {
   734  				addr := generateRandomAddress(r)
   735  				slab := generateRandomSlab(addr, r)
   736  				slabSize += uint64(slab.ByteSize())
   737  
   738  				storageID, err := storage.GenerateStorageID(addr)
   739  				require.NoError(t, err)
   740  				err = storage.Store(storageID, slab)
   741  				require.NoError(t, err)
   742  
   743  				storageID2, err := storageWithFastCommit.GenerateStorageID(addr)
   744  				require.NoError(t, err)
   745  				err = storageWithFastCommit.Store(storageID2, slab)
   746  				require.NoError(t, err)
   747  
   748  				// capture data for accuracy testing
   749  				simpleMap[storageID], err = Encode(slab, encMode)
   750  				require.NoError(t, err)
   751  			}
   752  		}
   753  
   754  		require.True(t, storage.DeltasSizeWithoutTempAddresses() > 0)
   755  		require.Equal(t, slabSize, storage.DeltasSizeWithoutTempAddresses())
   756  		require.True(t, storageWithFastCommit.DeltasSizeWithoutTempAddresses() > 0)
   757  		require.Equal(t, slabSize, storageWithFastCommit.DeltasSizeWithoutTempAddresses())
   758  
   759  		err = storage.Commit()
   760  		require.NoError(t, err)
   761  		require.Equal(t, uint64(0), storage.DeltasSizeWithoutTempAddresses())
   762  
   763  		err = storageWithFastCommit.FastCommit(10)
   764  		require.NoError(t, err)
   765  		require.Equal(t, uint64(0), storageWithFastCommit.DeltasSizeWithoutTempAddresses())
   766  
   767  		require.Equal(t, len(simpleMap), storage.Count())
   768  		require.Equal(t, len(simpleMap), storageWithFastCommit.Count())
   769  
   770  		// check update functionality
   771  		for sid, value := range simpleMap {
   772  			storedValue, found, err := baseStorage.Retrieve(sid)
   773  			require.NoError(t, err)
   774  			require.True(t, found)
   775  			require.Equal(t, value, storedValue)
   776  
   777  			storedValue, found, err = baseStorage2.Retrieve(sid)
   778  			require.NoError(t, err)
   779  			require.True(t, found)
   780  			require.Equal(t, value, storedValue)
   781  		}
   782  
   783  		// compare orders
   784  		require.Equal(t, baseStorage.SegTouchOrder(), baseStorage2.SegTouchOrder())
   785  
   786  		// remove all slabs from storage
   787  		for sid := range simpleMap {
   788  			err = storage.Remove(sid)
   789  			require.NoError(t, err)
   790  			require.Equal(t, uint64(0), storage.DeltasSizeWithoutTempAddresses())
   791  
   792  			err = storageWithFastCommit.Remove(sid)
   793  			require.NoError(t, err)
   794  			require.Equal(t, uint64(0), storageWithFastCommit.DeltasSizeWithoutTempAddresses())
   795  		}
   796  
   797  		require.Equal(t, uint(len(simpleMap)), storage.DeltasWithoutTempAddresses())
   798  		require.Equal(t, uint(len(simpleMap)), storageWithFastCommit.DeltasWithoutTempAddresses())
   799  
   800  		err = storage.Commit()
   801  		require.NoError(t, err)
   802  
   803  		err = storageWithFastCommit.FastCommit(10)
   804  		require.NoError(t, err)
   805  
   806  		require.Equal(t, 0, storage.Count())
   807  		require.Equal(t, 0, storageWithFastCommit.Count())
   808  		require.Equal(t, uint64(0), storage.DeltasSizeWithoutTempAddresses())
   809  		require.Equal(t, uint64(0), storageWithFastCommit.DeltasSizeWithoutTempAddresses())
   810  
   811  		// check remove functionality
   812  		for sid := range simpleMap {
   813  			storedValue, found, err := storage.Retrieve(sid)
   814  			require.NoError(t, err)
   815  			require.False(t, found)
   816  			require.Nil(t, storedValue)
   817  
   818  			storedValue, found, err = storageWithFastCommit.Retrieve(sid)
   819  			require.NoError(t, err)
   820  			require.False(t, found)
   821  			require.Nil(t, storedValue)
   822  		}
   823  
   824  		// compare orders
   825  		require.Equal(t, baseStorage.SegTouchOrder(), baseStorage2.SegTouchOrder())
   826  	})
   827  
   828  	t.Run("commit with error", func(t *testing.T) {
   829  
   830  		baseStorage := NewInMemBaseStorage()
   831  		storage := NewPersistentSlabStorage(baseStorage, encMode, decMode, nil, nil)
   832  
   833  		// Encoding slabWithNonStorable returns error.
   834  		slabWithNonStorable := &ArrayDataSlab{
   835  			header:   ArraySlabHeader{size: uint32(1), count: uint32(1)},
   836  			elements: []Storable{nonStorable{}},
   837  		}
   838  		// Encoding slabWithSlowStorable takes some time which delays
   839  		// sending encoding result to results channel.
   840  		slabWithSlowStorable := &ArrayDataSlab{
   841  			header:   ArraySlabHeader{size: uint32(3), count: uint32(1)},
   842  			elements: []Storable{newSlowStorable(1)},
   843  		}
   844  
   845  		address := Address{1}
   846  
   847  		id, err := storage.GenerateStorageID(address)
   848  		require.NoError(t, err)
   849  
   850  		err = storage.Store(id, slabWithNonStorable)
   851  		require.NoError(t, err)
   852  
   853  		for i := 0; i < 500; i++ {
   854  			id, err := storage.GenerateStorageID(address)
   855  			require.NoError(t, err)
   856  
   857  			err = storage.Store(id, slabWithSlowStorable)
   858  			require.NoError(t, err)
   859  		}
   860  
   861  		err = storage.FastCommit(2)
   862  		require.Equal(t, 1, errorCategorizationCount(err))
   863  
   864  		var externalError *ExternalError
   865  		require.ErrorAs(t, err, &externalError)
   866  		require.ErrorIs(t, err, errEncodeNonStorable)
   867  		require.ErrorIs(t, externalError.Unwrap(), errEncodeNonStorable)
   868  	})
   869  }
   870  
   871  func TestPersistentStorageSlabIterator(t *testing.T) {
   872  	t.Run("empty storage", func(t *testing.T) {
   873  		storage := newTestPersistentStorage(t)
   874  
   875  		iterator, err := storage.SlabIterator()
   876  		require.NoError(t, err)
   877  
   878  		count := 0
   879  		for {
   880  			id, _ := iterator()
   881  			if id == StorageIDUndefined {
   882  				break
   883  			}
   884  			count++
   885  		}
   886  		require.Equal(t, 0, count)
   887  	})
   888  
   889  	t.Run("not-empty storage", func(t *testing.T) {
   890  
   891  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
   892  		id1 := StorageID{Address: address, Index: StorageIndex{0, 0, 0, 0, 0, 0, 0, 1}}
   893  		id2 := StorageID{Address: address, Index: StorageIndex{0, 0, 0, 0, 0, 0, 0, 2}}
   894  		id3 := StorageID{Address: address, Index: StorageIndex{0, 0, 0, 0, 0, 0, 0, 3}}
   895  		id4 := StorageID{Address: address, Index: StorageIndex{0, 0, 0, 0, 0, 0, 0, 4}}
   896  
   897  		data := map[StorageID][]byte{
   898  			// (metadata slab) headers: [{id:2 size:228 count:9} {id:3 size:270 count:11} ]
   899  			id1: {
   900  				// extra data
   901  				// version
   902  				0x00,
   903  				// extra data flag
   904  				0x81,
   905  				// array of extra data
   906  				0x81,
   907  				// type info
   908  				0x18, 0x2a,
   909  
   910  				// version
   911  				0x00,
   912  				// array meta data slab flag
   913  				0x81,
   914  				// child header count
   915  				0x00, 0x02,
   916  				// child header 1 (storage id, count, size)
   917  				0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
   918  				0x00, 0x00, 0x00, 0x09,
   919  				0x00, 0x00, 0x00, 0xe4,
   920  				// child header 2
   921  				0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
   922  				0x00, 0x00, 0x00, 0x0b,
   923  				0x00, 0x00, 0x01, 0x0e,
   924  			},
   925  
   926  			// (data slab) next: 3, data: [aaaaaaaaaaaaaaaaaaaaaa ... aaaaaaaaaaaaaaaaaaaaaa]
   927  			id2: {
   928  				// version
   929  				0x00,
   930  				// array data slab flag
   931  				0x00,
   932  				// next storage id
   933  				0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
   934  				// CBOR encoded array head (fixed size 3 byte)
   935  				0x99, 0x00, 0x09,
   936  				// CBOR encoded array elements
   937  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
   938  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
   939  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
   940  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
   941  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
   942  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
   943  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
   944  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
   945  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
   946  			},
   947  
   948  			// (data slab) next: 0, data: [aaaaaaaaaaaaaaaaaaaaaa ... StorageID(...)]
   949  			id3: {
   950  				// version
   951  				0x00,
   952  				// array data slab flag
   953  				0x40,
   954  				// next storage id
   955  				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   956  				// CBOR encoded array head (fixed size 3 byte)
   957  				0x99, 0x00, 0x0b,
   958  				// CBOR encoded array elements
   959  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
   960  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
   961  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
   962  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
   963  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
   964  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
   965  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
   966  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
   967  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
   968  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
   969  				0xd8, 0xff, 0x50, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
   970  			},
   971  
   972  			// (data slab) next: 0, data: [0]
   973  			id4: {
   974  				// extra data
   975  				// version
   976  				0x00,
   977  				// extra data flag
   978  				0x80,
   979  				// array of extra data
   980  				0x81,
   981  				// type info
   982  				0x18, 0x2b,
   983  
   984  				// version
   985  				0x00,
   986  				// array data slab flag
   987  				0x80,
   988  				// CBOR encoded array head (fixed size 3 byte)
   989  				0x99, 0x00, 0x01,
   990  				// CBOR encoded array elements
   991  				0xd8, 0xa4, 0x00,
   992  			},
   993  		}
   994  
   995  		storage := newTestPersistentStorageWithData(t, data)
   996  
   997  		_, err := NewArrayWithRootID(storage, id1)
   998  		require.NoError(t, err)
   999  
  1000  		iterator, err := storage.SlabIterator()
  1001  		require.NoError(t, err)
  1002  
  1003  		count := 0
  1004  		for {
  1005  			id, slab := iterator()
  1006  			if id == StorageIDUndefined {
  1007  				break
  1008  			}
  1009  
  1010  			encodedSlab, err := Encode(slab, storage.cborEncMode)
  1011  			require.NoError(t, err)
  1012  
  1013  			require.Equal(t, encodedSlab, data[id])
  1014  			count++
  1015  		}
  1016  		require.Equal(t, len(data), count)
  1017  	})
  1018  }
  1019  
  1020  func TestPersistentStorageGenerateStorageID(t *testing.T) {
  1021  	baseStorage := NewInMemBaseStorage()
  1022  	storage := NewPersistentSlabStorage(baseStorage, nil, nil, nil, nil)
  1023  
  1024  	t.Run("temp address", func(t *testing.T) {
  1025  		address := Address{}
  1026  
  1027  		id, err := storage.GenerateStorageID(address)
  1028  		require.NoError(t, err)
  1029  		require.Equal(t, address, id.Address)
  1030  		require.Equal(t, StorageIndex{0, 0, 0, 0, 0, 0, 0, 1}, id.Index)
  1031  
  1032  		id, err = storage.GenerateStorageID(address)
  1033  		require.NoError(t, err)
  1034  		require.Equal(t, address, id.Address)
  1035  		require.Equal(t, StorageIndex{0, 0, 0, 0, 0, 0, 0, 2}, id.Index)
  1036  	})
  1037  	t.Run("perm address", func(t *testing.T) {
  1038  		address := Address{1}
  1039  
  1040  		id, err := storage.GenerateStorageID(address)
  1041  		require.NoError(t, err)
  1042  		require.Equal(t, address, id.Address)
  1043  		require.Equal(t, StorageIndex{0, 0, 0, 0, 0, 0, 0, 1}, id.Index)
  1044  
  1045  		id, err = storage.GenerateStorageID(address)
  1046  		require.NoError(t, err)
  1047  		require.Equal(t, address, id.Address)
  1048  		require.Equal(t, StorageIndex{0, 0, 0, 0, 0, 0, 0, 2}, id.Index)
  1049  	})
  1050  }
  1051  
  1052  func generateRandomSlab(address Address, r *rand.Rand) Slab {
  1053  	storable := Uint64Value(r.Uint64())
  1054  
  1055  	return &ArrayDataSlab{
  1056  		header: ArraySlabHeader{
  1057  			id:    NewStorageID(address, StorageIndex{1}),
  1058  			size:  arrayRootDataSlabPrefixSize + storable.ByteSize(),
  1059  			count: 1,
  1060  		},
  1061  		elements: []Storable{storable},
  1062  	}
  1063  }
  1064  
  1065  func generateRandomAddress(r *rand.Rand) Address {
  1066  	address := Address{}
  1067  	r.Read(address[:])
  1068  	return address
  1069  }
  1070  
  1071  type accessOrderTrackerBaseStorage struct {
  1072  	segTouchOrder []StorageID
  1073  	indexReqOrder []Address
  1074  	segments      map[StorageID][]byte
  1075  	storageIndex  map[Address]StorageIndex
  1076  }
  1077  
  1078  func newAccessOrderTrackerBaseStorage() *accessOrderTrackerBaseStorage {
  1079  	return &accessOrderTrackerBaseStorage{
  1080  		segTouchOrder: make([]StorageID, 0),
  1081  		indexReqOrder: make([]Address, 0),
  1082  		segments:      make(map[StorageID][]byte),
  1083  		storageIndex:  make(map[Address]StorageIndex),
  1084  	}
  1085  }
  1086  
  1087  func (s *accessOrderTrackerBaseStorage) SegTouchOrder() []StorageID {
  1088  	return s.segTouchOrder
  1089  }
  1090  
  1091  func (s *accessOrderTrackerBaseStorage) Retrieve(id StorageID) ([]byte, bool, error) {
  1092  	s.segTouchOrder = append(s.segTouchOrder, id)
  1093  	seg, ok := s.segments[id]
  1094  	return seg, ok, nil
  1095  }
  1096  
  1097  func (s *accessOrderTrackerBaseStorage) Store(id StorageID, data []byte) error {
  1098  	s.segTouchOrder = append(s.segTouchOrder, id)
  1099  	s.segments[id] = data
  1100  	return nil
  1101  }
  1102  
  1103  func (s *accessOrderTrackerBaseStorage) Remove(id StorageID) error {
  1104  	s.segTouchOrder = append(s.segTouchOrder, id)
  1105  	delete(s.segments, id)
  1106  	return nil
  1107  }
  1108  
  1109  func (s *accessOrderTrackerBaseStorage) GenerateStorageID(address Address) (StorageID, error) {
  1110  	s.indexReqOrder = append(s.indexReqOrder, address)
  1111  
  1112  	index := s.storageIndex[address]
  1113  	nextIndex := index.Next()
  1114  
  1115  	s.storageIndex[address] = nextIndex
  1116  	return NewStorageID(address, nextIndex), nil
  1117  }
  1118  
  1119  func (s *accessOrderTrackerBaseStorage) SegmentCounts() int { return len(s.segments) }
  1120  
  1121  func (s *accessOrderTrackerBaseStorage) Size() int { return 0 }
  1122  
  1123  func (s *accessOrderTrackerBaseStorage) BytesRetrieved() int { return 0 }
  1124  
  1125  func (s *accessOrderTrackerBaseStorage) BytesStored() int { return 0 }
  1126  
  1127  func (s *accessOrderTrackerBaseStorage) SegmentsReturned() int { return 0 }
  1128  
  1129  func (s *accessOrderTrackerBaseStorage) SegmentsUpdated() int { return 0 }
  1130  
  1131  func (s *accessOrderTrackerBaseStorage) SegmentsTouched() int { return 0 }
  1132  
  1133  func (s *accessOrderTrackerBaseStorage) ResetReporter() {}
  1134  
  1135  type testLedger struct {
  1136  	values map[string][]byte
  1137  	index  map[string]StorageIndex
  1138  }
  1139  
  1140  var _ Ledger = &testLedger{}
  1141  
  1142  func newTestLedger() *testLedger {
  1143  	return &testLedger{
  1144  		values: make(map[string][]byte),
  1145  		index:  make(map[string]StorageIndex),
  1146  	}
  1147  }
  1148  
  1149  func (l *testLedger) GetValue(owner, key []byte) (value []byte, err error) {
  1150  	value = l.values[l.key(owner, key)]
  1151  	return value, nil
  1152  }
  1153  
  1154  func (l *testLedger) SetValue(owner, key, value []byte) (err error) {
  1155  	l.values[l.key(owner, key)] = value
  1156  	return nil
  1157  }
  1158  
  1159  func (l *testLedger) ValueExists(owner, key []byte) (exists bool, err error) {
  1160  	value := l.values[l.key(owner, key)]
  1161  	return len(value) > 0, nil
  1162  }
  1163  
  1164  func (l *testLedger) AllocateStorageIndex(owner []byte) (StorageIndex, error) {
  1165  	index := l.index[string(owner)]
  1166  	next := index.Next()
  1167  	l.index[string(owner)] = next
  1168  	return next, nil
  1169  }
  1170  
  1171  func (l *testLedger) key(owner, key []byte) string {
  1172  	return strings.Join([]string{string(owner), string(key)}, "|")
  1173  }
  1174  
  1175  type ledgerIterationFunc func() (owner, key, value []byte)
  1176  
  1177  func (l *testLedger) Iterator() ledgerIterationFunc {
  1178  	keys := make([]string, 0, len(l.values))
  1179  	for k := range l.values {
  1180  		keys = append(keys, k)
  1181  	}
  1182  
  1183  	i := 0
  1184  	return func() (owner, key, value []byte) {
  1185  		if i >= len(keys) {
  1186  			return nil, nil, nil
  1187  		}
  1188  
  1189  		s := strings.Split(keys[i], "|")
  1190  		owner, key = []byte(s[0]), []byte(s[1])
  1191  		value = l.values[keys[i]]
  1192  		i++
  1193  		return owner, key, value
  1194  	}
  1195  }
  1196  
  1197  func (l *testLedger) Count() int {
  1198  	return len(l.values)
  1199  }
  1200  
  1201  var errEncodeNonStorable = errors.New("failed to encode non-storable")
  1202  
  1203  // nonStorable can't be encoded successfully.
  1204  type nonStorable struct{}
  1205  
  1206  func (nonStorable) Encode(_ *Encoder) error {
  1207  	return errEncodeNonStorable
  1208  }
  1209  
  1210  func (nonStorable) ByteSize() uint32 {
  1211  	return 1
  1212  }
  1213  
  1214  func (v nonStorable) StoredValue(_ SlabStorage) (Value, error) {
  1215  	return v, nil
  1216  }
  1217  
  1218  func (nonStorable) ChildStorables() []Storable {
  1219  	return nil
  1220  }
  1221  
  1222  func (v nonStorable) Storable(_ SlabStorage, _ Address, _ uint64) (Storable, error) {
  1223  	return v, nil
  1224  }
  1225  
  1226  type slowStorable struct {
  1227  	Uint8Value
  1228  }
  1229  
  1230  func newSlowStorable(i uint8) slowStorable {
  1231  	return slowStorable{
  1232  		Uint8Value: Uint8Value(i),
  1233  	}
  1234  }
  1235  
  1236  // slowStorable.Encode is used to reproduce a
  1237  // panic. It needs to be slow enough
  1238  // when called by FastCommit() compared to
  1239  // to a non-slow Encode function returning an error.
  1240  // See Atree issue #240.
  1241  func (s slowStorable) Encode(encoder *Encoder) error {
  1242  	// Use division in a loop to slow down this function
  1243  	n := 1.0
  1244  	for i := 0; i < 2000; i++ {
  1245  		n = (n + float64(i)) / 3.14
  1246  	}
  1247  	runtime.KeepAlive(n)
  1248  	return s.Uint8Value.Encode(encoder)
  1249  }