Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,6 @@ public EncodedStringToUInt32Converter() { }
/// </summary>
public IValueConverter<uint, string?> ToSource => _convertToSource;

/// <inheritdoc />
public readonly object? ConvertToDestination(object? source) => ConvertToDestination((string?)source);

/// <inheritdoc />
public readonly object? ConvertToSource(object? destination) => ConvertToSource((uint)destination!);

/// <inheritdoc />
public readonly uint ConvertToDestination(string? source) => ToDestination.Convert(source);

Expand Down
6 changes: 6 additions & 0 deletions src/CoreEx/Mapping/Converters/IConverterT.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ public interface IConverter<TSource, TDestination> : ISourceConverter<TSource>,
/// <inheritdoc/>
object? IDestinationConverter<TDestination>.ConvertToSource(TDestination destination) => ConvertToSource((TDestination)destination!);

/// <inheritdoc/>
object? IConverter.ConvertToDestination(object? source) => ConvertToDestination((TSource)source!);

/// <inheritdoc/>
object? IConverter.ConvertToSource(object? destination) => ConvertToSource((TDestination)destination!);

/// <summary>
/// Gets the source to destination <see cref="IValueConverter{TSource, TDestination}"/>.
/// </summary>
Expand Down
6 changes: 0 additions & 6 deletions src/CoreEx/Mapping/Converters/JsonElementStringConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,6 @@ public JsonElementStringConverter() { }
/// </summary>
public IValueConverter<string?, JsonElement?> ToSource => _convertToSource;

/// <inheritdoc />
public readonly object? ConvertToDestination(object? source) => ConvertToDestination((string?)source);

/// <inheritdoc />
public readonly object? ConvertToSource(object? destination) => ConvertToSource((JsonElement?)destination);

/// <inheritdoc />
public readonly string? ConvertToDestination(JsonElement? source) => ToDestination.Convert(source);

Expand Down
6 changes: 0 additions & 6 deletions src/CoreEx/Mapping/Converters/StringBase64Converter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,6 @@ public StringBase64Converter() { }
/// </summary>
public IValueConverter<byte[]?, string?> ToSource => _convertToSource;

/// <inheritdoc />
public readonly object? ConvertToDestination(object? source) => ConvertToDestination((string?)source);

/// <inheritdoc />
public readonly object? ConvertToSource(object? destination) => ConvertToSource((byte[]?)destination);

/// <inheritdoc />
public readonly byte[]? ConvertToDestination(string? source) => ToDestination.Convert(source);

Expand Down
6 changes: 0 additions & 6 deletions src/CoreEx/Mapping/Converters/TypeToJsonStringConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,6 @@ public TypeToJsonStringConverter() { }
/// </summary>
public IValueConverter<string?, T> ToSource => _convertToSource;

/// <inheritdoc />
public readonly object? ConvertToDestination(object? source) => ConvertToDestination((T)source!);

/// <inheritdoc />
public readonly object? ConvertToSource(object? destination) => ConvertToSource((string?)destination);

/// <inheritdoc />
public readonly string? ConvertToDestination(T source) => ToDestination.Convert(source);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
using CoreEx.Mapping.Converters;

namespace CoreEx.Test.Unit.Mapping.Converters;

