Skip to content

Commit

Permalink
Added config migration mechanism
Browse files Browse the repository at this point in the history
  • Loading branch information
iXab3r committed Nov 8, 2021
1 parent c6bf03d commit 5a7e2bc
Show file tree
Hide file tree
Showing 25 changed files with 855 additions and 262 deletions.
28 changes: 28 additions & 0 deletions PoeEye/PoeShared.Tests/Helpers/NamedTestCaseData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using NUnit.Framework;

namespace PoeShared.Tests.Helpers
{
public class NamedTestCaseData : TestCaseData
{
public NamedTestCaseData(params object[] args) : base(args)
{
}

public NamedTestCaseData(object arg) : base(arg)
{
}

public NamedTestCaseData(object arg1, object arg2) : base(arg1, arg2)
{
}

public NamedTestCaseData(object arg1, object arg2, object arg3) : base(arg1, arg2, arg3)
{
}

public override string ToString()
{
return string.IsNullOrEmpty(TestName) ? base.ToString() : $"{TestName}";
}
}
}
246 changes: 246 additions & 0 deletions PoeEye/PoeShared.Tests/Modularity/ConfigMigrationTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
using NUnit.Framework;
using AutoFixture;
using System;
using PoeShared.Modularity;
using PoeShared.Prism;
using PoeShared.Scaffolding;
using Shouldly;

namespace PoeShared.Tests.Modularity
{
[TestFixture]
public class ConfigMigrationTests : FixtureBase
{
private sealed record ConfigV1 : IPoeEyeConfigVersioned
{
public string StringValue { get; set; }

public int Version { get; set; } = 1;
}

private sealed record ConfigV2 : IPoeEyeConfigVersioned
{
public int IntValue { get; set; }

public int Version { get; set; } = 2;
}

private sealed record ConfigV3 : IPoeEyeConfigVersioned
{
public double DoubleValue { get; set; }

public int Version { get; set; } = 3;
}

private sealed record Config : IPoeEyeConfigVersioned
{
public string StringValue { get; set; }

public int Version { get; set; } = 4;
}

private abstract class ConfigMetadataConverterV1ToV2Base : ConfigMetadataConverter<ConfigMigrationTests.ConfigV1, ConfigMigrationTests.ConfigV2>
{
}

private sealed class ConfigMetadataConverterV1ToV2 : ConfigMetadataConverterV1ToV2Base
{
public override ConfigMigrationTests.ConfigV2 Convert(ConfigMigrationTests.ConfigV1 value)
{
return new ConfigMigrationTests.ConfigV2()
{
IntValue = Int32.Parse(value.StringValue) + 1
};
}
}

private sealed class ConfigMetadataConverterV2ToV3 : ConfigMetadataConverter<ConfigMigrationTests.ConfigV2, ConfigMigrationTests.ConfigV3>
{
public override ConfigMigrationTests.ConfigV3 Convert(ConfigMigrationTests.ConfigV2 value)
{
return new ConfigMigrationTests.ConfigV3()
{
DoubleValue = value.IntValue * 10
};
}
}

private sealed class ConfigMetadataConverterV3ToV4 : ConfigMetadataConverter<ConfigMigrationTests.ConfigV3, ConfigMigrationTests.Config>
{
public override ConfigMigrationTests.Config Convert(ConfigMigrationTests.ConfigV3 value)
{
return new ConfigMigrationTests.Config()
{
StringValue = $"Number is {value.DoubleValue:F0}"
};
}
}

private static readonly string SerializedConfigV1 = @"{
'TypeName': 'PoeShared.Tests.Modularity.ConfigMigrationTests+Config, PoeShared.Tests',
'ConfigValue': {
'StringValue': '1'
},
'Version': 1
}";

private static readonly string SerializedConfigV2 = @"{
'TypeName': 'PoeShared.Tests.Modularity.ConfigMigrationTests+Config, PoeShared.Tests',
'ConfigValue': {
'IntValue': '2'
},
'Version': 2
}";

private static readonly string SerializedConfigV3 = @"{
'TypeName': 'PoeShared.Tests.Modularity.ConfigMigrationTests+Config, PoeShared.Tests',
'ConfigValue': {
'DoubleValue': '20'
},
'Version': 3
}";

private static readonly string SerializedConfigV4 = @"{
'TypeName': 'PoeShared.Tests.Modularity.ConfigMigrationTests+Config, PoeShared.Tests',
'ConfigValue': {
'StringValue': 'Number is 20'
},
'Version': 4
}";

