Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Type safe enum deserialization #84

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions ChartJs.Blazor.Tests/ChartJs.Blazor.Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>

<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.analyzers" Version="0.10.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="1.0.1" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\src\ChartJs.Blazor\ChartJs.Blazor.csproj" />
</ItemGroup>

</Project>
122 changes: 122 additions & 0 deletions ChartJs.Blazor.Tests/ObjectEnumTests.Deserialization.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
using ChartJs.Blazor.ChartJS.Common.Enums;
using Newtonsoft.Json;
using System;
using System.Globalization;
using Xunit;

namespace ChartJs.Blazor.Tests
{
public partial class ObjectEnumTests
{
[Theory]
[InlineData("0", 0)]
[InlineData("10", 10)]
[InlineData("-1234567489", -1234567489)]
public void Deserialize_IntEnum_FromRoot(string json, int expectedValue)
{
// Act
TestObjectEnum objEnum = JsonConvert.DeserializeObject<TestObjectEnum>(json);

// Assert
Assert.True(objEnum.Equals(expectedValue)); // expects all the equality stuff to be correct
}

[Theory]
// [InlineData("0", 0.0)] this would fail because it gets serialized as int, not double
[InlineData("0.0", 0.0)]
[InlineData("123.456", 123.456)]
[InlineData("-654.321", -654.321)]
public void Deserialize_DoubleEnum_FromRoot(string json, double expectedValue)
{
// Act
TestObjectEnum objEnum = JsonConvert.DeserializeObject<TestObjectEnum>(json);

// Assert
Assert.True(objEnum.Equals(expectedValue)); // expects all the equality stuff to be correct
}

[Theory]
[InlineData("0", 0)]
[InlineData("10", 10)]
[InlineData("-1234567489", -1234567489)]
public void Deserialize_DoubleEnumThroughInt_FromRoot(string json, double expectedValue)
{
// Act
// the json would result in an int being deserialized but since there is no int
// that would fail. So instead it uses the double constructor.
DoubleStringEnum objEnum = JsonConvert.DeserializeObject<DoubleStringEnum>(json);

// Assert
Assert.True(objEnum.Equals(expectedValue)); // expects all the equality stuff to be correct
}

[Theory]
[InlineData("\"Hello World!\"", "Hello World!")]
[InlineData("\"\\\"That's what!\\\", she said.\"", "\"That's what!\", she said.")]
[InlineData("\"¨öä$ü¨^'{}][\\\\|/-.,+-/*\"", "¨öä$ü¨^'{}][\\|/-.,+-/*")]
public void Deserialize_StringEnum_FromRoot(string json, string expectedValue)
{
// Act
TestObjectEnum objEnum = JsonConvert.DeserializeObject<TestObjectEnum>(json);

// Assert
Assert.True(objEnum.Equals(expectedValue)); // expects all the equality stuff to be correct
}

[Fact]
public void Deserialize_BigIntegerEnum_ThrowsNotSupported()
{
// Arrange
string json = $"{ulong.MaxValue}"; // bigger than long.MaxValue

// Act & Assert
Assert.Throws<NotSupportedException>(() => JsonConvert.DeserializeObject<TestObjectEnum>(json));
}

[Fact]
public void Deserialize_JsonArray_ThrowsNotSupported()
{
// Arrange
const string json = "[1,2,3]";

// Act & Assert
Assert.Throws<NotSupportedException>(() => JsonConvert.DeserializeObject<TestObjectEnum>(json));
}

[Fact]
public void Deserialize_JsonObject_ThrowsNotSupported()
{
// Arrange
string json = "{}";

// Act & Assert
Assert.Throws<NotSupportedException>(() => JsonConvert.DeserializeObject<TestObjectEnum>(json));
}

[Fact]
public void Deserialize_Null_ReturnsNull()
{
// Arrange
string json = "null";

// Act
TestObjectEnum objEnum = JsonConvert.DeserializeObject<TestObjectEnum>(json);

// Assert
Assert.Null(objEnum);
}

[Fact]
public void Deserialize_Undefined_ReturnsNull()
{
// Arrange
string json = "undefined";

// Act
TestObjectEnum objEnum = JsonConvert.DeserializeObject<TestObjectEnum>(json);

// Assert
Assert.Null(objEnum);
}
}
}
245 changes: 245 additions & 0 deletions ChartJs.Blazor.Tests/ObjectEnumTests.Equality.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
using ChartJs.Blazor.ChartJS.Common.Enums;
using Newtonsoft.Json;
using System;
using System.Globalization;
using Xunit;

