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

     1  /*
     2   * Atree - Scalable Arrays and Ordered Maps
     3   *
     4   * Copyright 2021 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"
    24  	"math/rand"
    25  	"reflect"
    26  	"strings"
    27  	"testing"
    28  
    29  	"github.com/stretchr/testify/require"
    30  )
    31  
    32  func verifyEmptyArray(
    33  	t *testing.T,
    34  	storage *PersistentSlabStorage,
    35  	typeInfo TypeInfo,
    36  	address Address,
    37  	array *Array,
    38  ) {
    39  	verifyArray(t, storage, typeInfo, address, array, nil, false)
    40  }
    41  
    42  // verifyArray verifies array elements and validates serialization and in-memory slab tree.
    43  func verifyArray(
    44  	t *testing.T,
    45  	storage *PersistentSlabStorage,
    46  	typeInfo TypeInfo,
    47  	address Address,
    48  	array *Array,
    49  	values []Value,
    50  	hasNestedArrayMapElement bool,
    51  ) {
    52  	require.True(t, typeInfoComparator(typeInfo, array.Type()))
    53  	require.Equal(t, address, array.Address())
    54  	require.Equal(t, uint64(len(values)), array.Count())
    55  
    56  	var err error
    57  
    58  	// Verify array elements
    59  	for i, v := range values {
    60  		s, err := array.Get(uint64(i))
    61  		require.NoError(t, err)
    62  
    63  		e, err := s.StoredValue(array.Storage)
    64  		require.NoError(t, err)
    65  
    66  		valueEqual(t, typeInfoComparator, v, e)
    67  	}
    68  
    69  	// Verify array elements by iterator
    70  	i := 0
    71  	err = array.Iterate(func(v Value) (bool, error) {
    72  		valueEqual(t, typeInfoComparator, values[i], v)
    73  		i++
    74  		return true, nil
    75  	})
    76  	require.NoError(t, err)
    77  	require.Equal(t, len(values), i)
    78  
    79  	// Verify in-memory slabs
    80  	err = ValidArray(array, typeInfo, typeInfoComparator, hashInputProvider)
    81  	if err != nil {
    82  		PrintArray(array)
    83  	}
    84  	require.NoError(t, err)
    85  
    86  	// Verify slab serializations
    87  	err = ValidArraySerialization(
    88  		array,
    89  		storage.cborDecMode,
    90  		storage.cborEncMode,
    91  		storage.DecodeStorable,
    92  		storage.DecodeTypeInfo,
    93  		func(a, b Storable) bool {
    94  			return reflect.DeepEqual(a, b)
    95  		},
    96  	)
    97  	if err != nil {
    98  		PrintArray(array)
    99  	}
   100  	require.NoError(t, err)
   101  
   102  	// Check storage slab tree
   103  	rootIDSet, err := CheckStorageHealth(storage, 1)
   104  	require.NoError(t, err)
   105  
   106  	rootIDs := make([]StorageID, 0, len(rootIDSet))
   107  	for id := range rootIDSet {
   108  		rootIDs = append(rootIDs, id)
   109  	}
   110  	require.Equal(t, 1, len(rootIDs))
   111  	require.Equal(t, array.StorageID(), rootIDs[0])
   112  
   113  	if !hasNestedArrayMapElement {
   114  		// Need to call Commit before calling storage.Count() for PersistentSlabStorage.
   115  		err = storage.Commit()
   116  		require.NoError(t, err)
   117  
   118  		stats, err := GetArrayStats(array)
   119  		require.NoError(t, err)
   120  		require.Equal(t, stats.SlabCount(), uint64(storage.Count()))
   121  
   122  		if len(values) == 0 {
   123  			// Verify slab count for empty array
   124  			require.Equal(t, uint64(1), stats.DataSlabCount)
   125  			require.Equal(t, uint64(0), stats.MetaDataSlabCount)
   126  			require.Equal(t, uint64(0), stats.StorableSlabCount)
   127  		}
   128  	}
   129  }
   130  
   131  func TestArrayAppendAndGet(t *testing.T) {
   132  	// With slab size 256 bytes, number of array elements equal 4096,
   133  	// element values equal 0-4095, array tree will be 3 levels,
   134  	// with 14 metadata slabs, and 109 data slabs.
   135  
   136  	SetThreshold(256)
   137  	defer SetThreshold(1024)
   138  
   139  	const arraySize = 4096
   140  
   141  	typeInfo := testTypeInfo{42}
   142  	storage := newTestPersistentStorage(t)
   143  	address := Address{1, 2, 3, 4, 5, 6, 7, 8}
   144  
   145  	array, err := NewArray(storage, address, typeInfo)
   146  	require.NoError(t, err)
   147  
   148  	values := make([]Value, arraySize)
   149  	for i := uint64(0); i < arraySize; i++ {
   150  		v := Uint64Value(i)
   151  		values[i] = v
   152  		err := array.Append(v)
   153  		require.NoError(t, err)
   154  	}
   155  
   156  	storable, err := array.Get(array.Count())
   157  	require.Nil(t, storable)
   158  	require.Equal(t, 1, errorCategorizationCount(err))
   159  
   160  	var userError *UserError
   161  	var indexOutOfBoundsError *IndexOutOfBoundsError
   162  	require.ErrorAs(t, err, &userError)
   163  	require.ErrorAs(t, err, &indexOutOfBoundsError)
   164  	require.ErrorAs(t, userError, &indexOutOfBoundsError)
   165  
   166  	verifyArray(t, storage, typeInfo, address, array, values, false)
   167  }
   168  
   169  func TestArraySetAndGet(t *testing.T) {
   170  
   171  	t.Run("new elements with similar bytesize", func(t *testing.T) {
   172  		const arraySize = 4096
   173  
   174  		typeInfo := testTypeInfo{42}
   175  		storage := newTestPersistentStorage(t)
   176  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
   177  
   178  		array, err := NewArray(storage, address, typeInfo)
   179  		require.NoError(t, err)
   180  
   181  		values := make([]Value, arraySize)
   182  		for i := uint64(0); i < arraySize; i++ {
   183  			v := Uint64Value(i)
   184  			values[i] = v
   185  			err := array.Append(v)
   186  			require.NoError(t, err)
   187  		}
   188  
   189  		verifyArray(t, storage, typeInfo, address, array, values, false)
   190  
   191  		for i := uint64(0); i < arraySize; i++ {
   192  			oldValue := values[i]
   193  			newValue := Uint64Value(i * 10)
   194  			values[i] = newValue
   195  
   196  			existingStorable, err := array.Set(i, newValue)
   197  			require.NoError(t, err)
   198  
   199  			existingValue, err := existingStorable.StoredValue(storage)
   200  			require.NoError(t, err)
   201  			valueEqual(t, typeInfoComparator, oldValue, existingValue)
   202  		}
   203  
   204  		verifyArray(t, storage, typeInfo, address, array, values, false)
   205  	})
   206  
   207  	// This tests slabs splitting and root slab reassignment caused by Set operation.
   208  	t.Run("new elements with larger bytesize", func(t *testing.T) {
   209  		// With slab size 256 bytes, number of array elements equal 50,
   210  		// element values equal 0-49, array tree will be 1 level,
   211  		// with 0 metadata slab, and 1 data slab (root).
   212  		// When elements are overwritten with values from math.MaxUint64-49 to math.MaxUint64,
   213  		// array tree is 2 levels, with 1 metadata slab, and 2 data slabs.
   214  
   215  		const arraySize = 50
   216  
   217  		SetThreshold(256)
   218  		defer SetThreshold(1024)
   219  
   220  		typeInfo := testTypeInfo{42}
   221  		storage := newTestPersistentStorage(t)
   222  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
   223  
   224  		array, err := NewArray(storage, address, typeInfo)
   225  		require.NoError(t, err)
   226  
   227  		values := make([]Value, arraySize)
   228  		for i := uint64(0); i < arraySize; i++ {
   229  			v := Uint64Value(i)
   230  			values[i] = v
   231  			err := array.Append(v)
   232  			require.NoError(t, err)
   233  		}
   234  
   235  		verifyArray(t, storage, typeInfo, address, array, values, false)
   236  
   237  		for i := uint64(0); i < arraySize; i++ {
   238  			oldValue := values[i]
   239  			newValue := Uint64Value(math.MaxUint64 - arraySize + i + 1)
   240  			values[i] = newValue
   241  
   242  			existingStorable, err := array.Set(i, newValue)
   243  			require.NoError(t, err)
   244  
   245  			existingValue, err := existingStorable.StoredValue(storage)
   246  			require.NoError(t, err)
   247  			valueEqual(t, typeInfoComparator, oldValue, existingValue)
   248  		}
   249  
   250  		verifyArray(t, storage, typeInfo, address, array, values, false)
   251  	})
   252  
   253  	// This tests slabs merging and root slab reassignment caused by Set operation.
   254  	t.Run("new elements with smaller bytesize", func(t *testing.T) {
   255  
   256  		// With slab size 256 bytes, number of array elements equal 50,
   257  		// element values equal math.MaxUint64-49 to math.MaxUint64,
   258  		// array tree is 2 levels, with 1 metadata slab, and 2 data slabs.
   259  		// When elements are overwritten with values from 0-49,
   260  		// array tree will be 1 level, with 0 metadata slab, and 1 data slab (root).
   261  
   262  		const arraySize = 50
   263  
   264  		SetThreshold(256)
   265  		defer SetThreshold(1024)
   266  
   267  		typeInfo := testTypeInfo{42}
   268  		storage := newTestPersistentStorage(t)
   269  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
   270  
   271  		array, err := NewArray(storage, address, typeInfo)
   272  		require.NoError(t, err)
   273  
   274  		values := make([]Value, arraySize)
   275  		for i := uint64(0); i < arraySize; i++ {
   276  			v := Uint64Value(math.MaxUint64 - arraySize + i + 1)
   277  			values[i] = v
   278  			err := array.Append(v)
   279  			require.NoError(t, err)
   280  		}
   281  
   282  		verifyArray(t, storage, typeInfo, address, array, values, false)
   283  
   284  		for i := uint64(0); i < arraySize; i++ {
   285  			oldValue := values[i]
   286  			newValue := Uint64Value(i)
   287  			values[i] = newValue
   288  
   289  			existingStorable, err := array.Set(i, newValue)
   290  			require.NoError(t, err)
   291  
   292  			existingValue, err := existingStorable.StoredValue(storage)
   293  			require.NoError(t, err)
   294  			valueEqual(t, typeInfoComparator, oldValue, existingValue)
   295  		}
   296  
   297  		verifyArray(t, storage, typeInfo, address, array, values, false)
   298  	})
   299  
   300  	t.Run("index out of bounds", func(t *testing.T) {
   301  
   302  		const arraySize = 1024
   303  
   304  		typeInfo := testTypeInfo{42}
   305  		storage := newTestPersistentStorage(t)
   306  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
   307  
   308  		array, err := NewArray(storage, address, typeInfo)
   309  		require.NoError(t, err)
   310  
   311  		values := make([]Value, 0, arraySize)
   312  		for i := uint64(0); i < arraySize; i++ {
   313  			v := Uint64Value(i)
   314  			values = append(values, v)
   315  			err := array.Append(v)
   316  			require.NoError(t, err)
   317  		}
   318  
   319  		r := newRand(t)
   320  
   321  		v := NewStringValue(randStr(r, 1024))
   322  		storable, err := array.Set(array.Count(), v)
   323  		require.Nil(t, storable)
   324  		require.Equal(t, 1, errorCategorizationCount(err))
   325  
   326  		var userError *UserError
   327  		var indexOutOfBoundsError *IndexOutOfBoundsError
   328  		require.ErrorAs(t, err, &userError)
   329  		require.ErrorAs(t, err, &indexOutOfBoundsError)
   330  		require.ErrorAs(t, userError, &indexOutOfBoundsError)
   331  
   332  		verifyArray(t, storage, typeInfo, address, array, values, false)
   333  	})
   334  }
   335  
   336  func TestArrayInsertAndGet(t *testing.T) {
   337  
   338  	SetThreshold(256)
   339  	defer SetThreshold(1024)
   340  
   341  	t.Run("insert-first", func(t *testing.T) {
   342  
   343  		const arraySize = 4096
   344  
   345  		typeInfo := testTypeInfo{42}
   346  		storage := newTestPersistentStorage(t)
   347  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
   348  
   349  		array, err := NewArray(storage, address, typeInfo)
   350  		require.NoError(t, err)
   351  
   352  		values := make([]Value, arraySize)
   353  		for i := uint64(0); i < arraySize; i++ {
   354  			v := Uint64Value(arraySize - i - 1)
   355  			values[arraySize-i-1] = v
   356  			err := array.Insert(0, v)
   357  			require.NoError(t, err)
   358  		}
   359  
   360  		verifyArray(t, storage, typeInfo, address, array, values, false)
   361  	})
   362  
   363  	t.Run("insert-last", func(t *testing.T) {
   364  
   365  		const arraySize = 4096
   366  
   367  		typeInfo := testTypeInfo{42}
   368  		storage := newTestPersistentStorage(t)
   369  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
   370  
   371  		array, err := NewArray(storage, address, typeInfo)
   372  		require.NoError(t, err)
   373  
   374  		values := make([]Value, arraySize)
   375  		for i := uint64(0); i < arraySize; i++ {
   376  			v := Uint64Value(i)
   377  			values[i] = v
   378  			err := array.Insert(i, v)
   379  			require.NoError(t, err)
   380  		}
   381  
   382  		verifyArray(t, storage, typeInfo, address, array, values, false)
   383  	})
   384  
   385  	t.Run("insert", func(t *testing.T) {
   386  
   387  		const arraySize = 4096
   388  
   389  		typeInfo := testTypeInfo{42}
   390  		storage := newTestPersistentStorage(t)
   391  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
   392  
   393  		array, err := NewArray(storage, address, typeInfo)
   394  		require.NoError(t, err)
   395  
   396  		values := make([]Value, 0, arraySize)
   397  		for i := uint64(0); i < arraySize; i += 2 {
   398  			v := Uint64Value(i)
   399  			values = append(values, v)
   400  			err := array.Append(v)
   401  			require.NoError(t, err)
   402  		}
   403  
   404  		for i := uint64(1); i < arraySize; i += 2 {
   405  			v := Uint64Value(i)
   406  
   407  			values = append(values, nil)
   408  			copy(values[i+1:], values[i:])
   409  			values[i] = v
   410  
   411  			err := array.Insert(i, v)
   412  			require.NoError(t, err)
   413  		}
   414  
   415  		verifyArray(t, storage, typeInfo, address, array, values, false)
   416  	})
   417  
   418  	t.Run("index out of bounds", func(t *testing.T) {
   419  
   420  		const arraySize = 1024
   421  
   422  		typeInfo := testTypeInfo{42}
   423  		storage := newTestPersistentStorage(t)
   424  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
   425  
   426  		array, err := NewArray(storage, address, typeInfo)
   427  		require.NoError(t, err)
   428  
   429  		values := make([]Value, 0, arraySize)
   430  		for i := uint64(0); i < arraySize; i++ {
   431  			v := Uint64Value(i)
   432  			values = append(values, v)
   433  			err := array.Append(v)
   434  			require.NoError(t, err)
   435  		}
   436  
   437  		r := newRand(t)
   438  
   439  		v := NewStringValue(randStr(r, 1024))
   440  		err = array.Insert(array.Count()+1, v)
   441  		require.Equal(t, 1, errorCategorizationCount(err))
   442  
   443  		var userError *UserError
   444  		var indexOutOfBoundsError *IndexOutOfBoundsError
   445  		require.ErrorAs(t, err, &userError)
   446  		require.ErrorAs(t, err, &indexOutOfBoundsError)
   447  		require.ErrorAs(t, userError, &indexOutOfBoundsError)
   448  
   449  		verifyArray(t, storage, typeInfo, address, array, values, false)
   450  	})
   451  }
   452  
   453  func TestArrayRemove(t *testing.T) {
   454  	SetThreshold(256)
   455  	defer SetThreshold(1024)
   456  
   457  	t.Run("remove-first", func(t *testing.T) {
   458  
   459  		const arraySize = 4096
   460  
   461  		typeInfo := testTypeInfo{42}
   462  		storage := newTestPersistentStorage(t)
   463  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
   464  
   465  		array, err := NewArray(storage, address, typeInfo)
   466  		require.NoError(t, err)
   467  
   468  		values := make([]Value, arraySize)
   469  		for i := uint64(0); i < arraySize; i++ {
   470  			v := Uint64Value(i)
   471  			values[i] = v
   472  			err := array.Append(v)
   473  			require.NoError(t, err)
   474  		}
   475  
   476  		require.True(t, typeInfoComparator(typeInfo, array.Type()))
   477  		require.Equal(t, address, array.Address())
   478  		require.Equal(t, uint64(arraySize), array.Count())
   479  
   480  		for i := uint64(0); i < arraySize; i++ {
   481  			existingStorable, err := array.Remove(0)
   482  			require.NoError(t, err)
   483  
   484  			existingValue, err := existingStorable.StoredValue(array.Storage)
   485  			require.NoError(t, err)
   486  
   487  			valueEqual(t, typeInfoComparator, values[i], existingValue)
   488  
   489  			if id, ok := existingStorable.(StorageIDStorable); ok {
   490  				err = array.Storage.Remove(StorageID(id))
   491  				require.NoError(t, err)
   492  			}
   493  
   494  			require.Equal(t, arraySize-i-1, array.Count())
   495  
   496  			if i%256 == 0 {
   497  				verifyArray(t, storage, typeInfo, address, array, values[i+1:], false)
   498  			}
   499  		}
   500  
   501  		verifyEmptyArray(t, storage, typeInfo, address, array)
   502  	})
   503  
   504  	t.Run("remove-last", func(t *testing.T) {
   505  
   506  		const arraySize = 4096
   507  
   508  		typeInfo := testTypeInfo{42}
   509  		storage := newTestPersistentStorage(t)
   510  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
   511  
   512  		array, err := NewArray(storage, address, typeInfo)
   513  		require.NoError(t, err)
   514  
   515  		values := make([]Value, arraySize)
   516  		for i := uint64(0); i < arraySize; i++ {
   517  			v := Uint64Value(i)
   518  			values[i] = v
   519  			err := array.Append(v)
   520  			require.NoError(t, err)
   521  		}
   522  
   523  		require.True(t, typeInfoComparator(typeInfo, array.Type()))
   524  		require.Equal(t, address, array.Address())
   525  		require.Equal(t, uint64(arraySize), array.Count())
   526  
   527  		for i := arraySize - 1; i >= 0; i-- {
   528  			existingStorable, err := array.Remove(uint64(i))
   529  			require.NoError(t, err)
   530  
   531  			existingValue, err := existingStorable.StoredValue(array.Storage)
   532  			require.NoError(t, err)
   533  
   534  			valueEqual(t, typeInfoComparator, values[i], existingValue)
   535  
   536  			if id, ok := existingStorable.(StorageIDStorable); ok {
   537  				err = array.Storage.Remove(StorageID(id))
   538  				require.NoError(t, err)
   539  			}
   540  
   541  			require.Equal(t, uint64(i), array.Count())
   542  
   543  			if i%256 == 0 {
   544  				verifyArray(t, storage, typeInfo, address, array, values[:i], false)
   545  			}
   546  		}
   547  
   548  		verifyEmptyArray(t, storage, typeInfo, address, array)
   549  	})
   550  
   551  	t.Run("remove", func(t *testing.T) {
   552  
   553  		const arraySize = 4096
   554  
   555  		typeInfo := testTypeInfo{42}
   556  		storage := newTestPersistentStorage(t)
   557  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
   558  
   559  		array, err := NewArray(storage, address, typeInfo)
   560  		require.NoError(t, err)
   561  
   562  		values := make([]Value, arraySize)
   563  		for i := uint64(0); i < arraySize; i++ {
   564  			v := Uint64Value(i)
   565  			values[i] = v
   566  			err := array.Append(v)
   567  			require.NoError(t, err)
   568  		}
   569  
   570  		require.True(t, typeInfoComparator(typeInfo, array.Type()))
   571  		require.Equal(t, address, array.Address())
   572  		require.Equal(t, uint64(arraySize), array.Count())
   573  
   574  		// Remove every other elements
   575  		for i := uint64(0); i < arraySize/2; i++ {
   576  			v := values[i]
   577  
   578  			existingStorable, err := array.Remove(i)
   579  			require.NoError(t, err)
   580  
   581  			existingValue, err := existingStorable.StoredValue(array.Storage)
   582  			require.NoError(t, err)
   583  
   584  			valueEqual(t, typeInfoComparator, v, existingValue)
   585  
   586  			if id, ok := existingStorable.(StorageIDStorable); ok {
   587  				err = array.Storage.Remove(StorageID(id))
   588  				require.NoError(t, err)
   589  			}
   590  
   591  			copy(values[i:], values[i+1:])
   592  			values = values[:len(values)-1]
   593  
   594  			require.Equal(t, uint64(len(values)), array.Count())
   595  
   596  			if i%256 == 0 {
   597  				verifyArray(t, storage, typeInfo, address, array, values, false)
   598  			}
   599  		}
   600  
   601  		require.Equal(t, arraySize/2, len(values))
   602  
   603  		verifyArray(t, storage, typeInfo, address, array, values, false)
   604  	})
   605  
   606  	t.Run("index out of bounds", func(t *testing.T) {
   607  
   608  		const arraySize = 4096
   609  
   610  		typeInfo := testTypeInfo{42}
   611  		storage := newTestPersistentStorage(t)
   612  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
   613  
   614  		array, err := NewArray(storage, address, typeInfo)
   615  		require.NoError(t, err)
   616  
   617  		values := make([]Value, arraySize)
   618  		for i := uint64(0); i < arraySize; i++ {
   619  			v := Uint64Value(i)
   620  			values[i] = v
   621  			err := array.Append(v)
   622  			require.NoError(t, err)
   623  		}
   624  
   625  		storable, err := array.Remove(array.Count())
   626  		require.Nil(t, storable)
   627  		require.Equal(t, 1, errorCategorizationCount(err))
   628  
   629  		var userError *UserError
   630  		var indexOutOfBounds *IndexOutOfBoundsError
   631  		require.ErrorAs(t, err, &userError)
   632  		require.ErrorAs(t, err, &indexOutOfBounds)
   633  		require.ErrorAs(t, userError, &indexOutOfBounds)
   634  
   635  		verifyArray(t, storage, typeInfo, address, array, values, false)
   636  	})
   637  }
   638  
   639  func TestArrayIterate(t *testing.T) {
   640  
   641  	t.Run("empty", func(t *testing.T) {
   642  		typeInfo := testTypeInfo{42}
   643  		storage := newTestPersistentStorage(t)
   644  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
   645  
   646  		array, err := NewArray(storage, address, typeInfo)
   647  		require.NoError(t, err)
   648  
   649  		i := uint64(0)
   650  		err = array.Iterate(func(v Value) (bool, error) {
   651  			i++
   652  			return true, nil
   653  		})
   654  		require.NoError(t, err)
   655  		require.Equal(t, uint64(0), i)
   656  	})
   657  
   658  	t.Run("append", func(t *testing.T) {
   659  		SetThreshold(256)
   660  		defer SetThreshold(1024)
   661  
   662  		const arraySize = 4096
   663  
   664  		typeInfo := testTypeInfo{42}
   665  		storage := newTestPersistentStorage(t)
   666  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
   667  
   668  		array, err := NewArray(storage, address, typeInfo)
   669  		require.NoError(t, err)
   670  
   671  		for i := uint64(0); i < arraySize; i++ {
   672  			err := array.Append(Uint64Value(i))
   673  			require.NoError(t, err)
   674  		}
   675  
   676  		i := uint64(0)
   677  		err = array.Iterate(func(v Value) (bool, error) {
   678  			require.Equal(t, Uint64Value(i), v)
   679  			i++
   680  			return true, nil
   681  		})
   682  		require.NoError(t, err)
   683  		require.Equal(t, uint64(arraySize), i)
   684  	})
   685  
   686  	t.Run("set", func(t *testing.T) {
   687  		SetThreshold(256)
   688  		defer SetThreshold(1024)
   689  
   690  		const arraySize = 4096
   691  
   692  		typeInfo := testTypeInfo{42}
   693  		storage := newTestPersistentStorage(t)
   694  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
   695  
   696  		array, err := NewArray(storage, address, typeInfo)
   697  		require.NoError(t, err)
   698  
   699  		for i := uint64(0); i < arraySize; i++ {
   700  			err := array.Append(Uint64Value(0))
   701  			require.NoError(t, err)
   702  		}
   703  
   704  		for i := uint64(0); i < arraySize; i++ {
   705  			existingStorable, err := array.Set(i, Uint64Value(i))
   706  			require.NoError(t, err)
   707  
   708  			existingValue, err := existingStorable.StoredValue(storage)
   709  			require.NoError(t, err)
   710  			require.Equal(t, Uint64Value(0), existingValue)
   711  		}
   712  
   713  		i := uint64(0)
   714  		err = array.Iterate(func(v Value) (bool, error) {
   715  			require.Equal(t, Uint64Value(i), v)
   716  			i++
   717  			return true, nil
   718  		})
   719  		require.NoError(t, err)
   720  		require.Equal(t, uint64(arraySize), i)
   721  	})
   722  
   723  	t.Run("insert", func(t *testing.T) {
   724  		SetThreshold(256)
   725  		defer SetThreshold(1024)
   726  
   727  		const arraySize = 4096
   728  
   729  		typeInfo := testTypeInfo{42}
   730  		storage := newTestPersistentStorage(t)
   731  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
   732  
   733  		array, err := NewArray(storage, address, typeInfo)
   734  		require.NoError(t, err)
   735  
   736  		for i := uint64(0); i < arraySize; i += 2 {
   737  			err := array.Append(Uint64Value(i))
   738  			require.NoError(t, err)
   739  		}
   740  
   741  		for i := uint64(1); i < arraySize; i += 2 {
   742  			err := array.Insert(i, Uint64Value(i))
   743  			require.NoError(t, err)
   744  		}
   745  
   746  		i := uint64(0)
   747  		err = array.Iterate(func(v Value) (bool, error) {
   748  			require.Equal(t, Uint64Value(i), v)
   749  			i++
   750  			return true, nil
   751  		})
   752  		require.NoError(t, err)
   753  		require.Equal(t, uint64(arraySize), i)
   754  	})
   755  
   756  	t.Run("remove", func(t *testing.T) {
   757  		SetThreshold(256)
   758  		defer SetThreshold(1024)
   759  
   760  		const arraySize = 4096
   761  
   762  		typeInfo := testTypeInfo{42}
   763  		storage := newTestPersistentStorage(t)
   764  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
   765  
   766  		array, err := NewArray(storage, address, typeInfo)
   767  		require.NoError(t, err)
   768  
   769  		for i := uint64(0); i < arraySize; i++ {
   770  			err := array.Append(Uint64Value(i))
   771  			require.NoError(t, err)
   772  		}
   773  
   774  		// Remove every other elements
   775  		for i := uint64(0); i < array.Count(); i++ {
   776  			storable, err := array.Remove(i)
   777  			require.NoError(t, err)
   778  			require.Equal(t, Uint64Value(i*2), storable)
   779  		}
   780  
   781  		i := uint64(0)
   782  		j := uint64(1)
   783  		err = array.Iterate(func(v Value) (bool, error) {
   784  			require.Equal(t, Uint64Value(j), v)
   785  			i++
   786  			j += 2
   787  			return true, nil
   788  		})
   789  		require.NoError(t, err)
   790  		require.Equal(t, uint64(arraySize/2), i)
   791  	})
   792  
   793  	t.Run("stop", func(t *testing.T) {
   794  
   795  		typeInfo := testTypeInfo{42}
   796  		storage := newTestPersistentStorage(t)
   797  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
   798  
   799  		array, err := NewArray(storage, address, typeInfo)
   800  		require.NoError(t, err)
   801  
   802  		const count = 10
   803  		for i := uint64(0); i < count; i++ {
   804  			err := array.Append(Uint64Value(i))
   805  			require.NoError(t, err)
   806  		}
   807  
   808  		i := 0
   809  		err = array.Iterate(func(_ Value) (bool, error) {
   810  			if i == count/2 {
   811  				return false, nil
   812  			}
   813  			i++
   814  			return true, nil
   815  		})
   816  		require.NoError(t, err)
   817  		require.Equal(t, count/2, i)
   818  	})
   819  
   820  	t.Run("error", func(t *testing.T) {
   821  
   822  		typeInfo := testTypeInfo{42}
   823  		storage := newTestPersistentStorage(t)
   824  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
   825  
   826  		array, err := NewArray(storage, address, typeInfo)
   827  		require.NoError(t, err)
   828  
   829  		const count = 10
   830  		for i := uint64(0); i < count; i++ {
   831  			err := array.Append(Uint64Value(i))
   832  			require.NoError(t, err)
   833  		}
   834  
   835  		testErr := errors.New("test")
   836  
   837  		i := 0
   838  		err = array.Iterate(func(_ Value) (bool, error) {
   839  			if i == count/2 {
   840  				return false, testErr
   841  			}
   842  			i++
   843  			return true, nil
   844  		})
   845  		// err is testErr wrapped in ExternalError.
   846  		require.Equal(t, 1, errorCategorizationCount(err))
   847  		var externalError *ExternalError
   848  		require.ErrorAs(t, err, &externalError)
   849  		require.Equal(t, testErr, externalError.Unwrap())
   850  
   851  		require.Equal(t, count/2, i)
   852  	})
   853  }
   854  
   855  func testArrayIterateRange(t *testing.T, storage *PersistentSlabStorage, array *Array, values []Value) {
   856  	var i uint64
   857  	var err error
   858  	var sliceOutOfBoundsError *SliceOutOfBoundsError
   859  	var invalidSliceIndexError *InvalidSliceIndexError
   860  
   861  	count := array.Count()
   862  
   863  	// If startIndex > count, IterateRange returns SliceOutOfBoundsError
   864  	err = array.IterateRange(count+1, count+1, func(v Value) (bool, error) {
   865  		i++
   866  		return true, nil
   867  	})
   868  	require.Equal(t, 1, errorCategorizationCount(err))
   869  
   870  	var userError *UserError
   871  	require.ErrorAs(t, err, &userError)
   872  	require.ErrorAs(t, err, &sliceOutOfBoundsError)
   873  	require.ErrorAs(t, userError, &sliceOutOfBoundsError)
   874  	require.Equal(t, uint64(0), i)
   875  
   876  	// If endIndex > count, IterateRange returns SliceOutOfBoundsError
   877  	err = array.IterateRange(0, count+1, func(v Value) (bool, error) {
   878  		i++
   879  		return true, nil
   880  	})
   881  	require.Equal(t, 1, errorCategorizationCount(err))
   882  	require.ErrorAs(t, err, &userError)
   883  	require.ErrorAs(t, err, &sliceOutOfBoundsError)
   884  	require.ErrorAs(t, userError, &sliceOutOfBoundsError)
   885  	require.Equal(t, uint64(0), i)
   886  
   887  	// If startIndex > endIndex, IterateRange returns InvalidSliceIndexError
   888  	if count > 0 {
   889  		err = array.IterateRange(1, 0, func(v Value) (bool, error) {
   890  			i++
   891  			return true, nil
   892  		})
   893  		require.Equal(t, 1, errorCategorizationCount(err))
   894  		require.ErrorAs(t, err, &userError)
   895  		require.ErrorAs(t, err, &invalidSliceIndexError)
   896  		require.ErrorAs(t, userError, &invalidSliceIndexError)
   897  		require.Equal(t, uint64(0), i)
   898  	}
   899  
   900  	// IterateRange returns no error and iteration function is called on sliced array
   901  	for startIndex := uint64(0); startIndex <= count; startIndex++ {
   902  		for endIndex := startIndex; endIndex <= count; endIndex++ {
   903  			i = uint64(0)
   904  			err = array.IterateRange(startIndex, endIndex, func(v Value) (bool, error) {
   905  				valueEqual(t, typeInfoComparator, v, values[int(startIndex+i)])
   906  				i++
   907  				return true, nil
   908  			})
   909  			require.NoError(t, err)
   910  			require.Equal(t, endIndex-startIndex, i)
   911  		}
   912  	}
   913  }
   914  
   915  func TestArrayIterateRange(t *testing.T) {
   916  	typeInfo := testTypeInfo{42}
   917  	address := Address{1, 2, 3, 4, 5, 6, 7, 8}
   918  
   919  	t.Run("empty", func(t *testing.T) {
   920  		storage := newTestPersistentStorage(t)
   921  
   922  		array, err := NewArray(storage, address, typeInfo)
   923  		require.NoError(t, err)
   924  
   925  		testArrayIterateRange(t, storage, array, []Value{})
   926  	})
   927  
   928  	t.Run("dataslab as root", func(t *testing.T) {
   929  		const arraySize = 10
   930  
   931  		storage := newTestPersistentStorage(t)
   932  
   933  		array, err := NewArray(storage, address, typeInfo)
   934  		require.NoError(t, err)
   935  
   936  		values := make([]Value, arraySize)
   937  		for i := uint64(0); i < arraySize; i++ {
   938  			value := Uint64Value(i)
   939  			values[i] = value
   940  			err := array.Append(value)
   941  			require.NoError(t, err)
   942  		}
   943  
   944  		testArrayIterateRange(t, storage, array, values)
   945  	})
   946  
   947  	t.Run("metadataslab as root", func(t *testing.T) {
   948  		SetThreshold(256)
   949  		defer SetThreshold(1024)
   950  
   951  		const arraySize = 1024
   952  
   953  		storage := newTestPersistentStorage(t)
   954  
   955  		array, err := NewArray(storage, address, typeInfo)
   956  		require.NoError(t, err)
   957  
   958  		values := make([]Value, arraySize)
   959  		for i := uint64(0); i < arraySize; i++ {
   960  			value := Uint64Value(i)
   961  			values[i] = value
   962  			err := array.Append(value)
   963  			require.NoError(t, err)
   964  		}
   965  
   966  		testArrayIterateRange(t, storage, array, values)
   967  	})
   968  
   969  	t.Run("stop", func(t *testing.T) {
   970  		const arraySize = 10
   971  
   972  		storage := newTestPersistentStorage(t)
   973  
   974  		array, err := NewArray(storage, address, typeInfo)
   975  		require.NoError(t, err)
   976  
   977  		for i := uint64(0); i < arraySize; i++ {
   978  			err := array.Append(Uint64Value(i))
   979  			require.NoError(t, err)
   980  		}
   981  
   982  		i := uint64(0)
   983  		startIndex := uint64(1)
   984  		endIndex := uint64(5)
   985  		count := endIndex - startIndex
   986  		err = array.IterateRange(startIndex, endIndex, func(_ Value) (bool, error) {
   987  			if i == count/2 {
   988  				return false, nil
   989  			}
   990  			i++
   991  			return true, nil
   992  		})
   993  		require.NoError(t, err)
   994  		require.Equal(t, count/2, i)
   995  	})
   996  
   997  	t.Run("error", func(t *testing.T) {
   998  		storage := newTestPersistentStorage(t)
   999  
  1000  		array, err := NewArray(storage, address, typeInfo)
  1001  		require.NoError(t, err)
  1002  
  1003  		const arraySize = 10
  1004  		for i := uint64(0); i < arraySize; i++ {
  1005  			err := array.Append(Uint64Value(i))
  1006  			require.NoError(t, err)
  1007  		}
  1008  
  1009  		testErr := errors.New("test")
  1010  
  1011  		i := uint64(0)
  1012  		startIndex := uint64(1)
  1013  		endIndex := uint64(5)
  1014  		count := endIndex - startIndex
  1015  		err = array.IterateRange(startIndex, endIndex, func(_ Value) (bool, error) {
  1016  			if i == count/2 {
  1017  				return false, testErr
  1018  			}
  1019  			i++
  1020  			return true, nil
  1021  		})
  1022  		// err is testErr wrapped in ExternalError.
  1023  		require.Equal(t, 1, errorCategorizationCount(err))
  1024  		var externalError *ExternalError
  1025  		require.ErrorAs(t, err, &externalError)
  1026  		require.Equal(t, testErr, externalError.Unwrap())
  1027  		require.Equal(t, count/2, i)
  1028  	})
  1029  }
  1030  
  1031  func TestArrayRootStorageID(t *testing.T) {
  1032  	SetThreshold(256)
  1033  	defer SetThreshold(1024)
  1034  
  1035  	const arraySize = 4096
  1036  
  1037  	typeInfo := testTypeInfo{42}
  1038  	storage := newTestPersistentStorage(t)
  1039  	address := Address{1, 2, 3, 4, 5, 6, 7, 8}
  1040  
  1041  	array, err := NewArray(storage, address, typeInfo)
  1042  	require.NoError(t, err)
  1043  
  1044  	savedRootID := array.StorageID()
  1045  	require.NotEqual(t, StorageIDUndefined, savedRootID)
  1046  
  1047  	// Append elements
  1048  	for i := uint64(0); i < arraySize; i++ {
  1049  		err := array.Append(Uint64Value(i))
  1050  		require.NoError(t, err)
  1051  		require.Equal(t, savedRootID, array.StorageID())
  1052  	}
  1053  
  1054  	require.True(t, typeInfoComparator(typeInfo, array.Type()))
  1055  	require.Equal(t, address, array.Address())
  1056  	require.Equal(t, uint64(arraySize), array.Count())
  1057  
  1058  	// Remove elements
  1059  	for i := uint64(0); i < arraySize; i++ {
  1060  		storable, err := array.Remove(0)
  1061  		require.NoError(t, err)
  1062  		require.Equal(t, Uint64Value(i), storable)
  1063  		require.Equal(t, savedRootID, array.StorageID())
  1064  	}
  1065  
  1066  	require.True(t, typeInfoComparator(typeInfo, array.Type()))
  1067  	require.Equal(t, address, array.Address())
  1068  	require.Equal(t, uint64(0), array.Count())
  1069  	require.Equal(t, savedRootID, array.StorageID())
  1070  }
  1071  
  1072  func TestArraySetRandomValues(t *testing.T) {
  1073  
  1074  	SetThreshold(256)
  1075  	defer SetThreshold(1024)
  1076  
  1077  	const arraySize = 4096
  1078  
  1079  	r := newRand(t)
  1080  
  1081  	typeInfo := testTypeInfo{42}
  1082  	storage := newTestPersistentStorage(t)
  1083  	address := Address{1, 2, 3, 4, 5, 6, 7, 8}
  1084  
  1085  	array, err := NewArray(storage, address, typeInfo)
  1086  	require.NoError(t, err)
  1087  
  1088  	values := make([]Value, arraySize)
  1089  	for i := uint64(0); i < arraySize; i++ {
  1090  		v := Uint64Value(i)
  1091  		values[i] = v
  1092  		err := array.Append(v)
  1093  		require.NoError(t, err)
  1094  	}
  1095  
  1096  	for i := uint64(0); i < arraySize; i++ {
  1097  		oldValue := values[i]
  1098  		newValue := randomValue(r, int(MaxInlineArrayElementSize))
  1099  		values[i] = newValue
  1100  
  1101  		existingStorable, err := array.Set(i, newValue)
  1102  		require.NoError(t, err)
  1103  
  1104  		existingValue, err := existingStorable.StoredValue(storage)
  1105  		require.NoError(t, err)
  1106  		valueEqual(t, typeInfoComparator, oldValue, existingValue)
  1107  	}
  1108  
  1109  	verifyArray(t, storage, typeInfo, address, array, values, false)
  1110  }
  1111  
  1112  func TestArrayInsertRandomValues(t *testing.T) {
  1113  
  1114  	SetThreshold(256)
  1115  	defer SetThreshold(1024)
  1116  
  1117  	t.Run("insert-first", func(t *testing.T) {
  1118  
  1119  		const arraySize = 4096
  1120  
  1121  		r := newRand(t)
  1122  
  1123  		typeInfo := testTypeInfo{42}
  1124  		storage := newTestPersistentStorage(t)
  1125  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
  1126  
  1127  		array, err := NewArray(storage, address, typeInfo)
  1128  		require.NoError(t, err)
  1129  
  1130  		values := make([]Value, arraySize)
  1131  		for i := uint64(0); i < arraySize; i++ {
  1132  			v := randomValue(r, int(MaxInlineArrayElementSize))
  1133  			values[arraySize-i-1] = v
  1134  
  1135  			err := array.Insert(0, v)
  1136  			require.NoError(t, err)
  1137  		}
  1138  
  1139  		verifyArray(t, storage, typeInfo, address, array, values, false)
  1140  	})
  1141  
  1142  	t.Run("insert-last", func(t *testing.T) {
  1143  
  1144  		const arraySize = 4096
  1145  
  1146  		r := newRand(t)
  1147  
  1148  		typeInfo := testTypeInfo{42}
  1149  		storage := newTestPersistentStorage(t)
  1150  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
  1151  
  1152  		array, err := NewArray(storage, address, typeInfo)
  1153  		require.NoError(t, err)
  1154  
  1155  		values := make([]Value, arraySize)
  1156  		for i := uint64(0); i < arraySize; i++ {
  1157  			v := randomValue(r, int(MaxInlineArrayElementSize))
  1158  			values[i] = v
  1159  
  1160  			err := array.Insert(i, v)
  1161  			require.NoError(t, err)
  1162  		}
  1163  
  1164  		verifyArray(t, storage, typeInfo, address, array, values, false)
  1165  	})
  1166  
  1167  	t.Run("insert-random", func(t *testing.T) {
  1168  
  1169  		const arraySize = 4096
  1170  
  1171  		r := newRand(t)
  1172  
  1173  		typeInfo := testTypeInfo{42}
  1174  		storage := newTestPersistentStorage(t)
  1175  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
  1176  
  1177  		array, err := NewArray(storage, address, typeInfo)
  1178  		require.NoError(t, err)
  1179  
  1180  		values := make([]Value, arraySize)
  1181  		for i := uint64(0); i < arraySize; i++ {
  1182  			k := r.Intn(int(i) + 1)
  1183  			v := randomValue(r, int(MaxInlineArrayElementSize))
  1184  
  1185  			copy(values[k+1:], values[k:])
  1186  			values[k] = v
  1187  
  1188  			err := array.Insert(uint64(k), v)
  1189  			require.NoError(t, err)
  1190  		}
  1191  
  1192  		verifyArray(t, storage, typeInfo, address, array, values, false)
  1193  	})
  1194  }
  1195  
  1196  func TestArrayRemoveRandomValues(t *testing.T) {
  1197  
  1198  	SetThreshold(256)
  1199  	defer SetThreshold(1024)
  1200  
  1201  	const arraySize = 4096
  1202  
  1203  	r := newRand(t)
  1204  
  1205  	typeInfo := testTypeInfo{42}
  1206  	storage := newTestPersistentStorage(t)
  1207  	address := Address{1, 2, 3, 4, 5, 6, 7, 8}
  1208  
  1209  	array, err := NewArray(storage, address, typeInfo)
  1210  	require.NoError(t, err)
  1211  
  1212  	values := make([]Value, arraySize)
  1213  	// Insert n random values into array
  1214  	for i := uint64(0); i < arraySize; i++ {
  1215  		v := randomValue(r, int(MaxInlineArrayElementSize))
  1216  		values[i] = v
  1217  
  1218  		err := array.Insert(i, v)
  1219  		require.NoError(t, err)
  1220  	}
  1221  
  1222  	verifyArray(t, storage, typeInfo, address, array, values, false)
  1223  
  1224  	// Remove n elements at random index
  1225  	for i := uint64(0); i < arraySize; i++ {
  1226  		k := r.Intn(int(array.Count()))
  1227  
  1228  		existingStorable, err := array.Remove(uint64(k))
  1229  		require.NoError(t, err)
  1230  
  1231  		existingValue, err := existingStorable.StoredValue(storage)
  1232  		require.NoError(t, err)
  1233  		valueEqual(t, typeInfoComparator, values[k], existingValue)
  1234  
  1235  		copy(values[k:], values[k+1:])
  1236  		values = values[:len(values)-1]
  1237  
  1238  		if id, ok := existingStorable.(StorageIDStorable); ok {
  1239  			err = storage.Remove(StorageID(id))
  1240  			require.NoError(t, err)
  1241  		}
  1242  	}
  1243  
  1244  	verifyEmptyArray(t, storage, typeInfo, address, array)
  1245  }
  1246  
  1247  func testArrayAppendSetInsertRemoveRandomValues(
  1248  	t *testing.T,
  1249  	r *rand.Rand,
  1250  	storage *PersistentSlabStorage,
  1251  	typeInfo TypeInfo,
  1252  	address Address,
  1253  	opCount int,
  1254  ) (*Array, []Value) {
  1255  	const (
  1256  		ArrayAppendOp = iota
  1257  		ArrayInsertOp
  1258  		ArraySetOp
  1259  		ArrayRemoveOp
  1260  		MaxArrayOp
  1261  	)
  1262  
  1263  	array, err := NewArray(storage, address, typeInfo)
  1264  	require.NoError(t, err)
  1265  
  1266  	values := make([]Value, 0, opCount)
  1267  	for i := 0; i < opCount; i++ {
  1268  
  1269  		var nextOp int
  1270  
  1271  		for {
  1272  			nextOp = r.Intn(MaxArrayOp)
  1273  
  1274  			if array.Count() > 0 || (nextOp != ArrayRemoveOp && nextOp != ArraySetOp) {
  1275  				break
  1276  			}
  1277  		}
  1278  
  1279  		switch nextOp {
  1280  
  1281  		case ArrayAppendOp:
  1282  			v := randomValue(r, int(MaxInlineArrayElementSize))
  1283  			values = append(values, v)
  1284  
  1285  			err := array.Append(v)
  1286  			require.NoError(t, err)
  1287  
  1288  		case ArraySetOp:
  1289  			k := r.Intn(int(array.Count()))
  1290  			v := randomValue(r, int(MaxInlineArrayElementSize))
  1291  
  1292  			oldV := values[k]
  1293  
  1294  			values[k] = v
  1295  
  1296  			existingStorable, err := array.Set(uint64(k), v)
  1297  			require.NoError(t, err)
  1298  
  1299  			existingValue, err := existingStorable.StoredValue(storage)
  1300  			require.NoError(t, err)
  1301  			valueEqual(t, typeInfoComparator, oldV, existingValue)
  1302  
  1303  			if id, ok := existingStorable.(StorageIDStorable); ok {
  1304  				err = storage.Remove(StorageID(id))
  1305  				require.NoError(t, err)
  1306  			}
  1307  
  1308  		case ArrayInsertOp:
  1309  			k := r.Intn(int(array.Count() + 1))
  1310  			v := randomValue(r, int(MaxInlineArrayElementSize))
  1311  
  1312  			if k == int(array.Count()) {
  1313  				values = append(values, v)
  1314  			} else {
  1315  				values = append(values, nil)
  1316  				copy(values[k+1:], values[k:])
  1317  				values[k] = v
  1318  			}
  1319  
  1320  			err := array.Insert(uint64(k), v)
  1321  			require.NoError(t, err)
  1322  
  1323  		case ArrayRemoveOp:
  1324  			k := r.Intn(int(array.Count()))
  1325  
  1326  			existingStorable, err := array.Remove(uint64(k))
  1327  			require.NoError(t, err)
  1328  
  1329  			existingValue, err := existingStorable.StoredValue(storage)
  1330  			require.NoError(t, err)
  1331  			valueEqual(t, typeInfoComparator, values[k], existingValue)
  1332  
  1333  			copy(values[k:], values[k+1:])
  1334  			values = values[:len(values)-1]
  1335  
  1336  			if id, ok := existingStorable.(StorageIDStorable); ok {
  1337  				err = storage.Remove(StorageID(id))
  1338  				require.NoError(t, err)
  1339  			}
  1340  		}
  1341  
  1342  		require.Equal(t, uint64(len(values)), array.Count())
  1343  		require.True(t, typeInfoComparator(typeInfo, array.Type()))
  1344  		require.Equal(t, address, array.Address())
  1345  	}
  1346  
  1347  	return array, values
  1348  }
  1349  
  1350  func TestArrayAppendSetInsertRemoveRandomValues(t *testing.T) {
  1351  
  1352  	SetThreshold(256)
  1353  	defer SetThreshold(1024)
  1354  
  1355  	const opCount = 4096
  1356  
  1357  	r := newRand(t)
  1358  
  1359  	typeInfo := testTypeInfo{42}
  1360  	storage := newTestPersistentStorage(t)
  1361  	address := Address{1, 2, 3, 4, 5, 6, 7, 8}
  1362  
  1363  	array, values := testArrayAppendSetInsertRemoveRandomValues(t, r, storage, typeInfo, address, opCount)
  1364  	verifyArray(t, storage, typeInfo, address, array, values, false)
  1365  }
  1366  
  1367  func TestArrayNestedArrayMap(t *testing.T) {
  1368  
  1369  	SetThreshold(256)
  1370  	defer SetThreshold(1024)
  1371  
  1372  	t.Run("small array", func(t *testing.T) {
  1373  
  1374  		const arraySize = 4096
  1375  
  1376  		nestedTypeInfo := testTypeInfo{43}
  1377  		storage := newTestPersistentStorage(t)
  1378  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
  1379  
  1380  		// Create a list of arrays with 2 elements.
  1381  		nestedArrays := make([]Value, arraySize)
  1382  		for i := uint64(0); i < arraySize; i++ {
  1383  			nested, err := NewArray(storage, address, nestedTypeInfo)
  1384  			require.NoError(t, err)
  1385  
  1386  			err = nested.Append(Uint64Value(i))
  1387  			require.NoError(t, err)
  1388  
  1389  			require.True(t, nested.root.IsData())
  1390  
  1391  			nestedArrays[i] = nested
  1392  		}
  1393  
  1394  		typeInfo := testTypeInfo{42}
  1395  
  1396  		array, err := NewArray(storage, address, typeInfo)
  1397  		require.NoError(t, err)
  1398  
  1399  		for _, a := range nestedArrays {
  1400  			err := array.Append(a)
  1401  			require.NoError(t, err)
  1402  		}
  1403  
  1404  		verifyArray(t, storage, typeInfo, address, array, nestedArrays, false)
  1405  	})
  1406  
  1407  	t.Run("big array", func(t *testing.T) {
  1408  
  1409  		const arraySize = 4096
  1410  
  1411  		nestedTypeInfo := testTypeInfo{43}
  1412  		storage := newTestPersistentStorage(t)
  1413  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
  1414  
  1415  		values := make([]Value, arraySize)
  1416  		for i := uint64(0); i < arraySize; i++ {
  1417  			nested, err := NewArray(storage, address, nestedTypeInfo)
  1418  			require.NoError(t, err)
  1419  
  1420  			for i := uint64(0); i < 40; i++ {
  1421  				err := nested.Append(Uint64Value(math.MaxUint64))
  1422  				require.NoError(t, err)
  1423  			}
  1424  
  1425  			require.False(t, nested.root.IsData())
  1426  
  1427  			values[i] = nested
  1428  		}
  1429  
  1430  		typeInfo := testTypeInfo{42}
  1431  
  1432  		array, err := NewArray(storage, address, typeInfo)
  1433  		require.NoError(t, err)
  1434  		for _, a := range values {
  1435  			err := array.Append(a)
  1436  			require.NoError(t, err)
  1437  		}
  1438  
  1439  		verifyArray(t, storage, typeInfo, address, array, values, true)
  1440  	})
  1441  
  1442  	t.Run("small map", func(t *testing.T) {
  1443  
  1444  		const arraySize = 4096
  1445  
  1446  		nestedTypeInfo := testTypeInfo{43}
  1447  
  1448  		storage := newTestPersistentStorage(t)
  1449  
  1450  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
  1451  
  1452  		nestedMaps := make([]Value, arraySize)
  1453  		for i := uint64(0); i < arraySize; i++ {
  1454  			nested, err := NewMap(storage, address, NewDefaultDigesterBuilder(), nestedTypeInfo)
  1455  			require.NoError(t, err)
  1456  
  1457  			storable, err := nested.Set(compare, hashInputProvider, Uint64Value(i), Uint64Value(i*2))
  1458  			require.NoError(t, err)
  1459  			require.Nil(t, storable)
  1460  
  1461  			require.True(t, nested.root.IsData())
  1462  
  1463  			nestedMaps[i] = nested
  1464  		}
  1465  
  1466  		typeInfo := testTypeInfo{42}
  1467  
  1468  		array, err := NewArray(storage, address, typeInfo)
  1469  		require.NoError(t, err)
  1470  
  1471  		for _, a := range nestedMaps {
  1472  			err := array.Append(a)
  1473  			require.NoError(t, err)
  1474  		}
  1475  
  1476  		verifyArray(t, storage, typeInfo, address, array, nestedMaps, false)
  1477  	})
  1478  
  1479  	t.Run("big map", func(t *testing.T) {
  1480  
  1481  		const arraySize = 4096
  1482  
  1483  		nestedTypeInfo := testTypeInfo{43}
  1484  		storage := newTestPersistentStorage(t)
  1485  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
  1486  
  1487  		values := make([]Value, arraySize)
  1488  		for i := uint64(0); i < arraySize; i++ {
  1489  			nested, err := NewMap(storage, address, NewDefaultDigesterBuilder(), nestedTypeInfo)
  1490  			require.NoError(t, err)
  1491  
  1492  			for i := uint64(0); i < 25; i++ {
  1493  				storable, err := nested.Set(compare, hashInputProvider, Uint64Value(i), Uint64Value(i*2))
  1494  				require.NoError(t, err)
  1495  				require.Nil(t, storable)
  1496  			}
  1497  
  1498  			require.False(t, nested.root.IsData())
  1499  
  1500  			values[i] = nested
  1501  		}
  1502  
  1503  		typeInfo := testTypeInfo{42}
  1504  
  1505  		array, err := NewArray(storage, address, typeInfo)
  1506  		require.NoError(t, err)
  1507  		for _, a := range values {
  1508  			err := array.Append(a)
  1509  			require.NoError(t, err)
  1510  		}
  1511  
  1512  		verifyArray(t, storage, typeInfo, address, array, values, true)
  1513  	})
  1514  }
  1515  
  1516  func TestArrayEncodeDecode(t *testing.T) {
  1517  
  1518  	SetThreshold(256)
  1519  	defer SetThreshold(1024)
  1520  
  1521  	t.Run("empty", func(t *testing.T) {
  1522  		typeInfo := testTypeInfo{42}
  1523  		storage := newTestBasicStorage(t)
  1524  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
  1525  
  1526  		array, err := NewArray(storage, address, typeInfo)
  1527  		require.NoError(t, err)
  1528  
  1529  		expectedData := []byte{
  1530  			// extra data
  1531  			// version
  1532  			0x00,
  1533  			// extra data flag
  1534  			0x80,
  1535  			// array of extra data
  1536  			0x81,
  1537  			// type info
  1538  			0x18, 0x2a,
  1539  
  1540  			// version
  1541  			0x00,
  1542  			// array data slab flag
  1543  			0x80,
  1544  			// CBOR encoded array head (fixed size 3 byte)
  1545  			0x99, 0x00, 0x00,
  1546  		}
  1547  
  1548  		slabData, err := storage.Encode()
  1549  		require.NoError(t, err)
  1550  		require.Equal(t, 1, len(slabData))
  1551  		require.Equal(t, expectedData, slabData[array.StorageID()])
  1552  
  1553  		// Decode data to new storage
  1554  		storage2 := newTestPersistentStorageWithData(t, slabData)
  1555  
  1556  		// Test new array from storage2
  1557  		array2, err := NewArrayWithRootID(storage2, array.StorageID())
  1558  		require.NoError(t, err)
  1559  
  1560  		verifyEmptyArray(t, storage2, typeInfo, address, array2)
  1561  	})
  1562  
  1563  	t.Run("dataslab as root", func(t *testing.T) {
  1564  		typeInfo := testTypeInfo{42}
  1565  		storage := newTestBasicStorage(t)
  1566  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
  1567  
  1568  		array, err := NewArray(storage, address, typeInfo)
  1569  		require.NoError(t, err)
  1570  
  1571  		v := Uint64Value(0)
  1572  		values := []Value{v}
  1573  		err = array.Append(v)
  1574  		require.NoError(t, err)
  1575  
  1576  		expectedData := []byte{
  1577  			// extra data
  1578  			// version
  1579  			0x00,
  1580  			// extra data flag
  1581  			0x80,
  1582  			// array of extra data
  1583  			0x81,
  1584  			// type info
  1585  			0x18, 0x2a,
  1586  
  1587  			// version
  1588  			0x00,
  1589  			// array data slab flag
  1590  			0x80,
  1591  			// CBOR encoded array head (fixed size 3 byte)
  1592  			0x99, 0x00, 0x01,
  1593  			// CBOR encoded array elements
  1594  			0xd8, 0xa4, 0x00,
  1595  		}
  1596  
  1597  		slabData, err := storage.Encode()
  1598  		require.NoError(t, err)
  1599  		require.Equal(t, 1, len(slabData))
  1600  		require.Equal(t, expectedData, slabData[array.StorageID()])
  1601  
  1602  		// Decode data to new storage
  1603  		storage2 := newTestPersistentStorageWithData(t, slabData)
  1604  
  1605  		// Test new array from storage2
  1606  		array2, err := NewArrayWithRootID(storage2, array.StorageID())
  1607  		require.NoError(t, err)
  1608  
  1609  		verifyArray(t, storage2, typeInfo, address, array2, values, false)
  1610  	})
  1611  
  1612  	t.Run("has pointers", func(t *testing.T) {
  1613  		typeInfo := testTypeInfo{42}
  1614  		storage := newTestBasicStorage(t)
  1615  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
  1616  
  1617  		array, err := NewArray(storage, address, typeInfo)
  1618  		require.NoError(t, err)
  1619  
  1620  		const arraySize = 20
  1621  		values := make([]Value, arraySize)
  1622  		for i := uint64(0); i < arraySize-1; i++ {
  1623  			v := NewStringValue(strings.Repeat("a", 22))
  1624  			values[i] = v
  1625  			err := array.Append(v)
  1626  			require.NoError(t, err)
  1627  		}
  1628  
  1629  		typeInfo2 := testTypeInfo{43}
  1630  
  1631  		nestedArray, err := NewArray(storage, address, typeInfo2)
  1632  		require.NoError(t, err)
  1633  
  1634  		err = nestedArray.Append(Uint64Value(0))
  1635  		require.NoError(t, err)
  1636  
  1637  		values[arraySize-1] = nestedArray
  1638  
  1639  		err = array.Append(nestedArray)
  1640  		require.NoError(t, err)
  1641  
  1642  		require.Equal(t, uint64(arraySize), array.Count())
  1643  		require.Equal(t, uint64(1), nestedArray.Count())
  1644  
  1645  		id1 := StorageID{Address: address, Index: StorageIndex{0, 0, 0, 0, 0, 0, 0, 1}}
  1646  		id2 := StorageID{Address: address, Index: StorageIndex{0, 0, 0, 0, 0, 0, 0, 2}}
  1647  		id3 := StorageID{Address: address, Index: StorageIndex{0, 0, 0, 0, 0, 0, 0, 3}}
  1648  		id4 := StorageID{Address: address, Index: StorageIndex{0, 0, 0, 0, 0, 0, 0, 4}}
  1649  
  1650  		// Expected serialized slab data with storage id
  1651  		expected := map[StorageID][]byte{
  1652  
  1653  			// (metadata slab) headers: [{id:2 size:228 count:9} {id:3 size:270 count:11} ]
  1654  			id1: {
  1655  				// extra data
  1656  				// version
  1657  				0x00,
  1658  				// extra data flag
  1659  				0x81,
  1660  				// array of extra data
  1661  				0x81,
  1662  				// type info
  1663  				0x18, 0x2a,
  1664  
  1665  				// version
  1666  				0x00,
  1667  				// array meta data slab flag
  1668  				0x81,
  1669  				// child header count
  1670  				0x00, 0x02,
  1671  				// child header 1 (storage id, count, size)
  1672  				0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
  1673  				0x00, 0x00, 0x00, 0x09,
  1674  				0x00, 0x00, 0x00, 0xe4,
  1675  				// child header 2
  1676  				0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
  1677  				0x00, 0x00, 0x00, 0x0b,
  1678  				0x00, 0x00, 0x01, 0x0e,
  1679  			},
  1680  
  1681  			// (data slab) next: 3, data: [aaaaaaaaaaaaaaaaaaaaaa ... aaaaaaaaaaaaaaaaaaaaaa]
  1682  			id2: {
  1683  				// version
  1684  				0x00,
  1685  				// array data slab flag
  1686  				0x00,
  1687  				// next storage id
  1688  				0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
  1689  				// CBOR encoded array head (fixed size 3 byte)
  1690  				0x99, 0x00, 0x09,
  1691  				// CBOR encoded array elements
  1692  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
  1693  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
  1694  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
  1695  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
  1696  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
  1697  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
  1698  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
  1699  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
  1700  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
  1701  			},
  1702  
  1703  			// (data slab) next: 0, data: [aaaaaaaaaaaaaaaaaaaaaa ... StorageID(...)]
  1704  			id3: {
  1705  				// version
  1706  				0x00,
  1707  				// array data slab flag
  1708  				0x40,
  1709  				// next storage id
  1710  				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1711  				// CBOR encoded array head (fixed size 3 byte)
  1712  				0x99, 0x00, 0x0b,
  1713  				// CBOR encoded array elements
  1714  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
  1715  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
  1716  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
  1717  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
  1718  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
  1719  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
  1720  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
  1721  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
  1722  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
  1723  				0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
  1724  				0xd8, 0xff, 0x50, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
  1725  			},
  1726  
  1727  			// (data slab) next: 0, data: [0]
  1728  			id4: {
  1729  				// extra data
  1730  				// version
  1731  				0x00,
  1732  				// extra data flag
  1733  				0x80,
  1734  				// array of extra data
  1735  				0x81,
  1736  				// type info
  1737  				0x18, 0x2b,
  1738  
  1739  				// version
  1740  				0x00,
  1741  				// array data slab flag
  1742  				0x80,
  1743  				// CBOR encoded array head (fixed size 3 byte)
  1744  				0x99, 0x00, 0x01,
  1745  				// CBOR encoded array elements
  1746  				0xd8, 0xa4, 0x00,
  1747  			},
  1748  		}
  1749  
  1750  		m, err := storage.Encode()
  1751  		require.NoError(t, err)
  1752  		require.Equal(t, len(expected), len(m))
  1753  		require.Equal(t, expected[id1], m[id1])
  1754  		require.Equal(t, expected[id2], m[id2])
  1755  		require.Equal(t, expected[id3], m[id3])
  1756  		require.Equal(t, expected[id4], m[id4])
  1757  
  1758  		// Decode data to new storage
  1759  		storage2 := newTestPersistentStorageWithData(t, m)
  1760  
  1761  		// Test new array from storage2
  1762  		array2, err := NewArrayWithRootID(storage2, array.StorageID())
  1763  		require.NoError(t, err)
  1764  
  1765  		verifyArray(t, storage2, typeInfo, address, array2, values, false)
  1766  	})
  1767  }
  1768  
  1769  func TestArrayEncodeDecodeRandomValues(t *testing.T) {
  1770  
  1771  	SetThreshold(256)
  1772  	defer SetThreshold(1024)
  1773  
  1774  	const opCount = 8192
  1775  
  1776  	r := newRand(t)
  1777  
  1778  	typeInfo := testTypeInfo{42}
  1779  	storage := newTestPersistentStorage(t)
  1780  	address := Address{1, 2, 3, 4, 5, 6, 7, 8}
  1781  
  1782  	array, values := testArrayAppendSetInsertRemoveRandomValues(t, r, storage, typeInfo, address, opCount)
  1783  
  1784  	verifyArray(t, storage, typeInfo, address, array, values, false)
  1785  
  1786  	// Decode data to new storage
  1787  	storage2 := newTestPersistentStorageWithBaseStorage(t, storage.baseStorage)
  1788  
  1789  	// Test new array from storage2
  1790  	array2, err := NewArrayWithRootID(storage2, array.StorageID())
  1791  	require.NoError(t, err)
  1792  
  1793  	verifyArray(t, storage2, typeInfo, address, array2, values, false)
  1794  }
  1795  
  1796  func TestEmptyArray(t *testing.T) {
  1797  
  1798  	t.Parallel()
  1799  
  1800  	typeInfo := testTypeInfo{42}
  1801  	address := Address{1, 2, 3, 4, 5, 6, 7, 8}
  1802  	storage := newTestBasicStorage(t)
  1803  
  1804  	array, err := NewArray(storage, address, typeInfo)
  1805  	require.NoError(t, err)
  1806  
  1807  	t.Run("get", func(t *testing.T) {
  1808  		s, err := array.Get(0)
  1809  		require.Equal(t, 1, errorCategorizationCount(err))
  1810  		var userError *UserError
  1811  		var indexOutOfBoundsError *IndexOutOfBoundsError
  1812  		require.ErrorAs(t, err, &userError)
  1813  		require.ErrorAs(t, err, &indexOutOfBoundsError)
  1814  		require.ErrorAs(t, userError, &indexOutOfBoundsError)
  1815  		require.Nil(t, s)
  1816  	})
  1817  
  1818  	t.Run("set", func(t *testing.T) {
  1819  		s, err := array.Set(0, Uint64Value(0))
  1820  		require.Equal(t, 1, errorCategorizationCount(err))
  1821  		var userError *UserError
  1822  		var indexOutOfBoundsError *IndexOutOfBoundsError
  1823  		require.ErrorAs(t, err, &userError)
  1824  		require.ErrorAs(t, err, &indexOutOfBoundsError)
  1825  		require.ErrorAs(t, userError, &indexOutOfBoundsError)
  1826  		require.Nil(t, s)
  1827  	})
  1828  
  1829  	t.Run("insert", func(t *testing.T) {
  1830  		err := array.Insert(1, Uint64Value(0))
  1831  		require.Equal(t, 1, errorCategorizationCount(err))
  1832  		var userError *UserError
  1833  		var indexOutOfBoundsError *IndexOutOfBoundsError
  1834  		require.ErrorAs(t, err, &userError)
  1835  		require.ErrorAs(t, err, &indexOutOfBoundsError)
  1836  		require.ErrorAs(t, userError, &indexOutOfBoundsError)
  1837  	})
  1838  
  1839  	t.Run("remove", func(t *testing.T) {
  1840  		s, err := array.Remove(0)
  1841  		require.Equal(t, 1, errorCategorizationCount(err))
  1842  		var userError *UserError
  1843  		var indexOutOfBoundsError *IndexOutOfBoundsError
  1844  		require.ErrorAs(t, err, &userError)
  1845  		require.ErrorAs(t, err, &indexOutOfBoundsError)
  1846  		require.ErrorAs(t, userError, &indexOutOfBoundsError)
  1847  		require.Nil(t, s)
  1848  	})
  1849  
  1850  	t.Run("iterate", func(t *testing.T) {
  1851  		i := uint64(0)
  1852  		err := array.Iterate(func(v Value) (bool, error) {
  1853  			i++
  1854  			return true, nil
  1855  		})
  1856  		require.NoError(t, err)
  1857  		require.Equal(t, uint64(0), i)
  1858  	})
  1859  
  1860  	t.Run("count", func(t *testing.T) {
  1861  		count := array.Count()
  1862  		require.Equal(t, uint64(0), count)
  1863  	})
  1864  
  1865  	t.Run("type", func(t *testing.T) {
  1866  		require.True(t, typeInfoComparator(typeInfo, array.Type()))
  1867  	})
  1868  
  1869  	// TestArrayEncodeDecode/empty tests empty array encoding and decoding
  1870  }
  1871  
  1872  func TestArrayStringElement(t *testing.T) {
  1873  
  1874  	t.Parallel()
  1875  
  1876  	t.Run("inline", func(t *testing.T) {
  1877  
  1878  		const arraySize = 4096
  1879  
  1880  		r := newRand(t)
  1881  
  1882  		stringSize := int(MaxInlineArrayElementSize - 3)
  1883  
  1884  		values := make([]Value, arraySize)
  1885  		for i := uint64(0); i < arraySize; i++ {
  1886  			s := randStr(r, stringSize)
  1887  			values[i] = NewStringValue(s)
  1888  		}
  1889  
  1890  		storage := newTestPersistentStorage(t)
  1891  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
  1892  		typeInfo := testTypeInfo{42}
  1893  
  1894  		array, err := NewArray(storage, address, typeInfo)
  1895  		require.NoError(t, err)
  1896  
  1897  		for i := uint64(0); i < arraySize; i++ {
  1898  			err := array.Append(values[i])
  1899  			require.NoError(t, err)
  1900  		}
  1901  
  1902  		verifyArray(t, storage, typeInfo, address, array, values, false)
  1903  
  1904  		stats, err := GetArrayStats(array)
  1905  		require.NoError(t, err)
  1906  		require.Equal(t, uint64(0), stats.StorableSlabCount)
  1907  	})
  1908  
  1909  	t.Run("external slab", func(t *testing.T) {
  1910  
  1911  		const arraySize = 4096
  1912  
  1913  		r := newRand(t)
  1914  
  1915  		stringSize := int(MaxInlineArrayElementSize + 512)
  1916  
  1917  		values := make([]Value, arraySize)
  1918  		for i := uint64(0); i < arraySize; i++ {
  1919  			s := randStr(r, stringSize)
  1920  			values[i] = NewStringValue(s)
  1921  		}
  1922  
  1923  		storage := newTestPersistentStorage(t)
  1924  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
  1925  		typeInfo := testTypeInfo{42}
  1926  
  1927  		array, err := NewArray(storage, address, typeInfo)
  1928  		require.NoError(t, err)
  1929  
  1930  		for i := uint64(0); i < arraySize; i++ {
  1931  			err := array.Append(values[i])
  1932  			require.NoError(t, err)
  1933  		}
  1934  
  1935  		verifyArray(t, storage, typeInfo, address, array, values, false)
  1936  
  1937  		stats, err := GetArrayStats(array)
  1938  		require.NoError(t, err)
  1939  		require.Equal(t, uint64(arraySize), stats.StorableSlabCount)
  1940  	})
  1941  }
  1942  
  1943  func TestArrayStoredValue(t *testing.T) {
  1944  
  1945  	const arraySize = 4096
  1946  
  1947  	typeInfo := testTypeInfo{42}
  1948  	address := Address{1, 2, 3, 4, 5, 6, 7, 8}
  1949  	storage := newTestPersistentStorage(t)
  1950  
  1951  	array, err := NewArray(storage, address, typeInfo)
  1952  	require.NoError(t, err)
  1953  
  1954  	values := make([]Value, arraySize)
  1955  	for i := uint64(0); i < arraySize; i++ {
  1956  		v := Uint64Value(i)
  1957  		values[i] = v
  1958  		err := array.Append(v)
  1959  		require.NoError(t, err)
  1960  	}
  1961  
  1962  	rootID := array.StorageID()
  1963  
  1964  	slabIterator, err := storage.SlabIterator()
  1965  	require.NoError(t, err)
  1966  
  1967  	for {
  1968  		id, slab := slabIterator()
  1969  
  1970  		if id == StorageIDUndefined {
  1971  			break
  1972  		}
  1973  
  1974  		value, err := slab.StoredValue(storage)
  1975  
  1976  		if id == rootID {
  1977  			require.NoError(t, err)
  1978  
  1979  			array2, ok := value.(*Array)
  1980  			require.True(t, ok)
  1981  
  1982  			verifyArray(t, storage, typeInfo, address, array2, values, false)
  1983  		} else {
  1984  			require.Equal(t, 1, errorCategorizationCount(err))
  1985  			var fatalError *FatalError
  1986  			var notValueError *NotValueError
  1987  			require.ErrorAs(t, err, &fatalError)
  1988  			require.ErrorAs(t, err, &notValueError)
  1989  			require.ErrorAs(t, fatalError, &notValueError)
  1990  			require.Nil(t, value)
  1991  		}
  1992  	}
  1993  }
  1994  
  1995  func TestArrayPopIterate(t *testing.T) {
  1996  
  1997  	t.Run("empty", func(t *testing.T) {
  1998  		typeInfo := testTypeInfo{42}
  1999  		storage := newTestPersistentStorage(t)
  2000  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
  2001  
  2002  		array, err := NewArray(storage, address, typeInfo)
  2003  		require.NoError(t, err)
  2004  
  2005  		i := uint64(0)
  2006  		err = array.PopIterate(func(v Storable) {
  2007  			i++
  2008  		})
  2009  		require.NoError(t, err)
  2010  		require.Equal(t, uint64(0), i)
  2011  
  2012  		verifyEmptyArray(t, storage, typeInfo, address, array)
  2013  	})
  2014  
  2015  	t.Run("root-dataslab", func(t *testing.T) {
  2016  
  2017  		const arraySize = 10
  2018  
  2019  		typeInfo := testTypeInfo{42}
  2020  		storage := newTestPersistentStorage(t)
  2021  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
  2022  
  2023  		array, err := NewArray(storage, address, typeInfo)
  2024  		require.NoError(t, err)
  2025  
  2026  		values := make([]Value, arraySize)
  2027  		for i := uint64(0); i < arraySize; i++ {
  2028  			v := Uint64Value(i)
  2029  			values[i] = v
  2030  			err := array.Append(v)
  2031  			require.NoError(t, err)
  2032  		}
  2033  
  2034  		i := 0
  2035  		err = array.PopIterate(func(v Storable) {
  2036  			vv, err := v.StoredValue(storage)
  2037  			require.NoError(t, err)
  2038  			valueEqual(t, typeInfoComparator, values[arraySize-i-1], vv)
  2039  			i++
  2040  		})
  2041  		require.NoError(t, err)
  2042  		require.Equal(t, arraySize, i)
  2043  
  2044  		verifyEmptyArray(t, storage, typeInfo, address, array)
  2045  	})
  2046  
  2047  	t.Run("root-metaslab", func(t *testing.T) {
  2048  		SetThreshold(256)
  2049  		defer SetThreshold(1024)
  2050  
  2051  		const arraySize = 4096
  2052  
  2053  		typeInfo := testTypeInfo{42}
  2054  		storage := newTestPersistentStorage(t)
  2055  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
  2056  
  2057  		array, err := NewArray(storage, address, typeInfo)
  2058  		require.NoError(t, err)
  2059  
  2060  		values := make([]Value, arraySize)
  2061  		for i := uint64(0); i < arraySize; i++ {
  2062  			v := Uint64Value(i)
  2063  			values[i] = v
  2064  			err := array.Append(v)
  2065  			require.NoError(t, err)
  2066  		}
  2067  
  2068  		i := 0
  2069  		err = array.PopIterate(func(v Storable) {
  2070  			vv, err := v.StoredValue(storage)
  2071  			require.NoError(t, err)
  2072  			valueEqual(t, typeInfoComparator, values[arraySize-i-1], vv)
  2073  			i++
  2074  		})
  2075  		require.NoError(t, err)
  2076  		require.Equal(t, arraySize, i)
  2077  
  2078  		verifyEmptyArray(t, storage, typeInfo, address, array)
  2079  	})
  2080  }
  2081  
  2082  func TestArrayFromBatchData(t *testing.T) {
  2083  
  2084  	t.Run("empty", func(t *testing.T) {
  2085  		typeInfo := testTypeInfo{42}
  2086  
  2087  		array, err := NewArray(
  2088  			newTestPersistentStorage(t),
  2089  			Address{1, 2, 3, 4, 5, 6, 7, 8},
  2090  			typeInfo)
  2091  		require.NoError(t, err)
  2092  		require.Equal(t, uint64(0), array.Count())
  2093  
  2094  		iter, err := array.Iterator()
  2095  		require.NoError(t, err)
  2096  
  2097  		// Create a new array with new storage, new address, and original array's elements.
  2098  		address := Address{2, 3, 4, 5, 6, 7, 8, 9}
  2099  		storage := newTestPersistentStorage(t)
  2100  		copied, err := NewArrayFromBatchData(
  2101  			storage,
  2102  			address,
  2103  			array.Type(),
  2104  			func() (Value, error) {
  2105  				return iter.Next()
  2106  			})
  2107  		require.NoError(t, err)
  2108  		require.NotEqual(t, copied.StorageID(), array.StorageID())
  2109  
  2110  		verifyEmptyArray(t, storage, typeInfo, address, copied)
  2111  	})
  2112  
  2113  	t.Run("root-dataslab", func(t *testing.T) {
  2114  
  2115  		const arraySize = 10
  2116  
  2117  		typeInfo := testTypeInfo{42}
  2118  		array, err := NewArray(
  2119  			newTestPersistentStorage(t),
  2120  			Address{1, 2, 3, 4, 5, 6, 7, 8},
  2121  			typeInfo)
  2122  		require.NoError(t, err)
  2123  
  2124  		values := make([]Value, arraySize)
  2125  		for i := uint64(0); i < arraySize; i++ {
  2126  			v := Uint64Value(i)
  2127  			values[i] = v
  2128  			err := array.Append(v)
  2129  			require.NoError(t, err)
  2130  		}
  2131  
  2132  		require.Equal(t, uint64(arraySize), array.Count())
  2133  
  2134  		iter, err := array.Iterator()
  2135  		require.NoError(t, err)
  2136  
  2137  		// Create a new array with new storage, new address, and original array's elements.
  2138  		address := Address{2, 3, 4, 5, 6, 7, 8, 9}
  2139  		storage := newTestPersistentStorage(t)
  2140  		copied, err := NewArrayFromBatchData(
  2141  			storage,
  2142  			address,
  2143  			array.Type(),
  2144  			func() (Value, error) {
  2145  				return iter.Next()
  2146  			})
  2147  
  2148  		require.NoError(t, err)
  2149  		require.NotEqual(t, copied.StorageID(), array.StorageID())
  2150  
  2151  		verifyArray(t, storage, typeInfo, address, copied, values, false)
  2152  	})
  2153  
  2154  	t.Run("root-metaslab", func(t *testing.T) {
  2155  		SetThreshold(256)
  2156  		defer SetThreshold(1024)
  2157  
  2158  		const arraySize = 4096
  2159  
  2160  		typeInfo := testTypeInfo{42}
  2161  
  2162  		array, err := NewArray(
  2163  			newTestPersistentStorage(t),
  2164  			Address{1, 2, 3, 4, 5, 6, 7, 8},
  2165  			typeInfo)
  2166  		require.NoError(t, err)
  2167  
  2168  		values := make([]Value, arraySize)
  2169  		for i := uint64(0); i < arraySize; i++ {
  2170  			v := Uint64Value(i)
  2171  			values[i] = v
  2172  			err := array.Append(v)
  2173  			require.NoError(t, err)
  2174  		}
  2175  
  2176  		require.Equal(t, uint64(arraySize), array.Count())
  2177  
  2178  		iter, err := array.Iterator()
  2179  		require.NoError(t, err)
  2180  
  2181  		address := Address{2, 3, 4, 5, 6, 7, 8, 9}
  2182  		storage := newTestPersistentStorage(t)
  2183  		copied, err := NewArrayFromBatchData(
  2184  			storage,
  2185  			address,
  2186  			array.Type(),
  2187  			func() (Value, error) {
  2188  				return iter.Next()
  2189  			})
  2190  
  2191  		require.NoError(t, err)
  2192  		require.NotEqual(t, array.StorageID(), copied.StorageID())
  2193  
  2194  		verifyArray(t, storage, typeInfo, address, copied, values, false)
  2195  	})
  2196  
  2197  	t.Run("rebalance two data slabs", func(t *testing.T) {
  2198  		SetThreshold(256)
  2199  		defer SetThreshold(1024)
  2200  
  2201  		typeInfo := testTypeInfo{42}
  2202  
  2203  		array, err := NewArray(
  2204  			newTestPersistentStorage(t),
  2205  			Address{1, 2, 3, 4, 5, 6, 7, 8},
  2206  			typeInfo)
  2207  		require.NoError(t, err)
  2208  
  2209  		var values []Value
  2210  		var v Value
  2211  
  2212  		v = NewStringValue(strings.Repeat("a", int(MaxInlineArrayElementSize-2)))
  2213  		values = append(values, v)
  2214  
  2215  		err = array.Insert(0, v)
  2216  		require.NoError(t, err)
  2217  
  2218  		for i := 0; i < 35; i++ {
  2219  			v = Uint64Value(i)
  2220  			values = append(values, v)
  2221  
  2222  			err = array.Append(v)
  2223  			require.NoError(t, err)
  2224  		}
  2225  
  2226  		require.Equal(t, uint64(36), array.Count())
  2227  
  2228  		iter, err := array.Iterator()
  2229  		require.NoError(t, err)
  2230  
  2231  		storage := newTestPersistentStorage(t)
  2232  		address := Address{2, 3, 4, 5, 6, 7, 8, 9}
  2233  		copied, err := NewArrayFromBatchData(
  2234  			storage,
  2235  			address,
  2236  			array.Type(),
  2237  			func() (Value, error) {
  2238  				return iter.Next()
  2239  			})
  2240  
  2241  		require.NoError(t, err)
  2242  		require.NotEqual(t, array.StorageID(), copied.StorageID())
  2243  
  2244  		verifyArray(t, storage, typeInfo, address, copied, values, false)
  2245  	})
  2246  
  2247  	t.Run("merge two data slabs", func(t *testing.T) {
  2248  		SetThreshold(256)
  2249  		defer SetThreshold(1024)
  2250  
  2251  		typeInfo := testTypeInfo{42}
  2252  
  2253  		array, err := NewArray(
  2254  			newTestPersistentStorage(t),
  2255  			Address{1, 2, 3, 4, 5, 6, 7, 8},
  2256  			typeInfo)
  2257  		require.NoError(t, err)
  2258  
  2259  		var values []Value
  2260  		var v Value
  2261  		for i := 0; i < 35; i++ {
  2262  			v = Uint64Value(i)
  2263  			values = append(values, v)
  2264  			err = array.Append(v)
  2265  			require.NoError(t, err)
  2266  		}
  2267  
  2268  		v = NewStringValue(strings.Repeat("a", int(MaxInlineArrayElementSize-2)))
  2269  		values = append(values, nil)
  2270  		copy(values[25+1:], values[25:])
  2271  		values[25] = v
  2272  
  2273  		err = array.Insert(25, v)
  2274  		require.NoError(t, err)
  2275  
  2276  		require.Equal(t, uint64(36), array.Count())
  2277  
  2278  		iter, err := array.Iterator()
  2279  		require.NoError(t, err)
  2280  
  2281  		storage := newTestPersistentStorage(t)
  2282  		address := Address{2, 3, 4, 5, 6, 7, 8, 9}
  2283  		copied, err := NewArrayFromBatchData(
  2284  			storage,
  2285  			address,
  2286  			array.Type(),
  2287  			func() (Value, error) {
  2288  				return iter.Next()
  2289  			})
  2290  
  2291  		require.NoError(t, err)
  2292  		require.NotEqual(t, array.StorageID(), copied.StorageID())
  2293  
  2294  		verifyArray(t, storage, typeInfo, address, copied, values, false)
  2295  	})
  2296  
  2297  	t.Run("random", func(t *testing.T) {
  2298  		SetThreshold(256)
  2299  		defer SetThreshold(1024)
  2300  
  2301  		const arraySize = 4096
  2302  
  2303  		r := newRand(t)
  2304  
  2305  		typeInfo := testTypeInfo{42}
  2306  
  2307  		array, err := NewArray(
  2308  			newTestPersistentStorage(t),
  2309  			Address{1, 2, 3, 4, 5, 6, 7, 8},
  2310  			typeInfo)
  2311  		require.NoError(t, err)
  2312  
  2313  		values := make([]Value, arraySize)
  2314  		for i := uint64(0); i < arraySize; i++ {
  2315  			v := randomValue(r, int(MaxInlineArrayElementSize))
  2316  			values[i] = v
  2317  
  2318  			err := array.Append(v)
  2319  			require.NoError(t, err)
  2320  		}
  2321  
  2322  		require.Equal(t, uint64(arraySize), array.Count())
  2323  
  2324  		iter, err := array.Iterator()
  2325  		require.NoError(t, err)
  2326  
  2327  		storage := newTestPersistentStorage(t)
  2328  
  2329  		address := Address{2, 3, 4, 5, 6, 7, 8, 9}
  2330  		copied, err := NewArrayFromBatchData(
  2331  			storage,
  2332  			address,
  2333  			array.Type(),
  2334  			func() (Value, error) {
  2335  				return iter.Next()
  2336  			})
  2337  
  2338  		require.NoError(t, err)
  2339  		require.NotEqual(t, array.StorageID(), copied.StorageID())
  2340  
  2341  		verifyArray(t, storage, typeInfo, address, copied, values, false)
  2342  	})
  2343  
  2344  	t.Run("data slab too large", func(t *testing.T) {
  2345  		// Slab size must not exceed maxThreshold.
  2346  		// We cannot make this problem happen after Atree Issue #193
  2347  		// was fixed by PR #194 & PR #197. This test is to catch regressions.
  2348  
  2349  		SetThreshold(256)
  2350  		defer SetThreshold(1024)
  2351  
  2352  		r := newRand(t)
  2353  
  2354  		typeInfo := testTypeInfo{42}
  2355  		array, err := NewArray(
  2356  			newTestPersistentStorage(t),
  2357  			Address{1, 2, 3, 4, 5, 6, 7, 8},
  2358  			typeInfo)
  2359  		require.NoError(t, err)
  2360  
  2361  		var values []Value
  2362  		var v Value
  2363  
  2364  		v = NewStringValue(randStr(r, int(MaxInlineArrayElementSize-2)))
  2365  		values = append(values, v)
  2366  		err = array.Append(v)
  2367  		require.NoError(t, err)
  2368  
  2369  		v = NewStringValue(randStr(r, int(MaxInlineArrayElementSize-2)))
  2370  		values = append(values, v)
  2371  		err = array.Append(v)
  2372  		require.NoError(t, err)
  2373  
  2374  		v = NewStringValue(randStr(r, int(MaxInlineArrayElementSize-2)))
  2375  		values = append(values, v)
  2376  		err = array.Append(v)
  2377  		require.NoError(t, err)
  2378  
  2379  		iter, err := array.Iterator()
  2380  		require.NoError(t, err)
  2381  
  2382  		storage := newTestPersistentStorage(t)
  2383  		address := Address{2, 3, 4, 5, 6, 7, 8, 9}
  2384  		copied, err := NewArrayFromBatchData(
  2385  			storage,
  2386  			address,
  2387  			array.Type(),
  2388  			func() (Value, error) {
  2389  				return iter.Next()
  2390  			})
  2391  
  2392  		require.NoError(t, err)
  2393  		require.NotEqual(t, array.StorageID(), copied.StorageID())
  2394  
  2395  		verifyArray(t, storage, typeInfo, address, copied, values, false)
  2396  	})
  2397  }
  2398  
  2399  func TestArrayNestedStorables(t *testing.T) {
  2400  
  2401  	t.Parallel()
  2402  
  2403  	typeInfo := testTypeInfo{42}
  2404  
  2405  	const arraySize = 1024 * 4
  2406  
  2407  	storage := newTestPersistentStorage(t)
  2408  	address := Address{1, 2, 3, 4, 5, 6, 7, 8}
  2409  
  2410  	array, err := NewArray(storage, address, typeInfo)
  2411  	require.NoError(t, err)
  2412  
  2413  	values := make([]Value, arraySize)
  2414  	for i := uint64(0); i < arraySize; i++ {
  2415  		s := strings.Repeat("a", int(i))
  2416  		v := SomeValue{Value: NewStringValue(s)}
  2417  		values[i] = v
  2418  
  2419  		err := array.Append(v)
  2420  		require.NoError(t, err)
  2421  	}
  2422  
  2423  	verifyArray(t, storage, typeInfo, address, array, values, true)
  2424  }
  2425  
  2426  func TestArrayMaxInlineElement(t *testing.T) {
  2427  	t.Parallel()
  2428  
  2429  	r := newRand(t)
  2430  
  2431  	typeInfo := testTypeInfo{42}
  2432  	storage := newTestPersistentStorage(t)
  2433  	address := Address{1, 2, 3, 4, 5, 6, 7, 8}
  2434  
  2435  	array, err := NewArray(storage, address, typeInfo)
  2436  	require.NoError(t, err)
  2437  
  2438  	var values []Value
  2439  	for i := 0; i < 2; i++ {
  2440  		// String length is MaxInlineArrayElementSize - 3 to account for string encoding overhead.
  2441  		v := NewStringValue(randStr(r, int(MaxInlineArrayElementSize-3)))
  2442  		values = append(values, v)
  2443  
  2444  		err = array.Append(v)
  2445  		require.NoError(t, err)
  2446  	}
  2447  
  2448  	require.True(t, array.root.IsData())
  2449  
  2450  	// Size of root data slab with two elements of max inlined size is target slab size minus
  2451  	// storage id size (next storage id is omitted in root slab), and minus 1 byte
  2452  	// (for rounding when computing max inline array element size).
  2453  	require.Equal(t, targetThreshold-storageIDSize-1, uint64(array.root.Header().size))
  2454  
  2455  	verifyArray(t, storage, typeInfo, address, array, values, false)
  2456  }
  2457  
  2458  func TestArrayString(t *testing.T) {
  2459  
  2460  	SetThreshold(256)
  2461  	defer SetThreshold(1024)
  2462  
  2463  	t.Run("small", func(t *testing.T) {
  2464  		const arraySize = 6
  2465  
  2466  		typeInfo := testTypeInfo{42}
  2467  		storage := newTestPersistentStorage(t)
  2468  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
  2469  
  2470  		array, err := NewArray(storage, address, typeInfo)
  2471  		require.NoError(t, err)
  2472  
  2473  		for i := uint64(0); i < arraySize; i++ {
  2474  			err := array.Append(Uint64Value(i))
  2475  			require.NoError(t, err)
  2476  		}
  2477  
  2478  		want := `[0 1 2 3 4 5]`
  2479  		require.Equal(t, want, array.String())
  2480  	})
  2481  
  2482  	t.Run("large", func(t *testing.T) {
  2483  		const arraySize = 120
  2484  
  2485  		typeInfo := testTypeInfo{42}
  2486  		storage := newTestPersistentStorage(t)
  2487  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
  2488  
  2489  		array, err := NewArray(storage, address, typeInfo)
  2490  		require.NoError(t, err)
  2491  
  2492  		for i := uint64(0); i < arraySize; i++ {
  2493  			err := array.Append(Uint64Value(i))
  2494  			require.NoError(t, err)
  2495  		}
  2496  
  2497  		want := `[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119]`
  2498  		require.Equal(t, want, array.String())
  2499  	})
  2500  }
  2501  
  2502  func TestArraySlabDump(t *testing.T) {
  2503  	SetThreshold(256)
  2504  	defer SetThreshold(1024)
  2505  
  2506  	t.Run("small", func(t *testing.T) {
  2507  		const arraySize = 6
  2508  
  2509  		typeInfo := testTypeInfo{42}
  2510  		storage := newTestPersistentStorage(t)
  2511  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
  2512  
  2513  		array, err := NewArray(storage, address, typeInfo)
  2514  		require.NoError(t, err)
  2515  
  2516  		for i := uint64(0); i < arraySize; i++ {
  2517  			err := array.Append(Uint64Value(i))
  2518  			require.NoError(t, err)
  2519  		}
  2520  
  2521  		want := []string{
  2522  			"level 1, ArrayDataSlab id:0x102030405060708.1 size:23 count:6 elements: [0 1 2 3 4 5]",
  2523  		}
  2524  		dumps, err := DumpArraySlabs(array)
  2525  		require.NoError(t, err)
  2526  		require.Equal(t, want, dumps)
  2527  	})
  2528  
  2529  	t.Run("large", func(t *testing.T) {
  2530  		const arraySize = 120
  2531  
  2532  		typeInfo := testTypeInfo{42}
  2533  		storage := newTestPersistentStorage(t)
  2534  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
  2535  
  2536  		array, err := NewArray(storage, address, typeInfo)
  2537  		require.NoError(t, err)
  2538  
  2539  		for i := uint64(0); i < arraySize; i++ {
  2540  			err := array.Append(Uint64Value(i))
  2541  			require.NoError(t, err)
  2542  		}
  2543  
  2544  		want := []string{
  2545  			"level 1, ArrayMetaDataSlab id:0x102030405060708.1 size:52 count:120 children: [{id:0x102030405060708.2 size:213 count:54} {id:0x102030405060708.3 size:285 count:66}]",
  2546  			"level 2, ArrayDataSlab id:0x102030405060708.2 size:213 count:54 elements: [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53]",
  2547  			"level 2, ArrayDataSlab id:0x102030405060708.3 size:285 count:66 elements: [54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119]",
  2548  		}
  2549  
  2550  		dumps, err := DumpArraySlabs(array)
  2551  		require.NoError(t, err)
  2552  		require.Equal(t, want, dumps)
  2553  	})
  2554  
  2555  	t.Run("overflow", func(t *testing.T) {
  2556  
  2557  		typeInfo := testTypeInfo{42}
  2558  		storage := newTestPersistentStorage(t)
  2559  		address := Address{1, 2, 3, 4, 5, 6, 7, 8}
  2560  
  2561  		array, err := NewArray(storage, address, typeInfo)
  2562  		require.NoError(t, err)
  2563  
  2564  		err = array.Append(NewStringValue(strings.Repeat("a", int(MaxInlineArrayElementSize))))
  2565  		require.NoError(t, err)
  2566  
  2567  		want := []string{
  2568  			"level 1, ArrayDataSlab id:0x102030405060708.1 size:24 count:1 elements: [StorageIDStorable({[1 2 3 4 5 6 7 8] [0 0 0 0 0 0 0 2]})]",
  2569  			"overflow: &{0x102030405060708.2 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}",
  2570  		}
  2571  
  2572  		dumps, err := DumpArraySlabs(array)
  2573  		require.NoError(t, err)
  2574  		require.Equal(t, want, dumps)
  2575  	})
  2576  }
  2577  
  2578  func errorCategorizationCount(err error) int {
  2579  	var fatalError *FatalError
  2580  	var userError *UserError
  2581  	var externalError *ExternalError
  2582  
  2583  	count := 0
  2584  	if errors.As(err, &fatalError) {
  2585  		count++
  2586  	}
  2587  	if errors.As(err, &userError) {
  2588  		count++
  2589  	}
  2590  	if errors.As(err, &externalError) {
  2591  		count++
  2592  	}
  2593  	return count
  2594  }