Files
QWERTYkez.Mensura/QWERTYkez.Mensura.Tests/DoubleExtensionsTest.cs
2026-06-12 23:34:00 +07:00

394 lines
13 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.Linq;
using QWERTYkez.Mensura.Extensions;
using Xunit;
namespace QWERTYkez.Mensura.Tests
{
public class DoubleExtensionsTests
{
private const double Tolerance = 1e-12;
#region Single value conversions (non-nullable)
[Theory]
[InlineData(0)]
[InlineData(1)]
[InlineData(255)]
public void ToDouble_Byte_ReturnsExpected(byte value) => Assert.Equal(value, value.ToDouble());
[Theory]
[InlineData(-128)]
[InlineData(0)]
[InlineData(127)]
public void ToDouble_SByte_ReturnsExpected(sbyte value) => Assert.Equal(value, value.ToDouble());
[Theory]
[InlineData(-32768)]
[InlineData(0)]
[InlineData(32767)]
public void ToDouble_Short_ReturnsExpected(short value) => Assert.Equal(value, value.ToDouble());
[Theory]
[InlineData(0)]
[InlineData(1)]
[InlineData(65535)]
public void ToDouble_UShort_ReturnsExpected(ushort value) => Assert.Equal(value, value.ToDouble());
[Theory]
[InlineData(-2147483648)]
[InlineData(0)]
[InlineData(2147483647)]
public void ToDouble_Int_ReturnsExpected(int value) => Assert.Equal(value, value.ToDouble());
[Theory]
[InlineData(0U)]
[InlineData(1U)]
[InlineData(uint.MaxValue)]
public void ToDouble_UInt_ReturnsExpected(uint value) => Assert.Equal(value, value.ToDouble());
[Theory]
[InlineData(-9223372036854775808)]
[InlineData(0)]
[InlineData(9223372036854775807)]
public void ToDouble_Long_ReturnsExpected(long value) => Assert.Equal((double)value, value.ToDouble(), Tolerance);
[Theory]
[InlineData(0UL)]
[InlineData(1UL)]
[InlineData(ulong.MaxValue)]
public void ToDouble_ULong_ReturnsExpected(ulong value) => Assert.Equal((double)value, value.ToDouble(), Tolerance);
[Theory]
[InlineData(-123456789)]
[InlineData(0)]
[InlineData(123456789)]
public void ToDouble_NInt_ReturnsExpected(nint value) => Assert.Equal(value, value.ToDouble());
[Theory]
[InlineData(0u)]
[InlineData(123456789u)]
public void ToDouble_NUInt_ReturnsExpected(nuint value) => Assert.Equal((double)value, value.ToDouble());
[Theory]
[InlineData(0.0f)]
[InlineData(123.456f)]
[InlineData(-987.654f)]
[InlineData(float.Epsilon)]
[InlineData(float.MaxValue)]
public void ToDouble_Float_ReturnsExpected(float value) => Assert.Equal((double)value, value.ToDouble(), Tolerance);
[Theory]
[InlineData(0.0)]
[InlineData(123.456)]
[InlineData(-987.654)]
public void ToDouble_Decimal_ReturnsExpected(decimal value) => Assert.Equal((double)value, value.ToDouble(), Tolerance);
[Theory]
[InlineData(0.0)]
[InlineData(123.456)]
[InlineData(-987.654)]
public void ToDouble_Half_ReturnsExpected(Half value) => Assert.Equal((double)value, value.ToDouble(), Tolerance);
#endregion
#region Single value conversions (nullable)
[Fact]
public void ToDouble_NullableByte_Null_ReturnsZero() => Assert.Equal(0.0, ((byte?)null).ToDouble());
[Fact]
public void ToDouble_NullableSByte_Null_ReturnsZero() => Assert.Equal(0.0, ((sbyte?)null).ToDouble());
[Fact]
public void ToDouble_NullableShort_Null_ReturnsZero() => Assert.Equal(0.0, ((short?)null).ToDouble());
[Fact]
public void ToDouble_NullableUShort_Null_ReturnsZero() => Assert.Equal(0.0, ((ushort?)null).ToDouble());
[Fact]
public void ToDouble_NullableInt_Null_ReturnsZero() => Assert.Equal(0.0, ((int?)null).ToDouble());
[Fact]
public void ToDouble_NullableUInt_Null_ReturnsZero() => Assert.Equal(0.0, ((uint?)null).ToDouble());
[Fact]
public void ToDouble_NullableLong_Null_ReturnsZero() => Assert.Equal(0.0, ((long?)null).ToDouble());
[Fact]
public void ToDouble_NullableULong_Null_ReturnsZero() => Assert.Equal(0.0, ((ulong?)null).ToDouble());
[Fact]
public void ToDouble_NullableNInt_Null_ReturnsZero() => Assert.Equal(0.0, ((nint?)null).ToDouble());
[Fact]
public void ToDouble_NullableNUInt_Null_ReturnsZero() => Assert.Equal(0.0, ((nuint?)null).ToDouble());
[Fact]
public void ToDouble_NullableFloat_Null_ReturnsZero() => Assert.Equal(0.0, ((float?)null).ToDouble());
[Fact]
public void ToDouble_NullableDecimal_Null_ReturnsZero() => Assert.Equal(0.0, ((decimal?)null).ToDouble());
[Fact]
public void ToDouble_NullableHalf_Null_ReturnsZero() => Assert.Equal(0.0, ((Half?)null).ToDouble());
#endregion
#region NET7_0_OR_GREATER
#if NET7_0_OR_GREATER
[Theory]
[InlineData(0)]
[InlineData(1)]
[InlineData(-1)]
[InlineData(long.MaxValue)]
public void ToDouble_Int128_ReturnsExpected(Int128 value) => Assert.Equal((double)value, value.ToDouble(), Tolerance);
[Theory]
[InlineData(0)]
[InlineData(1)]
[InlineData(ulong.MaxValue)]
public void ToDouble_UInt128_ReturnsExpected(UInt128 value) => Assert.Equal((double)value, value.ToDouble(), Tolerance);
[Fact]
public void ToDouble_NullableInt128_Null_ReturnsZero() => Assert.Equal(0.0, ((Int128?)null).ToDouble());
[Fact]
public void ToDouble_NullableUInt128_Null_ReturnsZero() => Assert.Equal(0.0, ((UInt128?)null).ToDouble());
#endif
#endregion
#region IEnumerable<T> -> IEnumerable<double> (non-nullable)
[Fact]
public void ToDouble_IEnumerableByte_ReturnsCorrect()
{
byte[] source = [1, 2, 3];
var result = source.ToDouble();
Assert.Equal(new double[] { 1, 2, 3 }, result);
}
[Fact]
public void ToDouble_IEnumerableByte_Empty_ReturnsEmpty()
{
var source = Array.Empty<byte>();
var result = source.ToDouble();
Assert.Empty(result);
}
[Fact]
public void ToDouble_IEnumerableByte_Null_Throws() => Assert.Null(((IEnumerable<byte>)null!).ToDouble());
[Fact]
public void ToDouble_IEnumerableInt_ReturnsCorrect()
{
int[] source = [-5, 0, 10];
var result = source.ToDouble();
Assert.Equal(new double[] { -5, 0, 10 }, result);
}
[Fact]
public void ToDouble_IEnumerableInt_Null_Throws() => Assert.Null(((IEnumerable<int>)null!).ToDouble());
#endregion
#region IEnumerable<T?> -> IEnumerable<double?>
[Fact]
public void ToDouble_IEnumerableNullableInt_ReturnsCorrect()
{
int?[] source = [1, null, 3];
var result = source.ToDouble();
Assert.Equal(3, result.Length);
Assert.Equal(1.0, result.First());
Assert.Null(result.Skip(1).First());
Assert.Equal(3.0, result.Last());
}
[Fact]
public void ToDouble_IEnumerableNullableInt_Null_Throws() => Assert.Null(((IEnumerable<int?>)null!).ToDouble());
#endregion
#region Array and List conversions (non-nullable)
[Fact]
public void ToDouble_ByteArray_ReturnsDoubleArray()
{
byte[] arr = [10, 20];
var result = arr.ToDouble();
Assert.Equal(new double[] { 10, 20 }, result);
}
[Fact]
public void ToDouble_ByteArray_Null_ReturnsNull() => Assert.Null(((byte[])null!).ToDouble());
[Fact]
public void ToDouble_ByteList_ReturnsDoubleList()
{
var list = new List<byte> { 10, 20 };
var result = list.ToDouble();
Assert.Equal([10, 20], result);
}
[Fact]
public void ToDouble_ByteList_Null_ReturnsNull() => Assert.Null(((List<byte>)null!).ToDouble());
[Fact]
public void ToDouble_IntArray_ReturnsDoubleArray()
{
int[] arr = [-5, 0, 7];
var result = arr.ToDouble();
Assert.Equal(new double[] { -5, 0, 7 }, result);
}
[Fact]
public void ToDouble_IntList_ReturnsDoubleList()
{
var list = new List<int> { -5, 0, 7 };
var result = list.ToDouble();
Assert.Equal([-5, 0, 7], result);
}
#endregion
#region Array and List conversions (nullable)
[Fact]
public void ToDouble_NullableIntArray_ReturnsNullableDoubleArray()
{
int?[] arr = [1, null, 3];
var result = arr.ToDouble();
Assert.Equal(3, result.Length);
Assert.Equal(1.0, result[0]);
Assert.Null(result[1]);
Assert.Equal(3.0, result[2]);
}
[Fact]
public void ToDouble_NullableIntArray_Null_ReturnsNull() => Assert.Null(((int?[])null!).ToDouble());
[Fact]
public void ToDouble_NullableIntList_ReturnsNullableDoubleList()
{
var list = new List<int?> { 1, null, 3 };
var result = list.ToDouble();
Assert.Equal(3, result.Count);
Assert.Equal(1.0, result[0]);
Assert.Null(result[1]);
Assert.Equal(3.0, result[2]);
}
[Fact]
public void ToDouble_NullableIntList_Null_ReturnsNull() => Assert.Null(((List<int?>)null!).ToDouble());
#endregion
#region IReadOnlyCollection<T> -> Span<double>
[Fact]
public void ToDouble_IReadOnlyCollectionByte_Span_Works()
{
byte[] source = [1, 2];
Span<double> dest = new double[source.Length];
((IReadOnlyCollection<byte>)source).ToDouble(dest);
Assert.Equal(1.0, dest[0]);
Assert.Equal(2.0, dest[1]);
}
[Fact]
public void ToDouble_IReadOnlyCollectionByte_EmptySpan_Works()
{
byte[] source = [];
Span<double> dest = [];
((IReadOnlyCollection<byte>)source).ToDouble(dest);
}
[Fact]
public void ToDouble_IReadOnlyCollectionByte_DestinationTooShort_Throws()
{
byte[] source = [1, 2];
Assert.Throws<ArgumentException>(() =>
{
Span<double> dest = new double[1];
((IReadOnlyCollection<byte>)source).ToDouble(dest);
});
}
[Fact]
public void ToDouble_IReadOnlyCollectionNullableInt_Span_HandlesNulls()
{
int?[] source = [1, null, 3];
Span<double?> dest = new double?[3];
((IReadOnlyCollection<int?>)source).ToDouble(dest);
Assert.Equal(1.0, dest[0]);
Assert.Null(dest[1]);
Assert.Equal(3.0, dest[2]);
}
#endregion
#region Span conversions (ToDoubleCore) - через массивы
[Fact]
public void IntSpan_ToDouble_ConversionWorks()
{
int[] source = [1, 2, 3];
var result = source.ToDouble();
Assert.Equal(new double[] { 1, 2, 3 }, result);
}
[Fact]
public void FloatSpan_ToDouble_ConversionWorks()
{
float[] source = [1.1f, -2.2f];
var result = source.ToDouble();
Assert.Equal(1.1f, result[0], Tolerance);
Assert.Equal(-2.2f, result[1], Tolerance);
}
[Fact]
public void NullableDecimalSpan_ToDouble_HandlesNulls()
{
decimal?[] source = [1.5m, null, -3.3m];
var result = source.ToDouble();
Assert.Equal(3, result.Length);
Assert.Equal(1.5, result[0]!.Value, Tolerance);
Assert.Null(result[1]);
Assert.Equal(-3.3, result[2]!.Value, Tolerance);
}
#endregion
#region Edge cases
[Fact]
public void ToDouble_LongMaxValue_DoesNotOverflow()
{
long max = long.MaxValue;
double result = max.ToDouble();
Assert.Equal((double)max, result, Tolerance);
}
[Fact]
public void ToDouble_ULongMaxValue_DoesNotOverflow()
{
ulong max = ulong.MaxValue;
double result = max.ToDouble();
Assert.Equal((double)max, result, Tolerance);
}
[Fact]
public void ToDouble_Decimal_HighPrecision_DoesNotCrash()
{
decimal huge = decimal.MaxValue;
var result = huge.ToDouble();
Assert.False(double.IsInfinity(result));
}
#endregion
}
}