private PoeConfigConverter configConverter;
private PoeConfigConverterMigrationService migrationService;

protected override void SetUp()
{
migrationService = new PoeConfigConverterMigrationService() { AutomaticallyLoadConverters = false };
configConverter = new PoeConfigConverter(migrationService);
}

[Test]
public void ShouldDeserializeV1()
{
//Given
var instance = CreateInstance();
RegisterAll();

//When
var result = instance.Deserialize<IPoeEyeConfigVersioned>(SerializedConfigV1);


//Then
result.Version.ShouldBe(4);
result.GetPropertyValue<string>(nameof(Config.StringValue)).ShouldBe("Number is 20");
}

[Test]
public void ShouldDeserializeV2()
{
//Given
var instance = CreateInstance();
RegisterAll();

//When
var result = instance.Deserialize<IPoeEyeConfigVersioned>(SerializedConfigV2);


//Then
result.Version.ShouldBe(4);
result.GetPropertyValue<string>(nameof(Config.StringValue)).ShouldBe("Number is 20");
}


[Test]
public void ShouldDeserializeV3()
{
//Given
var instance = CreateInstance();
RegisterAll();

//When
var result = instance.Deserialize<IPoeEyeConfigVersioned>(SerializedConfigV3);


//Then
result.Version.ShouldBe(4);
result.GetPropertyValue<string>(nameof(Config.StringValue)).ShouldBe("Number is 20");
}

[Test]
public void ShouldDeserializeV4()
{
//Given
var instance = CreateInstance();
RegisterAll();

//When
var result = instance.Deserialize<IPoeEyeConfigVersioned>(SerializedConfigV4);


//Then
result.Version.ShouldBe(4);
result.GetPropertyValue<string>(nameof(Config.StringValue)).ShouldBe("Number is 20");
}

[Test]
public void ShouldDeserializeToDefaultIfConverterInChainIsMissing()
{
//Given
var instance = CreateInstance();
migrationService.RegisterMetadataConverter(new ConfigMetadataConverterV1ToV2());
migrationService.RegisterMetadataConverter(new ConfigMetadataConverterV3ToV4());

//When
var result = instance.Deserialize<IPoeEyeConfigVersioned>(SerializedConfigV2);

//Then
result.Version.ShouldBe(4);
result.GetPropertyValue<string>(nameof(Config.StringValue)).ShouldBeNullOrEmpty();
}

[Test]
public void ShouldAutomaticallyLoadConvertersWhenNeeded()
{
//Given
migrationService.AutomaticallyLoadConverters = true;
var instance = CreateInstance();

//When
var result = instance.Deserialize<IPoeEyeConfigVersioned>(SerializedConfigV1);

//Then
result.Version.ShouldBe(4);
result.GetPropertyValue<string>(nameof(Config.StringValue)).ShouldBe("Number is 20");
}

[Test]
[TestCase(typeof(ConfigMetadataConverter<,>), false)]
[TestCase(typeof(ConfigMetadataConverterV1ToV2Base), false)]
[TestCase(typeof(ConfigMetadataConverter<SampleVersionedConfig,SampleVersionedConfig>), false)]
[TestCase(typeof(ConfigMetadataConverterV1ToV2), true)]
[TestCase(typeof(ConfigMetadataConverterV2ToV3), true)]
[TestCase(typeof(ConfigMetadataConverterV3ToV4), true)]
[TestCase(typeof(PoeConfigMetadata), false)]
public void ShouldDetectMetadataConverter(Type type, bool expected)
{
//Given
//When
var isConverter = migrationService.IsMetadataConverter(type);

//Then
isConverter.ShouldBe(expected);
}

private void RegisterAll()
{
migrationService.RegisterMetadataConverter(new ConfigMetadataConverterV3ToV4());
migrationService.RegisterMetadataConverter(new ConfigMetadataConverterV1ToV2());
migrationService.RegisterMetadataConverter(new ConfigMetadataConverterV2ToV3());
}

private JsonConfigSerializer CreateInstance()
{
return new JsonConfigSerializer(configConverter);
}
}
}
105 changes: 0 additions & 105 deletions PoeEye/PoeShared.Tests/Modularity/ConfigSerializerTests.cs

This file was deleted.

Loading

0 comments on commit 5a7e2bc

Please sign in to comment.