Add unit tests for the various constructors

This commit is contained in:
Frederik Carlier
2019-06-02 00:35:19 +02:00
parent b9c41214c4
commit e5fa322513
3 changed files with 180 additions and 5 deletions

View File

@@ -72,6 +72,24 @@ namespace plistcil.test
Assert.Equal(doubleValue, number.ToDouble(), 5);
}
[Fact]
public void SpanConstructorInvalidValuesTest()
{
Assert.Throws<ArgumentNullException>(() => new NSNumber((Span<byte>)null, NSNumber.INTEGER));
Assert.Throws<ArgumentNullException>(() => new NSNumber((Span<byte>)null, NSNumber.REAL));
Assert.Throws<ArgumentOutOfRangeException>(() => new NSNumber((Span<byte>)Array.Empty<byte>(), NSNumber.INTEGER));
Assert.Throws<ArgumentException>(() => new NSNumber((Span<byte>)Array.Empty<byte>(), NSNumber.REAL));
Assert.Throws<ArgumentException>(() => new NSNumber((Span<byte>)Array.Empty<byte>(), 9));
}
[Fact]
public void StringAndTypeConstructorInvalidValuesTest()
{
Assert.Throws<ArgumentNullException>(() => new NSNumber((string)null, NSNumber.INTEGER));
Assert.Throws<ArgumentNullException>(() => new NSNumber((string)null, NSNumber.REAL));
Assert.Throws<ArgumentException>(() => new NSNumber("0", 9));
}
[Fact]
public static void NSNumberConstructorTest()
{
@@ -138,7 +156,149 @@ namespace plistcil.test
Assert.True(number.isReal());
Assert.Equal(7200d, number.ToDouble());
}
#endif
#endif
public static IEnumerable<object[]> StringConstructorTestData()
{
return new List<object[]>
{
// Long values, formatted as hexadecimal values
new object[] { "0x00", false, 0, 0.0 },
new object[] { "0x1000", true, 0x1000, 1.0 * 0x1000 },
new object[] { "0x00001000", true, 0x1000, 1.0 * 0x1000 },
new object[] { "0x0000000000001000", true, 0x1000, 1.0 * 0x1000 },
// Long values, formatted as decimal values
new object[] { "0", false, 0, 0.0 },
new object[] { "10", true, 10, 10.0 },
// Decimal values
new object[] { "0.0", false, 0, 0.0 },
new object[] { "0.10", false, 0, 0.1 },
new object[] { "3.14", true, 3, 3.14 },
// Boolean values
new object[] { "yes", true, 1, 1},
new object[] { "true", true, 1, 1},
new object[] { "Yes", true, 1, 1},
new object[] { "True", true, 1, 1},
new object[] { "YES", true, 1, 1},
new object[] { "TRUE", true, 1, 1},
new object[] { "no", false, 0, 0},
new object[] { "false", false, 0, 0},
new object[] { "No", false, 0, 0},
new object[] { "False", false, 0, 0},
new object[] { "NO", false, 0, 0},
new object[] { "FALSE", false, 0, 0},
};
}
[Theory]
[MemberData(nameof(StringConstructorTestData))]
public void StringConstructorTest(string value, bool boolValue, long longValue, double doubleValue)
{
NSNumber number = new NSNumber(value);
Assert.Equal(boolValue, number.ToBool());
Assert.Equal(longValue, number.ToLong());
Assert.Equal(doubleValue, number.ToDouble(), 5);
}
[Fact]
public void StringConstructorInvalidValuesTest()
{
Assert.Throws<ArgumentException>(() => new NSNumber(null));
Assert.Throws<ArgumentException>(() => new NSNumber("plist"));
}
public static IEnumerable<object[]> Int32ConstructorTestData()
{
return new List<object[]>
{
// Long values, formatted as hexadecimal values
new object[] { 0, false, 0, 0.0 },
new object[] { 1, true, 1, 1.0 },
new object[] { -1, true, -1, -1.0 },
new object[] { int.MaxValue, true, int.MaxValue, int.MaxValue },
new object[] { int.MinValue, true, int.MinValue, int.MinValue },
};
}
[Theory]
[MemberData(nameof(Int32ConstructorTestData))]
public void Int32ConstructorTest(int value, bool boolValue, long longValue, double doubleValue)
{
NSNumber number = new NSNumber(value);
Assert.Equal(boolValue, number.ToBool());
Assert.Equal(longValue, number.ToLong());
Assert.Equal(doubleValue, number.ToDouble(), 5);
}
public static IEnumerable<object[]> Int64ConstructorTestData()
{
return new List<object[]>
{
// Long values, formatted as hexadecimal values
new object[] { 0, false, 0, 0.0 },
new object[] { 1, true, 1, 1.0 },
new object[] { -1, true, -1, -1.0 },
new object[] { long.MaxValue, true, long.MaxValue, long.MaxValue },
new object[] { long.MinValue, true, long.MinValue, long.MinValue },
};
}
[Theory]
[MemberData(nameof(Int64ConstructorTestData))]
public void Int64ConstructorTest(long value, bool boolValue, long longValue, double doubleValue)
{
NSNumber number = new NSNumber(value);
Assert.Equal(boolValue, number.ToBool());
Assert.Equal(longValue, number.ToLong());
Assert.Equal(doubleValue, number.ToDouble(), 5);
}
public static IEnumerable<object[]> DoubleConstructorTestData()
{
return new List<object[]>
{
// Long values, formatted as hexadecimal values
new object[] { 0.0, false, 0, 0.0 },
new object[] { 1.0, true, 1, 1.0 },
new object[] { -1.0, true, -1, -1.0 },
new object[] { double.Epsilon, false, 0, double.Epsilon },
new object[] { double.MaxValue, true, long.MinValue /* Overflow! */, double.MaxValue },
new object[] { double.MinValue, true, long.MinValue, double.MinValue },
};
}
[Theory]
[MemberData(nameof(DoubleConstructorTestData))]
public void DoubleConstructorTest(double value, bool boolValue, long longValue, double doubleValue)
{
NSNumber number = new NSNumber(value);
Assert.Equal(boolValue, number.ToBool());
Assert.Equal(longValue, number.ToLong());
Assert.Equal(doubleValue, number.ToDouble(), 5);
}
public static IEnumerable<object[]> BoolConstructorTestData()
{
return new List<object[]>
{
// Long values, formatted as hexadecimal values
new object[] { false, false, 0, 0.0 },
new object[] { true, true, 1, 1.0 },
};
}
[Theory]
[MemberData(nameof(BoolConstructorTestData))]
public void BoolConstructorTest(bool value, bool boolValue, long longValue, double doubleValue)
{
NSNumber number = new NSNumber(value);
Assert.Equal(boolValue, number.ToBool());
Assert.Equal(longValue, number.ToLong());
Assert.Equal(doubleValue, number.ToDouble(), 5);
}
[Fact]
public void EqualTest()