namespace ChartJs.Blazor.Tests
{
public partial class ObjectEnumTests
{
[Fact]
public void Equals_IntEnumAndIntEnum_ReturnsTrue()
{
// Arrange
const int ExampleIntValue = 10;
var a = TestObjectEnum.Int(ExampleIntValue);
var b = TestObjectEnum.Int(ExampleIntValue);

// Act
bool equal = a.Equals(b);

// Assert
Assert.True(equal);
}

[Fact]
public void Equals_IntEnumAndInt_ReturnsTrue()
{
// Arrange
const int ExampleIntValue = 10;
var a = TestObjectEnum.Int(ExampleIntValue);

// Act
bool equal = a.Equals(ExampleIntValue);

// Assert
Assert.True(equal);
}

[Fact]
public void Equals_StringEnumAndStringEnum_ReturnsTrue()
{
// Arrange
var a = TestObjectEnum.Auto;
var b = TestObjectEnum.Auto; // different instance, same inner value

// Act
bool equal = a.Equals(b);

// Assert
Assert.True(equal);
}

[Fact]
public void Equals_StringEnumAndString_ReturnsTrue()
{
// Arrange
const string ExampleStringValue = "abcdefg";
var a = TestObjectEnum.CustomString(ExampleStringValue);

// Act
bool equal = a.Equals(ExampleStringValue);

// Assert
Assert.True(equal);
}

[Fact]
public void Equals_DoubleEnumAndDoubleEnum_ReturnsTrue()
{
// Arrange
const double ExampleDoubleValue = 123.456;
var a = TestObjectEnum.Double(ExampleDoubleValue);
var b = TestObjectEnum.Double(ExampleDoubleValue);

// Act
bool equal = a.Equals(b);

// Assert
Assert.True(equal);
}

[Fact]
public void Equals_DoubleEnumAndDouble_ReturnsTrue()
{
// Arrange
const double ExampleDoubleValue = 123.456;
var a = TestObjectEnum.Double(ExampleDoubleValue);

// Act
bool equal = a.Equals(ExampleDoubleValue);

// Assert
Assert.True(equal);
}

[Fact]
public void Equals_EnumAndNull_ReturnsFalse()
{
// Arrange
var a = TestObjectEnum.CustomObject(new object());

// Act
bool equal = a.Equals(null);

// Assert
Assert.False(equal);
}

[Fact]
public void Equals_SameReference_ReturnsTrue()
{
// Arrange
var a = TestObjectEnum.CustomObject(new object());
var b = a;

// Act
bool equal = a.Equals(b);

// Assert
Assert.True(equal);
}

[Fact]
public void EqualityOperator_IntEnumAndIntEnum_ReturnsTrue()
{
// Arrange
const int ExampleIntValue = 10;
var a = TestObjectEnum.Int(ExampleIntValue);
var b = TestObjectEnum.Int(ExampleIntValue);

// Act
bool equal = a == b;

// Assert
Assert.True(equal);
}

[Fact]
public void EqualityOperator_StringEnumAndStringEnum_ReturnsTrue()
{
// Arrange
var a = TestObjectEnum.Auto;
var b = TestObjectEnum.Auto; // different instance, same inner value

// Act
bool equal = a == b;

// Assert
Assert.True(equal);
}

[Fact]
public void EqualityOperator_DoubleEnumAndDoubleEnum_ReturnsTrue()
{
// Arrange
const double ExampleDoubleValue = 123.456;
var a = TestObjectEnum.Double(ExampleDoubleValue);
var b = TestObjectEnum.Double(ExampleDoubleValue);

// Act
bool equal = a == b;

// Assert
Assert.True(equal);
}

[Fact]
public void EqualityOperator_EnumAndNull_ReturnsFalse()
{
// Arrange
var a = TestObjectEnum.CustomObject(new object());

// Act
bool equal = a == null;

// Assert
Assert.False(equal);
}

[Fact]
public void EqualityOperator_NullAndNull_ReturnsTrue()
{
// Arrange
TestObjectEnum a = null;

// Act
bool equal = a == null;

// Assert
Assert.True(equal);
}

[Fact]
public void EqualityOperator_SameReference_ReturnsTrue()
{
// Arrange
var a = TestObjectEnum.CustomObject(new object());
var b = a;

// Act
bool equal = a == b;

// Assert
Assert.True(equal);
}

[Theory]
[InlineData(10)]
[InlineData(123.456)]
[InlineData("asdf")]
[InlineData(false)]
public void GetHashCode_InnerValueAndEnum_Equals(object value)
{
// Arrange
TestObjectEnum objEnum = TestObjectEnum.CustomObject(value);

// Act
int hashCodeValue = value.GetHashCode();
int hashCodeEnum = objEnum.GetHashCode();

// Assert
Assert.Equal(hashCodeValue, hashCodeEnum);
}

[Theory]
[InlineData(-10)]
[InlineData(-654.321)]
[InlineData("fdsa")]
[InlineData(true)]
public void GetHashCode_EnumAndEnum_Equals(object value)
{
// Arrange
var a = TestObjectEnum.CustomObject(value);
var b = TestObjectEnum.CustomObject(value);

// Act
int hashA = a.GetHashCode();
int hashB = b.GetHashCode();

// Assert
Assert.Equal(hashA, hashB);
}
}
}
Loading