Skip to content

Commit

Permalink
add rehashing test
Browse files Browse the repository at this point in the history
  • Loading branch information
turbolent committed Apr 23, 2024
1 parent 80ede1e commit e94d7e0
Showing 1 changed file with 165 additions and 0 deletions.
165 changes: 165 additions & 0 deletions migrations/statictypes/statictype_migration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1238,3 +1238,168 @@ func TestCanSkipStaticTypeMigration(t *testing.T) {
test(ty, expected)
}
}

// TestOptionalTypeRehash stores a dictionary in storage,
// which has a key that is a type value with an optional type,
// runs the migration, and ensures the dictionary is still usable
func TestOptionalTypeRehash(t *testing.T) {

t.Parallel()

locationRange := interpreter.EmptyLocationRange

ledger := NewTestLedger(nil, nil)

storageMapKey := interpreter.StringStorageMapKey("dict")
newTestValue := func() interpreter.Value {
return interpreter.NewUnmeteredStringValue("test")
}

newStorageAndInterpreter := func(t *testing.T) (*runtime.Storage, *interpreter.Interpreter) {
storage := runtime.NewStorage(ledger, nil)
inter, err := interpreter.NewInterpreter(
nil,
utils.TestLocation,
&interpreter.Config{
Storage: storage,
AtreeValueValidationEnabled: true,
AtreeStorageValidationEnabled: true,
},
)
require.NoError(t, err)

return storage, inter
}

newOptionalType := func() *interpreter.OptionalStaticType {
return interpreter.NewOptionalStaticType(nil, interpreter.PrimitiveStaticTypeInt)
}

// Prepare
(func() {

storage, inter := newStorageAndInterpreter(t)

dictionaryStaticType := interpreter.NewDictionaryStaticType(
nil,
interpreter.PrimitiveStaticTypeMetaType,
interpreter.PrimitiveStaticTypeString,
)
dictValue := interpreter.NewDictionaryValue(inter, locationRange, dictionaryStaticType)

optionalType := &migrations.LegacyOptionalType{
OptionalStaticType: newOptionalType(),
}

typeValue := interpreter.NewUnmeteredTypeValue(optionalType)

dictValue.Insert(
inter,
locationRange,
typeValue,
newTestValue(),
)

// NOTE: intentionally in old format
assert.Equal(t,
common.TypeID("Int?"),
optionalType.ID(),
)

storageMap := storage.GetStorageMap(
testAddress,
common.PathDomainStorage.Identifier(),
true,
)

storageMap.SetValue(inter,
storageMapKey,
dictValue.Transfer(
inter,
locationRange,
atree.Address(testAddress),
false,
nil,
nil,
),
)

err := storage.Commit(inter, false)
require.NoError(t, err)
})()

// Migrate
(func() {

storage, inter := newStorageAndInterpreter(t)

migration, err := migrations.NewStorageMigration(inter, storage, "test", testAddress)
require.NoError(t, err)

reporter := newTestReporter()

migration.Migrate(
migration.NewValueMigrationsPathMigrator(
reporter,
NewStaticTypeMigration(),
),
)

err = migration.Commit()
require.NoError(t, err)

// Assert

require.Empty(t, reporter.errors)

err = storage.CheckHealth()
require.NoError(t, err)

require.Equal(t,
map[struct {
interpreter.StorageKey
interpreter.StorageMapKey
}]struct{}{
{
StorageKey: interpreter.StorageKey{
Address: testAddress,
Key: common.PathDomainStorage.Identifier(),
},
StorageMapKey: storageMapKey,
}: {},
},
reporter.migrated,
)
})()

// Load
(func() {

storage, inter := newStorageAndInterpreter(t)

storageMap := storage.GetStorageMap(testAddress, common.PathDomainStorage.Identifier(), false)
storedValue := storageMap.ReadValue(inter, storageMapKey)

require.IsType(t, &interpreter.DictionaryValue{}, storedValue)

dictValue := storedValue.(*interpreter.DictionaryValue)

optionalType := newOptionalType()
typeValue := interpreter.NewUnmeteredTypeValue(optionalType)

// NOTE: in *new* format
assert.Equal(t,
common.TypeID("(Int)?"),
optionalType.ID(),
)

value, ok := dictValue.Get(inter, locationRange, typeValue)
require.True(t, ok)

require.IsType(t, &interpreter.StringValue{}, value)
require.Equal(t,
newTestValue(),
value.(*interpreter.StringValue),
)
})()
}

0 comments on commit e94d7e0

Please sign in to comment.