View File

@@ -515,6 +515,16 @@ namespace Claunia.PropertyList
/// <param name="bytes">The bytes representing the long integer.</param>
public static long ParseLong(ReadOnlySpan<byte> bytes)
{
if(bytes == null)
{
throw new ArgumentNullException(nameof(bytes));
}
if(bytes.Length == 0)
{
throw new ArgumentOutOfRangeException(nameof(bytes));
}
// https://opensource.apple.com/source/CF/CF-1153.18/CFBinaryPList.c,
// __CFBinaryPlistCreateObjectFiltered, case kCFBinaryPlistMarkerInt:
//
@@ -564,6 +574,11 @@ namespace Claunia.PropertyList
/// <param name="bytes">The bytes representing the double.</param>
public static double ParseDouble(ReadOnlySpan<byte> bytes)
{
if(bytes == null)
{
throw new ArgumentNullException(nameof(bytes));
}
if(bytes.Length == 8) return BitConverter.Int64BitsToDouble(ParseLong(bytes));
if(bytes.Length == 4) return BitConverter.ToSingle(BitConverter.GetBytes(ParseLong(bytes)), 0);

View File

@@ -83,7 +83,7 @@ namespace Claunia.PropertyList
longValue = (long)Math.Round(doubleValue);
break;
default: throw new ArgumentException("Type argument is not valid.");
default: throw new ArgumentException("Type argument is not valid.", nameof(type));
}
this.type = type;
@@ -124,13 +124,12 @@ namespace Claunia.PropertyList
long l;
double d;
if(text.StartsWith("0x") && long.TryParse("", NumberStyles.HexNumber, CultureInfo.InvariantCulture, out l))
if(text.StartsWith("0x") && long.TryParse(text.Substring(2), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out l))
{
doubleValue = longValue = l;
type = INTEGER;
}
if(long.TryParse(text, NumberStyles.Number, CultureInfo.InvariantCulture, out l))
else if(long.TryParse(text, NumberStyles.Number, CultureInfo.InvariantCulture, out l))
{
doubleValue = longValue = l;
type = INTEGER;
@@ -151,6 +150,7 @@ namespace Claunia.PropertyList
if(isTrue || isFalse)
{
type = BOOLEAN;
boolValue = isTrue;
doubleValue = longValue = boolValue ? 1 : 0;
}
else