[TestFixture]
public class EncodedStringToUInt32ConverterTests
{
private readonly EncodedStringToUInt32Converter _converter = EncodedStringToUInt32Converter.Default;

[Test]
public void ConvertToDestination_ValidBase64String_ReturnsUInt32()
{
var value = 12345u;
var base64 = Convert.ToBase64String(BitConverter.GetBytes(value));

_converter.ConvertToDestination(base64).Should().Be(value);
}

[Test]
public void ConvertToDestination_Null_ReturnsZero()
{
_converter.ConvertToDestination((string?)null).Should().Be(0u);
}

[Test]
public void ConvertToSource_ValidUInt32_ReturnsBase64String()
{
var value = 98765u;

var result = _converter.ConvertToSource(value);

result.Should().Be(Convert.ToBase64String(BitConverter.GetBytes(value)));
}

[Test]
public void ConvertToSource_Zero_ReturnsNull()
{
_converter.ConvertToSource(0u).Should().BeNull();
}

[Test]
public void RoundTrip_UInt32ToBase64AndBack()
{
var value = 555u;
var base64 = _converter.ConvertToSource(value);
var roundTrip = _converter.ConvertToDestination(base64);

roundTrip.Should().Be(value);
}

// The following two tests exercise the non-generic IConverter object-based overloads directly (see issue #175,
// which found the exact same defect class in JsonElementStringConverter's non-generic overloads).
[Test]
public void IConverter_ConvertToDestination_Object_ReturnsUInt32()
{
IConverter converter = _converter;
var value = 4242u;
var base64 = Convert.ToBase64String(BitConverter.GetBytes(value));

var result = converter.ConvertToDestination(base64);

result.Should().Be(value);
}

[Test]
public void IConverter_ConvertToSource_Object_ReturnsBase64String()
{
IConverter converter = _converter;
var value = 111u;

var result = converter.ConvertToSource(value);

result.Should().Be(Convert.ToBase64String(BitConverter.GetBytes(value)));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
using System.Text.Json;
using CoreEx.Mapping.Converters;

namespace CoreEx.Test.Unit.Mapping.Converters;

[TestFixture]
public class JsonElementStringConverterTests
{
private readonly JsonElementStringConverter _converter = JsonElementStringConverter.Default;

[Test]
public void ConvertToDestination_Value_ReturnsJson()
{
using var doc = JsonDocument.Parse("""{"name":"Bob","number":42}""");
var result = _converter.ConvertToDestination(doc.RootElement);

result.Should().Be("""{"name":"Bob","number":42}""");
}

[Test]
public void ConvertToDestination_Null_ReturnsNull()
{
_converter.ConvertToDestination((JsonElement?)null).Should().BeNull();
}

[Test]
public void ConvertToSource_Json_ReturnsJsonElement()
{
var result = _converter.ConvertToSource("""{"name":"Bob","number":42}""");

result!.Value.GetProperty("name").GetString().Should().Be("Bob");
result.Value.GetProperty("number").GetInt32().Should().Be(42);
}

[Test]
public void ConvertToSource_Null_ReturnsNull()
{
_converter.ConvertToSource((string?)null).Should().BeNull();
}

[Test]
public void RoundTrip_JsonElementToStringAndBack()
{
using var doc = JsonDocument.Parse("""{"name":"Alice","number":7}""");
var json = _converter.ConvertToDestination(doc.RootElement);
var roundTrip = _converter.ConvertToSource(json);

roundTrip!.Value.GetProperty("name").GetString().Should().Be("Alice");
roundTrip.Value.GetProperty("number").GetInt32().Should().Be(7);
}

// The following two tests exercise the non-generic IConverter object-based overloads directly, which is
// where a copy/paste bug (issue #175) previously caused an InvalidCastException or infinite recursion
// (StackOverflowException) because the casts were against the wrong side's type (TDestination instead of
// TSource, and vice versa).
[Test]
public void IConverter_ConvertToDestination_Object_ReturnsJson()
{
IConverter converter = _converter;
using var doc = JsonDocument.Parse("""{"name":"Bob","number":42}""");

var result = converter.ConvertToDestination(doc.RootElement);

result.Should().Be("""{"name":"Bob","number":42}""");
}

[Test]
public void IConverter_ConvertToSource_Object_ReturnsJsonElement()
{
IConverter converter = _converter;

var result = (JsonElement?)converter.ConvertToSource("""{"name":"Bob","number":42}""");

result!.Value.GetProperty("name").GetString().Should().Be("Bob");
result.Value.GetProperty("number").GetInt32().Should().Be(42);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,29 @@ public void ConvertToDestination_InvalidBase64_ThrowsFormatException()
Action act = () => _converter.ConvertToDestination("not_base64!");
act.Should().Throw<FormatException>();
}

// The following two tests exercise the non-generic IConverter object-based overloads directly (see issue #175,
// which found the exact same defect class in JsonElementStringConverter's non-generic overloads).
[Test]
public void IConverter_ConvertToDestination_Object_ReturnsBytes()
{
IConverter converter = _converter;
var text = "Hello, World!";
var base64 = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(text));

var result = (byte[]?)converter.ConvertToDestination(base64);

System.Text.Encoding.UTF8.GetString(result!).Should().Be(text);
}

[Test]
public void IConverter_ConvertToSource_Object_ReturnsBase64String()
{
IConverter converter = _converter;
var bytes = System.Text.Encoding.UTF8.GetBytes("Test123");

var result = converter.ConvertToSource(bytes);

result.Should().Be(Convert.ToBase64String(bytes));
}
}
Loading