1071 lines
60 KiB
C#
Raw Normal View History

// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.Serialization.Json;
using System.Text;
using Xunit;
namespace System.Json
{
/// <summary>
/// JsonPrimitive unit tests
/// </summary>
public class JsonPrimitiveTests
{
const string DateTimeFormat = "yyyy-MM-ddTHH:mm:ss.fffK";
/// <summary>
/// Validates round-trip of <see cref="JsonPrimitive"/> values created from <see cref="Int16"/> values.
/// </summary>
[Fact]
public void JsonPrimitiveFromInt16()
{
short[] values = new short[] { Int16.MinValue, Int16.MaxValue, 1 };
for (int i = 0; i < values.Length; i++)
{
this.ValidateJson(new JsonPrimitive(values[i]), GetExpectedRepresentation(values[i]), JsonType.Number);
this.TestReadAsRoundtrip<short>(new JsonPrimitive(values[i]), values[i]);
}
}
/// <summary>
/// Validates round-trip of <see cref="JsonPrimitive"/> values created from <see cref="Int32"/> values.
/// </summary>
[Fact]
public void JsonPrimitiveFromInt32()
{
int[] values = new int[] { Int32.MinValue, Int32.MaxValue, 12345678 };
for (int i = 0; i < values.Length; i++)
{
this.ValidateJson(new JsonPrimitive(values[i]), GetExpectedRepresentation(values[i]), JsonType.Number);
this.TestReadAsRoundtrip<int>(new JsonPrimitive(values[i]), values[i]);
}
}
/// <summary>
/// Validates round-trip of <see cref="JsonPrimitive"/> values created from <see cref="Int64"/> values.
/// </summary>
[Fact]
public void JsonPrimitiveFromInt64()
{
long[] values = new long[] { Int64.MinValue, Int64.MaxValue, 12345678901232L };
for (int i = 0; i < values.Length; i++)
{
this.ValidateJson(new JsonPrimitive(values[i]), GetExpectedRepresentation(values[i]), JsonType.Number);
this.TestReadAsRoundtrip<long>(new JsonPrimitive(values[i]), values[i]);
}
}
/// <summary>
/// Validates round-trip of <see cref="JsonPrimitive"/> values created from <see cref="UInt64"/> values.
/// </summary>
[Fact]
public void JsonPrimitiveFromUInt64()
{
ulong[] values = new ulong[] { UInt64.MinValue, UInt64.MaxValue, 12345678901232L };
for (int i = 0; i < values.Length; i++)
{
this.ValidateJson(new JsonPrimitive(values[i]), GetExpectedRepresentation(values[i]), JsonType.Number);
this.TestReadAsRoundtrip<ulong>(new JsonPrimitive(values[i]), values[i]);
}
}
/// <summary>
/// Validates round-trip of <see cref="JsonPrimitive"/> values created from <see cref="UInt32"/> values.
/// </summary>
[Fact]
public void JsonPrimitiveFromUInt32()
{
uint[] values = new uint[] { UInt32.MinValue, UInt32.MaxValue, 3234567890 };
for (int i = 0; i < values.Length; i++)
{
this.ValidateJson(new JsonPrimitive(values[i]), GetExpectedRepresentation(values[i]), JsonType.Number);
this.TestReadAsRoundtrip<uint>(new JsonPrimitive(values[i]), values[i]);
}
}
/// <summary>
/// Validates round-trip of <see cref="JsonPrimitive"/> values created from <see cref="UInt16"/> values.
/// </summary>
[Fact]
public void JsonPrimitiveFromUInt16()
{
ushort[] values = new ushort[] { UInt16.MinValue, UInt16.MaxValue, 33333 };
for (int i = 0; i < values.Length; i++)
{
this.ValidateJson(new JsonPrimitive(values[i]), GetExpectedRepresentation(values[i]), JsonType.Number);
this.TestReadAsRoundtrip<ushort>(new JsonPrimitive(values[i]), values[i]);
}
}
/// <summary>
/// Validates round-trip of <see cref="JsonPrimitive"/> values created from <see cref="Byte"/> values.
/// </summary>
[Fact]
public void JsonPrimitiveFromByte()
{
byte[] values = new byte[] { Byte.MinValue, Byte.MaxValue, 0x83 };
for (int i = 0; i < values.Length; i++)
{
this.ValidateJson(new JsonPrimitive(values[i]), GetExpectedRepresentation(values[i]), JsonType.Number);
this.TestReadAsRoundtrip<byte>(new JsonPrimitive(values[i]), values[i]);
}
}
/// <summary>
/// Validates round-trip of <see cref="JsonPrimitive"/> values created from <see cref="SByte"/> values.
/// </summary>
[Fact]
public void JsonPrimitiveFromSByte()
{
sbyte[] values = new sbyte[] { SByte.MinValue, SByte.MaxValue, -0x33 };
for (int i = 0; i < values.Length; i++)
{
this.ValidateJson(new JsonPrimitive(values[i]), GetExpectedRepresentation(values[i]), JsonType.Number);
this.TestReadAsRoundtrip<sbyte>(new JsonPrimitive(values[i]), values[i]);
}
}
/// <summary>
/// Validates round-trip of <see cref="JsonPrimitive"/> values created from <see cref="Single"/> values.
/// </summary>
[Fact]
public void JsonPrimitiveFromFloat()
{
float[] values = new float[] { float.MinValue, float.MaxValue, 1.234f, float.PositiveInfinity, float.NegativeInfinity, float.NaN };
for (int i = 0; i < values.Length; i++)
{
this.ValidateJson(new JsonPrimitive(values[i]), GetExpectedRepresentation(values[i]), JsonType.Number);
this.TestReadAsRoundtrip<float>(new JsonPrimitive(values[i]), values[i]);
}
}
/// <summary>
/// Validates round-trip of <see cref="JsonPrimitive"/> values created from <see cref="Double"/> values.
/// </summary>
[Fact]
public void JsonPrimitiveFromDouble()
{
double[] values = new double[] { double.MinValue, double.MaxValue, 1.234, double.PositiveInfinity, double.NegativeInfinity, double.NaN };
for (int i = 0; i < values.Length; i++)
{
this.ValidateJson(new JsonPrimitive(values[i]), GetExpectedRepresentation(values[i]), JsonType.Number);
this.TestReadAsRoundtrip<double>(new JsonPrimitive(values[i]), values[i]);
}
}
/// <summary>
/// Validates round-trip of <see cref="JsonPrimitive"/> values created from <see cref="Decimal"/> values.
/// </summary>
[Fact]
public void JsonPrimitiveFromDecimal()
{
decimal[] values = new decimal[] { decimal.MinValue, decimal.MaxValue, 123456789.123456789m };
for (int i = 0; i < values.Length; i++)
{
this.ValidateJson(new JsonPrimitive(values[i]), GetExpectedRepresentation(values[i]), JsonType.Number);
this.TestReadAsRoundtrip<decimal>(new JsonPrimitive(values[i]), values[i]);
}
}
/// <summary>
/// Validates round-trip of <see cref="JsonPrimitive"/> values created from <see cref="Boolean"/> values.
/// </summary>
[Fact]
public void JsonPrimitiveFromBoolean()
{
bool[] values = new bool[] { true, false };
for (int i = 0; i < values.Length; i++)
{
this.ValidateJson(new JsonPrimitive(values[i]), GetExpectedRepresentation(values[i]), JsonType.Boolean);
this.TestReadAsRoundtrip<bool>(new JsonPrimitive(values[i]), values[i]);
}
}
/// <summary>
/// Validates round-trip of <see cref="JsonPrimitive"/> values created from <see cref="Char"/> values.
/// </summary>
[Fact]
public void JsonPrimitiveFromChar()
{
char[] values = new char[] { 'H', '\0', '\uffff' };
for (int i = 0; i < values.Length; i++)
{
this.ValidateJson(new JsonPrimitive(values[i]), GetExpectedRepresentation(values[i]), JsonType.String);
this.TestReadAsRoundtrip<char>(new JsonPrimitive(values[i]), values[i]);
}
}
/// <summary>
/// Validates round-trip of <see cref="JsonPrimitive"/> values created from <see cref="String"/> values.
/// </summary>
[Fact]
public void JsonPrimitiveFromString()
{
string[] values = new string[] { "Hello", "abcdef", "\r\t123\n32" };
for (int i = 0; i < values.Length; i++)
{
this.ValidateJson(new JsonPrimitive(values[i]), GetExpectedRepresentation(values[i]), JsonType.String);
this.TestReadAsRoundtrip<string>(new JsonPrimitive(values[i]), values[i]);
}
}
/// <summary>
/// Validates round-trip of <see cref="JsonPrimitive"/> values created from <see cref="DateTime"/> values.
/// </summary>
[Fact]
public void JsonPrimitiveFromDateTime()
{
DateTime[] values = new DateTime[]
{
new DateTime(2000, 10, 16, 8, 0, 0, DateTimeKind.Utc),
new DateTime(2000, 10, 16, 8, 0, 0, DateTimeKind.Local),
};
for (int i = 0; i < values.Length; i++)
{
this.ValidateJson(new JsonPrimitive(values[i]), GetExpectedRepresentation(values[i]), JsonType.String);
this.TestReadAsRoundtrip<DateTime>(new JsonPrimitive(values[i]), values[i]);
}
}
/// <summary>
/// Validates round-trip of <see cref="JsonPrimitive"/> values created from <see cref="Uri"/> values.
/// </summary>
[Fact]
public void JsonPrimitiveFromUri()
{
Uri[] values = new Uri[] { new Uri("http://tempuri.org"), new Uri("foo/bar", UriKind.Relative) };
for (int i = 0; i < values.Length; i++)
{
this.ValidateJson(new JsonPrimitive(values[i]), GetExpectedRepresentation(values[i]), JsonType.String);
this.TestReadAsRoundtrip<Uri>(new JsonPrimitive(values[i]), values[i]);
}
}
/// <summary>
/// Validates round-trip of <see cref="JsonPrimitive"/> values created from <see cref="Guid"/> values.
/// </summary>
[Fact]
public void JsonPrimitiveFromGuid()
{
Guid[] values = new Guid[] { Guid.NewGuid(), Guid.Empty, Guid.NewGuid() };
for (int i = 0; i < values.Length; i++)
{
this.ValidateJson(new JsonPrimitive(values[i]), GetExpectedRepresentation(values[i]), JsonType.String);
this.TestReadAsRoundtrip<Guid>(new JsonPrimitive(values[i]), values[i]);
}
}
/// <summary>
/// Validates round-trip of <see cref="JsonPrimitive"/> values created from different types of values.
/// </summary>
[Fact]
public void JsonPrimitiveFromObject()
{
List<KeyValuePair<object, JsonType>> values = new List<KeyValuePair<object, JsonType>>
{
new KeyValuePair<object, JsonType>(true, JsonType.Boolean),
new KeyValuePair<object, JsonType>((short)1, JsonType.Number),
new KeyValuePair<object, JsonType>(234, JsonType.Number),
new KeyValuePair<object, JsonType>(3435434233443L, JsonType.Number),
new KeyValuePair<object, JsonType>(UInt64.MaxValue, JsonType.Number),
new KeyValuePair<object, JsonType>(UInt32.MaxValue, JsonType.Number),
new KeyValuePair<object, JsonType>(UInt16.MaxValue, JsonType.Number),
new KeyValuePair<object, JsonType>(Byte.MaxValue, JsonType.Number),
new KeyValuePair<object, JsonType>(SByte.MinValue, JsonType.Number),
new KeyValuePair<object, JsonType>(double.MaxValue, JsonType.Number),
new KeyValuePair<object, JsonType>(float.Epsilon, JsonType.Number),
new KeyValuePair<object, JsonType>(decimal.MinusOne, JsonType.Number),
new KeyValuePair<object, JsonType>("hello", JsonType.String),
new KeyValuePair<object, JsonType>(Guid.NewGuid(), JsonType.String),
new KeyValuePair<object, JsonType>(DateTime.UtcNow, JsonType.String),
new KeyValuePair<object, JsonType>(new Uri("http://www.microsoft.com"), JsonType.String),
};
foreach (var value in values)
{
string json = GetExpectedRepresentation(value.Key);
JsonValue jsonValue = JsonValue.Parse(json);
Assert.IsType(typeof(JsonPrimitive), jsonValue);
this.ValidateJson((JsonPrimitive)jsonValue, json, value.Value);
}
}
/// <summary>
/// Negative tests for <see cref="JsonPrimitive"/> constructors with null values.
/// </summary>
[Fact]
public void NullChecks()
{
ExpectException<ArgumentNullException>(() => new JsonPrimitive((string)null));
ExpectException<ArgumentNullException>(() => new JsonPrimitive((Uri)null));
}
/// <summary>
/// Tests for casting string values into non-string values.
/// </summary>
[Fact]
public void CastingFromStringTests()
{
int seed = MethodBase.GetCurrentMethod().Name.GetHashCode();
Random rndGen = new Random(seed);
Assert.Equal(false, (bool)(new JsonPrimitive("false")));
Assert.Equal(false, (bool)(new JsonPrimitive("False")));
Assert.Equal(true, (bool)(new JsonPrimitive("true")));
Assert.Equal(true, (bool)(new JsonPrimitive("True")));
byte b = PrimitiveCreator.CreateInstanceOfByte(rndGen);
Assert.Equal(b, (byte)(new JsonPrimitive(b.ToString(CultureInfo.InvariantCulture))));
decimal dec = PrimitiveCreator.CreateInstanceOfDecimal(rndGen);
Assert.Equal(dec, (decimal)(new JsonPrimitive(dec.ToString(CultureInfo.InvariantCulture))));
double dbl = rndGen.NextDouble() * rndGen.Next();
Assert.Equal(dbl, (double)(new JsonPrimitive(dbl.ToString("R", CultureInfo.InvariantCulture))));
Assert.Equal(Double.PositiveInfinity, (double)(new JsonPrimitive("Infinity")));
Assert.Equal(Double.NegativeInfinity, (double)(new JsonPrimitive("-Infinity")));
Assert.Equal(Double.NaN, (double)(new JsonPrimitive("NaN")));
ExpectException<InvalidCastException>(delegate { var d = (double)(new JsonPrimitive("INF")); });
ExpectException<InvalidCastException>(delegate { var d = (double)(new JsonPrimitive("-INF")); });
ExpectException<InvalidCastException>(delegate { var d = (double)(new JsonPrimitive("infinity")); });
ExpectException<InvalidCastException>(delegate { var d = (double)(new JsonPrimitive("INFINITY")); });
ExpectException<InvalidCastException>(delegate { var d = (double)(new JsonPrimitive("nan")); });
ExpectException<InvalidCastException>(delegate { var d = (double)(new JsonPrimitive("Nan")); });
float flt = (float)(rndGen.NextDouble() * rndGen.Next());
Assert.Equal(flt, (float)(new JsonPrimitive(flt.ToString("R", CultureInfo.InvariantCulture))));
Assert.Equal(Single.PositiveInfinity, (float)(new JsonPrimitive("Infinity")));
Assert.Equal(Single.NegativeInfinity, (float)(new JsonPrimitive("-Infinity")));
Assert.Equal(Single.NaN, (float)(new JsonPrimitive("NaN")));
ExpectException<InvalidCastException>(delegate { var f = (float)(new JsonPrimitive("INF")); });
ExpectException<InvalidCastException>(delegate { var f = (float)(new JsonPrimitive("-INF")); });
ExpectException<InvalidCastException>(delegate { var f = (float)(new JsonPrimitive("infinity")); });
ExpectException<InvalidCastException>(delegate { var f = (float)(new JsonPrimitive("INFINITY")); });
ExpectException<InvalidCastException>(delegate { var f = (float)(new JsonPrimitive("nan")); });
ExpectException<InvalidCastException>(delegate { var f = (float)(new JsonPrimitive("Nan")); });
int i = PrimitiveCreator.CreateInstanceOfInt32(rndGen);
Assert.Equal(i, (int)(new JsonPrimitive(i.ToString(CultureInfo.InvariantCulture))));
long l = PrimitiveCreator.CreateInstanceOfInt64(rndGen);
Assert.Equal(l, (long)(new JsonPrimitive(l.ToString(CultureInfo.InvariantCulture))));
sbyte sb = PrimitiveCreator.CreateInstanceOfSByte(rndGen);
Assert.Equal(sb, (sbyte)(new JsonPrimitive(sb.ToString(CultureInfo.InvariantCulture))));
short s = PrimitiveCreator.CreateInstanceOfInt16(rndGen);
Assert.Equal(s, (short)(new JsonPrimitive(s.ToString(CultureInfo.InvariantCulture))));
ushort ui16 = PrimitiveCreator.CreateInstanceOfUInt16(rndGen);
Assert.Equal(ui16, (ushort)(new JsonPrimitive(ui16.ToString(CultureInfo.InvariantCulture))));
uint ui32 = PrimitiveCreator.CreateInstanceOfUInt32(rndGen);
Assert.Equal(ui32, (uint)(new JsonPrimitive(ui32.ToString(CultureInfo.InvariantCulture))));
ulong ui64 = PrimitiveCreator.CreateInstanceOfUInt64(rndGen);
Assert.Equal(ui64, (ulong)(new JsonPrimitive(ui64.ToString(CultureInfo.InvariantCulture))));
}
/// <summary>
/// Tests for casting <see cref="JsonPrimitive"/> created from special floating point values (infinity, NaN).
/// </summary>
[Fact]
public void CastingNumbersTest()
{
Assert.Equal(float.PositiveInfinity, (float)(new JsonPrimitive(double.PositiveInfinity)));
Assert.Equal(float.NegativeInfinity, (float)(new JsonPrimitive(double.NegativeInfinity)));
Assert.Equal(float.NaN, (float)(new JsonPrimitive(double.NaN)));
Assert.Equal(double.PositiveInfinity, (double)(new JsonPrimitive(float.PositiveInfinity)));
Assert.Equal(double.NegativeInfinity, (double)(new JsonPrimitive(float.NegativeInfinity)));
Assert.Equal(double.NaN, (double)(new JsonPrimitive(float.NaN)));
}
/// <summary>
/// Tests for the many formats which can be cast to a <see cref="DateTime"/>.
/// </summary>
[Fact]
public void CastingDateTimeTest()
{
int seed = MethodBase.GetCurrentMethod().Name.GetHashCode();
Random rndGen = new Random(seed);
DateTime dt = new DateTime(
rndGen.Next(1000, 3000), // year
rndGen.Next(1, 13), // month
rndGen.Next(1, 28), // day
rndGen.Next(0, 24), // hour
rndGen.Next(0, 60), // minute
rndGen.Next(0, 60), // second
DateTimeKind.Utc);
Log.Info("dt = {0}", dt);
const string JsonDateFormat = "yyyy-MM-ddTHH:mm:ssZ";
string dateString = dt.ToString(JsonDateFormat, CultureInfo.InvariantCulture);
JsonValue jv = dateString;
DateTime dt2 = (DateTime)jv;
Assert.Equal(dt.ToUniversalTime(), dt2.ToUniversalTime());
const string DateTimeLocalFormat = "yyyy-MM-ddTHH:mm:ss";
const string DateLocalFormat = "yyyy-MM-dd";
const string TimeLocalFormat = "HH:mm:ss";
for (int i = 0; i < 100; i++)
{
DateTime dateLocal = PrimitiveCreator.CreateInstanceOfDateTime(rndGen).ToLocalTime();
dateLocal = new DateTime(dateLocal.Year, dateLocal.Month, dateLocal.Day, dateLocal.Hour, dateLocal.Minute, dateLocal.Second, DateTimeKind.Local);
string localDateTime = dateLocal.ToString(DateTimeLocalFormat, CultureInfo.InvariantCulture);
string localDate = dateLocal.ToString(DateLocalFormat, CultureInfo.InvariantCulture);
string localTime = dateLocal.ToString(TimeLocalFormat, CultureInfo.InvariantCulture);
Assert.Equal(dateLocal, new JsonPrimitive(localDateTime).ReadAs<DateTime>());
Assert.Equal(dateLocal.Date, new JsonPrimitive(localDate).ReadAs<DateTime>());
DateTime timeOnly = new JsonPrimitive(localTime).ReadAs<DateTime>();
Assert.Equal(dateLocal.Hour, timeOnly.Hour);
Assert.Equal(dateLocal.Minute, timeOnly.Minute);
Assert.Equal(dateLocal.Second, timeOnly.Second);
DataContractJsonSerializer dcjs = new DataContractJsonSerializer(typeof(DateTime));
using (MemoryStream ms = new MemoryStream())
{
dcjs.WriteObject(ms, dateLocal);
ms.Position = 0;
JsonValue jvFromString = JsonValue.Load(ms);
Assert.Equal(dateLocal, jvFromString.ReadAs<DateTime>());
}
using (MemoryStream ms = new MemoryStream())
{
DateTime dateUtc = dateLocal.ToUniversalTime();
dcjs.WriteObject(ms, dateUtc);
ms.Position = 0;
JsonValue jvFromString = JsonValue.Load(ms);
Assert.Equal(dateUtc, jvFromString.ReadAs<DateTime>());
}
}
}
/// <summary>
/// Tests for date parsing form the RFC2822 format.
/// </summary>
[Fact]
public void Rfc2822DateTimeFormatTest()
{
string[] localFormats = new string[]
{
"ddd, d MMM yyyy HH:mm:ss zzz",
"d MMM yyyy HH:mm:ss zzz",
"ddd, dd MMM yyyy HH:mm:ss zzz",
"ddd, dd MMM yyyy HH:mm zzz",
};
string[] utcFormats = new string[]
{
@"ddd, d MMM yyyy HH:mm:ss \U\T\C",
"d MMM yyyy HH:mm:ssZ",
@"ddd, dd MMM yyyy HH:mm:ss \U\T\C",
"ddd, dd MMM yyyy HH:mmZ",
};
DateTime today = DateTime.Today;
int seed = today.Year * 10000 + today.Month * 100 + today.Day;
Log.Info("Seed: {0}", seed);
Random rndGen = new Random(seed);
const int DatesToTry = 100;
const string DateTraceFormat = "ddd yyyy/MM/dd HH:mm:ss.fffZ";
for (int i = 0; i < DatesToTry; i++)
{
DateTime dt = PrimitiveCreator.CreateInstanceOfDateTime(rndGen);
dt = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second, dt.Kind);
Log.Info("Test with date: {0} ({1})", dt.ToString(DateTraceFormat, CultureInfo.InvariantCulture), dt.Kind);
string[] formatsToTest = dt.Kind == DateTimeKind.Utc ? utcFormats : localFormats;
foreach (string format in formatsToTest)
{
string strDate = dt.ToString(format, CultureInfo.InvariantCulture);
Log.Info("As string: {0} (format = {1})", strDate, format);
JsonPrimitive jp = new JsonPrimitive(strDate);
DateTime parsedDate = jp.ReadAs<DateTime>();
Log.Info("Parsed date: {0} ({1})", parsedDate.ToString(DateTraceFormat, CultureInfo.InvariantCulture), parsedDate.Kind);
DateTime dtExpected = dt;
DateTime dtActual = parsedDate;
if (dt.Kind != parsedDate.Kind)
{
dtExpected = dtExpected.ToUniversalTime();
dtActual = dtActual.ToUniversalTime();
}
Assert.Equal(dtExpected.Year, dtActual.Year);
Assert.Equal(dtExpected.Month, dtActual.Month);
Assert.Equal(dtExpected.Day, dtActual.Day);
Assert.Equal(dtExpected.Hour, dtActual.Hour);
Assert.Equal(dtExpected.Minute, dtActual.Minute);
if (format.Contains(":ss"))
{
Assert.Equal(dtExpected.Second, dtActual.Second);
}
else
{
Assert.Equal(0, parsedDate.Second);
}
}
Log.Info("");
}
}
/// <summary>
/// Tests for the <see cref="System.Json.JsonValue.ReadAs{T}()"/> function from string values.
/// </summary>
[Fact]
public void ReadAsFromStringTests()
{
int seed = MethodBase.GetCurrentMethod().Name.GetHashCode();
Random rndGen = new Random(seed);
TestReadAsFromStringRoundtrip<bool>(false, "false");
TestReadAsFromStringRoundtrip<bool>(false, "False");
TestReadAsFromStringRoundtrip<bool>(true, "true");
TestReadAsFromStringRoundtrip<bool>(true, "True");
TestReadAsFromStringRoundtrip<byte>(PrimitiveCreator.CreateInstanceOfByte(rndGen));
TestReadAsFromStringRoundtrip<char>(PrimitiveCreator.CreateInstanceOfChar(rndGen));
TestReadAsFromStringRoundtrip<decimal>(PrimitiveCreator.CreateInstanceOfDecimal(rndGen));
TestReadAsFromStringRoundtrip<int>(PrimitiveCreator.CreateInstanceOfInt32(rndGen));
TestReadAsFromStringRoundtrip<long>(PrimitiveCreator.CreateInstanceOfInt64(rndGen));
TestReadAsFromStringRoundtrip<sbyte>(PrimitiveCreator.CreateInstanceOfSByte(rndGen));
TestReadAsFromStringRoundtrip<short>(PrimitiveCreator.CreateInstanceOfInt16(rndGen));
TestReadAsFromStringRoundtrip<ushort>(PrimitiveCreator.CreateInstanceOfUInt16(rndGen));
TestReadAsFromStringRoundtrip<uint>(PrimitiveCreator.CreateInstanceOfUInt32(rndGen));
TestReadAsFromStringRoundtrip<ulong>(PrimitiveCreator.CreateInstanceOfUInt64(rndGen));
double dbl = rndGen.NextDouble() * rndGen.Next();
TestReadAsFromStringRoundtrip<double>(dbl, dbl.ToString("R", CultureInfo.InvariantCulture));
TestReadAsFromStringRoundtrip<double>(double.PositiveInfinity, "Infinity");
TestReadAsFromStringRoundtrip<double>(double.NegativeInfinity, "-Infinity");
TestReadAsFromStringRoundtrip<double>(double.NaN, "NaN");
float flt = (float)(rndGen.NextDouble() * rndGen.Next());
TestReadAsFromStringRoundtrip<float>(flt, flt.ToString("R", CultureInfo.InvariantCulture));
TestReadAsFromStringRoundtrip<float>(float.PositiveInfinity, "Infinity");
TestReadAsFromStringRoundtrip<float>(float.NegativeInfinity, "-Infinity");
TestReadAsFromStringRoundtrip<float>(float.NaN, "NaN");
Guid guid = PrimitiveCreator.CreateInstanceOfGuid(rndGen);
TestReadAsFromStringRoundtrip<Guid>(guid, guid.ToString("N", CultureInfo.InvariantCulture));
TestReadAsFromStringRoundtrip<Guid>(guid, guid.ToString("D", CultureInfo.InvariantCulture));
TestReadAsFromStringRoundtrip<Guid>(guid, guid.ToString("B", CultureInfo.InvariantCulture));
TestReadAsFromStringRoundtrip<Guid>(guid, guid.ToString("P", CultureInfo.InvariantCulture));
TestReadAsFromStringRoundtrip<Guid>(guid, guid.ToString("X", CultureInfo.InvariantCulture));
TestReadAsFromStringRoundtrip<Guid>(guid, guid.ToString("X", CultureInfo.InvariantCulture).Replace("0x", "0X"));
TestReadAsFromStringRoundtrip<Guid>(guid, guid.ToString("X", CultureInfo.InvariantCulture).Replace("{", " { "));
TestReadAsFromStringRoundtrip<Guid>(guid, guid.ToString("X", CultureInfo.InvariantCulture).Replace("}", " } "));
TestReadAsFromStringRoundtrip<Guid>(guid, guid.ToString("X", CultureInfo.InvariantCulture).Replace(",", " , "));
TestReadAsFromStringRoundtrip<Guid>(guid, guid.ToString("X", CultureInfo.InvariantCulture).Replace("0x", "0x0000"));
Uri uri = null;
do
{
try
{
uri = PrimitiveCreator.CreateInstanceOfUri(rndGen);
}
catch (UriFormatException)
{
}
} while (uri == null);
TestReadAsFromStringRoundtrip<Uri>(uri);
TestReadAsFromStringRoundtrip<string>(PrimitiveCreator.CreateInstanceOfString(rndGen));
// Roundtrip reference DateTime to remove some of the precision in the ticks. Otherwise, value is too precise.
DateTimeOffset dateTimeOffset = PrimitiveCreator.CreateInstanceOfDateTimeOffset(rndGen);
const string ISO8601Format = "yyyy-MM-ddTHH:mm:sszzz";
dateTimeOffset = DateTimeOffset.ParseExact(dateTimeOffset.ToString(ISO8601Format, CultureInfo.InvariantCulture), ISO8601Format, CultureInfo.InvariantCulture);
DateTime dateTime = dateTimeOffset.UtcDateTime;
TestReadAsFromStringRoundtrip<DateTime>(dateTime, dateTimeOffset.ToUniversalTime().ToString(@"ddd, d MMM yyyy HH:mm:ss \U\T\C"));
TestReadAsFromStringRoundtrip<DateTime>(dateTime, dateTimeOffset.ToUniversalTime().ToString(@"ddd, d MMM yyyy HH:mm:ss \G\M\T"));
TestReadAsFromStringRoundtrip<DateTime>(dateTime.ToLocalTime(), dateTimeOffset.ToString(@"ddd, d MMM yyyy HH:mm:ss zzz"));
TestReadAsFromStringRoundtrip<DateTime>(dateTime, dateTime.ToString("yyyy-MM-ddTHH:mm:ssK"));
TestReadAsFromStringRoundtrip<DateTime>(dateTime.ToLocalTime(), dateTimeOffset.ToString(@"ddd, d MMM yyyy HH:mm:ss zzz"));
TestReadAsFromStringRoundtrip<DateTime>(dateTime.ToLocalTime(), dateTimeOffset.ToString("yyyy-MM-ddTHH:mm:sszzz"));
TestReadAsFromStringRoundtrip<DateTimeOffset>(dateTimeOffset.UtcDateTime, dateTimeOffset.ToUniversalTime().ToString(@"ddd, d MMM yyyy HH:mm:ss \U\T\C"));
TestReadAsFromStringRoundtrip<DateTimeOffset>(dateTimeOffset.UtcDateTime, dateTimeOffset.ToUniversalTime().ToString(@"ddd, d MMM yyyy HH:mm:ss \G\M\T"));
TestReadAsFromStringRoundtrip<DateTimeOffset>(dateTimeOffset, dateTimeOffset.ToUniversalTime().ToString(@"ddd, d MMM yyyy HH:mm:ss zzz"));
TestReadAsFromStringRoundtrip<DateTimeOffset>(dateTimeOffset, dateTime.ToString("yyyy-MM-ddTHH:mm:ssK"));
TestReadAsFromStringRoundtrip<DateTimeOffset>(dateTimeOffset, dateTimeOffset.ToString("yyyy-MM-ddTHH:mm:sszzz"));
TestReadAsFromStringRoundtrip<DateTimeOffset>(dateTimeOffset, dateTimeOffset.ToString(@"ddd, d MMM yyyy HH:mm:ss zzz"));
// Create ASPNetFormat DateTime
long unixEpochMilliseconds = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks / 10000;
long millisecondsFromUnixEpoch = dateTime.Ticks / 10000 - unixEpochMilliseconds;
string AspNetFormattedDateTime = String.Format("/Date({0})/", millisecondsFromUnixEpoch);
string AspNetFormattedDateTimeWithValidTZ = String.Format("/Date({0}+0700)/", millisecondsFromUnixEpoch);
string AspNetFormattedDateTimeInvalid1 = String.Format("/Date({0}+99999)/", millisecondsFromUnixEpoch);
string AspNetFormattedDateTimeInvalid2 = String.Format("/Date({0}+07z0)/", millisecondsFromUnixEpoch);
TestReadAsFromStringRoundtrip<DateTime>(dateTime, AspNetFormattedDateTime);
TestReadAsFromStringRoundtrip<DateTime>(dateTime.ToLocalTime(), AspNetFormattedDateTimeWithValidTZ);
TestReadAsFromStringRoundtrip<DateTimeOffset>(dateTimeOffset, AspNetFormattedDateTime);
TestReadAsFromStringRoundtrip<DateTimeOffset>(dateTimeOffset, AspNetFormattedDateTimeWithValidTZ);
ExpectException<FormatException>(delegate { new JsonPrimitive(AspNetFormattedDateTimeInvalid1).ReadAs<DateTime>(); });
ExpectException<FormatException>(delegate { new JsonPrimitive(AspNetFormattedDateTimeInvalid2).ReadAs<DateTime>(); });
ExpectException<FormatException>(delegate { new JsonPrimitive(AspNetFormattedDateTimeInvalid1).ReadAs<DateTimeOffset>(); });
ExpectException<FormatException>(delegate { new JsonPrimitive(AspNetFormattedDateTimeInvalid2).ReadAs<DateTimeOffset>(); });
ExpectException<FormatException>(delegate { new JsonPrimitive("INF").ReadAs<float>(); });
ExpectException<FormatException>(delegate { new JsonPrimitive("-INF").ReadAs<float>(); });
ExpectException<FormatException>(delegate { new JsonPrimitive("infinity").ReadAs<float>(); });
ExpectException<FormatException>(delegate { new JsonPrimitive("INFINITY").ReadAs<float>(); });
ExpectException<FormatException>(delegate { new JsonPrimitive("nan").ReadAs<float>(); });
ExpectException<FormatException>(delegate { new JsonPrimitive("Nan").ReadAs<float>(); });
ExpectException<FormatException>(delegate { new JsonPrimitive("INF").ReadAs<double>(); });
ExpectException<FormatException>(delegate { new JsonPrimitive("-INF").ReadAs<double>(); });
ExpectException<FormatException>(delegate { new JsonPrimitive("infinity").ReadAs<double>(); });
ExpectException<FormatException>(delegate { new JsonPrimitive("INFINITY").ReadAs<double>(); });
ExpectException<FormatException>(delegate { new JsonPrimitive("nan").ReadAs<double>(); });
ExpectException<FormatException>(delegate { new JsonPrimitive("Nan").ReadAs<double>(); });
}
/// <summary>
/// Tests for the <see cref="System.Json.JsonValue.ReadAs{T}()">JsonValue.ReadAs&lt;string&gt;</see> method from number values.
/// </summary>
[Fact]
public void TestReadAsStringFromNumbers()
{
int seed = MethodBase.GetCurrentMethod().Name.GetHashCode();
Random rndGen = new Random(seed);
int intValue = PrimitiveCreator.CreateInstanceOfInt32(rndGen);
JsonValue jv = intValue;
Assert.Equal(intValue.ToString(CultureInfo.InvariantCulture), jv.ToString());
Assert.Equal(intValue.ToString(CultureInfo.InvariantCulture), jv.ReadAs<string>());
uint uintValue = PrimitiveCreator.CreateInstanceOfUInt32(rndGen);
jv = uintValue;
Assert.Equal(uintValue.ToString(CultureInfo.InvariantCulture), jv.ToString());
Assert.Equal(uintValue.ToString(CultureInfo.InvariantCulture), jv.ReadAs<string>());
long longValue = PrimitiveCreator.CreateInstanceOfInt64(rndGen);
jv = longValue;
Assert.Equal(longValue.ToString(CultureInfo.InvariantCulture), jv.ToString());
Assert.Equal(longValue.ToString(CultureInfo.InvariantCulture), jv.ReadAs<string>());
ulong ulongValue = PrimitiveCreator.CreateInstanceOfUInt64(rndGen);
jv = ulongValue;
Assert.Equal(ulongValue.ToString(CultureInfo.InvariantCulture), jv.ToString());
Assert.Equal(ulongValue.ToString(CultureInfo.InvariantCulture), jv.ReadAs<string>());
short shortValue = PrimitiveCreator.CreateInstanceOfInt16(rndGen);
jv = shortValue;
Assert.Equal(shortValue.ToString(CultureInfo.InvariantCulture), jv.ToString());
Assert.Equal(shortValue.ToString(CultureInfo.InvariantCulture), jv.ReadAs<string>());
ushort ushortValue = PrimitiveCreator.CreateInstanceOfUInt16(rndGen);
jv = ushortValue;
Assert.Equal(ushortValue.ToString(CultureInfo.InvariantCulture), jv.ToString());
Assert.Equal(ushortValue.ToString(CultureInfo.InvariantCulture), jv.ReadAs<string>());
byte byteValue = PrimitiveCreator.CreateInstanceOfByte(rndGen);
jv = byteValue;
Assert.Equal(byteValue.ToString(CultureInfo.InvariantCulture), jv.ToString());
Assert.Equal(byteValue.ToString(CultureInfo.InvariantCulture), jv.ReadAs<string>());
sbyte sbyteValue = PrimitiveCreator.CreateInstanceOfSByte(rndGen);
jv = sbyteValue;
Assert.Equal(sbyteValue.ToString(CultureInfo.InvariantCulture), jv.ToString());
Assert.Equal(sbyteValue.ToString(CultureInfo.InvariantCulture), jv.ReadAs<string>());
decimal decValue = PrimitiveCreator.CreateInstanceOfDecimal(rndGen);
jv = decValue;
Assert.Equal(decValue.ToString(CultureInfo.InvariantCulture), jv.ToString());
Assert.Equal(decValue.ToString(CultureInfo.InvariantCulture), jv.ReadAs<string>());
float fltValue = PrimitiveCreator.CreateInstanceOfSingle(rndGen);
jv = fltValue;
Assert.Equal(fltValue.ToString("R", CultureInfo.InvariantCulture), jv.ToString());
Assert.Equal(fltValue.ToString("R", CultureInfo.InvariantCulture), jv.ReadAs<string>());
double dblValue = PrimitiveCreator.CreateInstanceOfDouble(rndGen);
jv = dblValue;
Assert.Equal(dblValue.ToString("R", CultureInfo.InvariantCulture), jv.ToString());
Assert.Equal(dblValue.ToString("R", CultureInfo.InvariantCulture), jv.ReadAs<string>());
}
/// <summary>
/// Tests for the <see cref="System.Json.JsonValue.ReadAs{T}()">JsonValue.ReadAs&lt;string&gt;</see> method from date values.
/// </summary>
[Fact]
public void TestReadAsStringFromDates()
{
int seed = MethodBase.GetCurrentMethod().Name.GetHashCode();
Random rndGen = new Random(seed);
DateTime dateTimeValue = PrimitiveCreator.CreateInstanceOfDateTime(rndGen);
JsonValue jv = dateTimeValue;
Assert.Equal("\"" + dateTimeValue.ToString(DateTimeFormat, CultureInfo.InvariantCulture) + "\"", jv.ToString());
Assert.Equal(dateTimeValue.ToString(DateTimeFormat, CultureInfo.InvariantCulture), jv.ReadAs<string>());
}
/// <summary>
/// Tests for the <see cref="System.Json.JsonValue.ReadAs{T}()">JsonValue.ReadAs&lt;string&gt;</see> method from char values.
/// </summary>
[Fact]
public void TestReadAsStringFromChar()
{
char[] chars = "abc\u0000\b\f\r\n\t\ufedc".ToCharArray();
foreach (char c in chars)
{
string expected = new string(c, 1);
JsonValue jv = c;
string actual1 = jv.ReadAs<string>();
string actual2 = (string)jv;
Assert.Equal(expected, actual1);
Assert.Equal(expected, actual2);
}
}
/// <summary>
/// Tests for the <see cref="System.Json.JsonValue.ReadAs{T}()"/> method where T is a number type and the value is created from a string.
/// </summary>
[Fact]
public void TestReadAsNumberFromStrings()
{
Dictionary<object, List<Type>> valuesToNonOverflowingTypesMapping = new Dictionary<object, List<Type>>
{
{ double.NaN.ToString("R", CultureInfo.InvariantCulture), new List<Type> { typeof(float), typeof(double) } },
{ double.NegativeInfinity.ToString("R", CultureInfo.InvariantCulture), new List<Type> { typeof(float), typeof(double) } },
{ double.PositiveInfinity.ToString("R", CultureInfo.InvariantCulture), new List<Type> { typeof(float), typeof(double) } },
{ double.MaxValue.ToString("R", CultureInfo.InvariantCulture), new List<Type> { typeof(double), typeof(float) } },
{ double.MinValue.ToString("R", CultureInfo.InvariantCulture), new List<Type> { typeof(double), typeof(float) } },
{ float.MaxValue.ToString("R", CultureInfo.InvariantCulture), new List<Type> { typeof(double), typeof(float) } },
{ float.MinValue.ToString("R", CultureInfo.InvariantCulture), new List<Type> { typeof(double), typeof(float) } },
{ Int64.MaxValue.ToString(), new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(ulong) } },
{ Int64.MinValue.ToString(), new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long) } },
{ Int32.MaxValue.ToString(), new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(ulong), typeof(uint) } },
{ Int32.MinValue.ToString(), new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int) } },
{ Int16.MaxValue.ToString(), new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(ulong), typeof(uint), typeof(ushort) } },
{ Int16.MinValue.ToString(), new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short) } },
{ SByte.MaxValue.ToString(), new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte), typeof(ulong), typeof(uint), typeof(ushort), typeof(byte) } },
{ SByte.MinValue.ToString(), new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte) } },
{ UInt64.MaxValue.ToString(), new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(ulong) } },
{ UInt32.MaxValue.ToString(), new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(ulong), typeof(uint) } },
{ UInt16.MaxValue.ToString(), new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(ulong), typeof(uint), typeof(ushort) } },
{ Byte.MaxValue.ToString(), new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(ulong), typeof(uint), typeof(ushort), typeof(byte) } },
{ Byte.MinValue.ToString(), new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte), typeof(ulong), typeof(uint), typeof(ushort), typeof(byte) } },
{ "1", new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte), typeof(ulong), typeof(uint), typeof(ushort), typeof(byte) } },
{ "+01", new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte), typeof(ulong), typeof(uint), typeof(ushort), typeof(byte) } },
{ "01.1e+01", new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte), typeof(ulong), typeof(uint), typeof(ushort), typeof(byte) } },
{ "1e1", new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte), typeof(ulong), typeof(uint), typeof(ushort), typeof(byte) } },
{ "1.0", new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte), typeof(ulong), typeof(uint), typeof(ushort), typeof(byte) } },
{ "01.0", new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte), typeof(ulong), typeof(uint), typeof(ushort), typeof(byte) } },
{ "-1", new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte) } },
{ "-1.0", new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte) } },
{ "-01.0", new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte) } },
{ "-01.0e+01", new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte) } },
{ "-01.0e-01", new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte), typeof(ulong), typeof(uint), typeof(ushort), typeof(byte) } },
{ "-.1", new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte), typeof(ulong), typeof(uint), typeof(ushort), typeof(byte) } },
{ "-0100.0e-1", new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte) } },
};
foreach (KeyValuePair<object, List<Type>> mapping in valuesToNonOverflowingTypesMapping)
{
ConvertValueToNumber<double>(mapping);
ConvertValueToNumber<float>(mapping);
ConvertValueToNumber<decimal>(mapping);
ConvertValueToNumber<long>(mapping);
ConvertValueToNumber<int>(mapping);
ConvertValueToNumber<short>(mapping);
ConvertValueToNumber<sbyte>(mapping);
ConvertValueToNumber<ulong>(mapping);
ConvertValueToNumber<uint>(mapping);
ConvertValueToNumber<ushort>(mapping);
ConvertValueToNumber<byte>(mapping);
}
Dictionary<object, List<Type>> valuesThatAreInvalidNumber = new Dictionary<object, List<Type>>
{
{ "1L", new List<Type> { } },
{ "0x1", new List<Type> { } },
{ "1e309", new List<Type> { } },
{ "", new List<Type> { } },
{ "-", new List<Type> { } },
{ "e10", new List<Type> { } },
};
foreach (KeyValuePair<object, List<Type>> mapping in valuesThatAreInvalidNumber)
{
ConvertValueToNumber<double, FormatException>(mapping);
ConvertValueToNumber<float, FormatException>(mapping);
ConvertValueToNumber<decimal, FormatException>(mapping);
ConvertValueToNumber<long, FormatException>(mapping);
ConvertValueToNumber<int, FormatException>(mapping);
ConvertValueToNumber<short, FormatException>(mapping);
ConvertValueToNumber<sbyte, FormatException>(mapping);
ConvertValueToNumber<ulong, FormatException>(mapping);
ConvertValueToNumber<uint, FormatException>(mapping);
ConvertValueToNumber<ushort, FormatException>(mapping);
ConvertValueToNumber<byte, FormatException>(mapping);
}
}
/// <summary>
/// Tests for the <see cref="System.Json.JsonValue.ReadAs{T}()"/> method where T is a number type and the value is created from a number.
/// This is essentially a number conversion test.
/// </summary>
[Fact]
public void TestReadAsNumberFromNumber()
{
Dictionary<object, List<Type>> valuesToNonOverflowingTypesMapping = new Dictionary<object, List<Type>>
{
{ double.NaN, new List<Type> { typeof(float), typeof(double) } },
{ double.NegativeInfinity, new List<Type> { typeof(float), typeof(double) } },
{ double.PositiveInfinity, new List<Type> { typeof(float), typeof(double) } },
{ float.NaN, new List<Type> { typeof(float), typeof(double) } },
{ float.NegativeInfinity, new List<Type> { typeof(float), typeof(double) } },
{ float.PositiveInfinity, new List<Type> { typeof(float), typeof(double) } },
{ double.MaxValue, new List<Type> { typeof(double), typeof(float) } },
{ double.MinValue, new List<Type> { typeof(double), typeof(float) } },
{ float.MaxValue, new List<Type> { typeof(double), typeof(float) } },
{ float.MinValue, new List<Type> { typeof(double), typeof(float) } },
{ Int64.MaxValue, new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(ulong) } },
{ Int64.MinValue, new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long) } },
{ Int32.MaxValue, new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(ulong), typeof(uint) } },
{ Int32.MinValue, new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int) } },
{ Int16.MaxValue, new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(ulong), typeof(uint), typeof(ushort) } },
{ Int16.MinValue, new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short) } },
{ SByte.MaxValue, new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte), typeof(ulong), typeof(uint), typeof(ushort), typeof(byte) } },
{ SByte.MinValue, new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte) } },
{ UInt64.MaxValue, new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(ulong) } },
{ UInt64.MinValue, new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte), typeof(ulong), typeof(uint), typeof(ushort), typeof(byte) } },
{ UInt32.MaxValue, new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(ulong), typeof(uint) } },
{ UInt32.MinValue, new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte), typeof(ulong), typeof(uint), typeof(ushort), typeof(byte) } },
{ UInt16.MaxValue, new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(ulong), typeof(uint), typeof(ushort) } },
{ UInt16.MinValue, new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte), typeof(ulong), typeof(uint), typeof(ushort), typeof(byte) } },
{ Byte.MaxValue, new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(ulong), typeof(uint), typeof(ushort), typeof(byte) } },
{ Byte.MinValue, new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte), typeof(ulong), typeof(uint), typeof(ushort), typeof(byte) } },
{ (double)1, new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte), typeof(ulong), typeof(uint), typeof(ushort), typeof(byte) } },
{ (float)1, new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte), typeof(ulong), typeof(uint), typeof(ushort), typeof(byte) } },
{ (decimal)1, new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte), typeof(ulong), typeof(uint), typeof(ushort), typeof(byte) } },
{ (long)1, new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte), typeof(ulong), typeof(uint), typeof(ushort), typeof(byte) } },
{ (int)1, new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte), typeof(ulong), typeof(uint), typeof(ushort), typeof(byte) } },
{ (short)1, new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte), typeof(ulong), typeof(uint), typeof(ushort), typeof(byte) } },
{ (sbyte)1, new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte), typeof(ulong), typeof(uint), typeof(ushort), typeof(byte) } },
{ (ulong)1, new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte), typeof(ulong), typeof(uint), typeof(ushort), typeof(byte) } },
{ (uint)1, new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte), typeof(ulong), typeof(uint), typeof(ushort), typeof(byte) } },
{ (ushort)1, new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte), typeof(ulong), typeof(uint), typeof(ushort), typeof(byte) } },
{ (byte)1, new List<Type> { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte), typeof(ulong), typeof(uint), typeof(ushort), typeof(byte) } },
};
foreach (KeyValuePair<object, List<Type>> mapping in valuesToNonOverflowingTypesMapping)
{
ConvertValueToNumber<double>(mapping);
ConvertValueToNumber<float>(mapping);
ConvertValueToNumber<decimal>(mapping);
ConvertValueToNumber<long>(mapping);
ConvertValueToNumber<int>(mapping);
ConvertValueToNumber<short>(mapping);
ConvertValueToNumber<sbyte>(mapping);
ConvertValueToNumber<ulong>(mapping);
ConvertValueToNumber<uint>(mapping);
ConvertValueToNumber<ushort>(mapping);
ConvertValueToNumber<byte>(mapping);
}
}
static void ConvertValueToNumber<T>(KeyValuePair<object, List<Type>> mapping)
{
ConvertValueToNumber<T, OverflowException>(mapping);
}
static void ConvertValueToNumber<T, TException>(KeyValuePair<object, List<Type>> mapping)
where TException : Exception
{
JsonValue jsonValue = CastToJsonValue(mapping.Key);
Log.Info("Converting value {0} of type {1} to type {2}.", mapping.Key, mapping.Key.GetType().Name, typeof(T).Name);
if (mapping.Value.Contains(typeof(T)))
{
Console.Write("Conversion should work... ");
T valueOfT;
Assert.True(jsonValue.TryReadAs<T>(out valueOfT));
if (mapping.Key.GetType() != typeof(string))
{
Console.Write("and original value casted to {0} should be the same as the retrieved value... ", typeof(T).Name);
T castValue = (T)Convert.ChangeType(mapping.Key, typeof(T), CultureInfo.InvariantCulture);
Assert.Equal<T>(castValue, valueOfT);
}
}
else
{
Console.Write("Conversion should fail... ");
T valueOfT;
Assert.False(jsonValue.TryReadAs<T>(out valueOfT), String.Format("It was possible to read the value as {0}", valueOfT));
ExpectException<TException>(delegate
{
jsonValue.ReadAs<T>();
});
}
Log.Info("Success!");
}
static JsonValue CastToJsonValue(object o)
{
switch (Type.GetTypeCode(o.GetType()))
{
case TypeCode.Boolean:
return (JsonValue)(bool)o;
case TypeCode.Byte:
return (JsonValue)(byte)o;
case TypeCode.Char:
return (JsonValue)(char)o;
case TypeCode.DateTime:
return (JsonValue)(DateTime)o;
case TypeCode.Decimal:
return (JsonValue)(decimal)o;
case TypeCode.Double:
return (JsonValue)(double)o;
case TypeCode.Int16:
return (JsonValue)(short)o;
case TypeCode.Int32:
return (JsonValue)(int)o;
case TypeCode.Int64:
return (JsonValue)(long)o;
case TypeCode.SByte:
return (JsonValue)(sbyte)o;
case TypeCode.Single:
return (JsonValue)(float)o;
case TypeCode.String:
return (JsonValue)(string)o;
case TypeCode.UInt16:
return (JsonValue)(ushort)o;
case TypeCode.UInt32:
return (JsonValue)(uint)o;
case TypeCode.UInt64:
return (JsonValue)(ulong)o;
default:
if (o.GetType() == typeof(DateTimeOffset))
{
return (JsonValue)(DateTimeOffset)o;
}
if (o.GetType() == typeof(Guid))
{
return (JsonValue)(Guid)o;
}
if (o.GetType() == typeof(Uri))
{
return (JsonValue)(Uri)o;
}
break;
}
return (JsonObject)o;
}
static void ExpectException<T>(Action action) where T : Exception
{
JsonValueTests.ExpectException<T>(action);
}
static string GetExpectedRepresentation(object obj)
{
if (obj is double)
{
double dbl = (double)obj;
if (Double.IsPositiveInfinity(dbl))
{
return "Infinity";
}
else if (Double.IsNegativeInfinity(dbl))
{
return "-Infinity";
}
}
else if (obj is float)
{
float flt = (float)obj;
if (Single.IsPositiveInfinity(flt))
{
return "Infinity";
}
else if (Single.IsNegativeInfinity(flt))
{
return "-Infinity";
}
}
else if (obj is DateTime)
{
DateTime dt = (DateTime)obj;
return "\"" + dt.ToString(DateTimeFormat, CultureInfo.InvariantCulture) + "\"";
}
using (MemoryStream ms = new MemoryStream())
{
DataContractJsonSerializer dcjs = new DataContractJsonSerializer(obj.GetType());
dcjs.WriteObject(ms, obj);
return Encoding.UTF8.GetString(ms.GetBuffer(), 0, (int)ms.Position);
}
}
void ValidateJson(JsonPrimitive jsonPrim, string expectedJson, JsonType expectedJsonType)
{
Assert.Equal(expectedJson, jsonPrim.ToString());
Assert.Equal(expectedJsonType, jsonPrim.JsonType);
}
void TestReadAsRoundtrip<T>(JsonPrimitive jsonPrim, T myOriginalObjectOfT)
{
T myReadObjectOfT = jsonPrim.ReadAs<T>();
T myTryReadObjectOfT;
Assert.True(jsonPrim.TryReadAs<T>(out myTryReadObjectOfT));
Assert.Equal(myOriginalObjectOfT, myReadObjectOfT);
Assert.Equal(myOriginalObjectOfT, myTryReadObjectOfT);
string stringValue;
Assert.True(jsonPrim.TryReadAs<string>(out stringValue));
if (typeof(T) == typeof(bool))
{
// bool returns a lowercase version. make sure we get something usable by doing another roundtrip of the value in .NET
Assert.Equal(String.Format(CultureInfo.InvariantCulture, "{0}", myOriginalObjectOfT), bool.Parse(stringValue).ToString(CultureInfo.InvariantCulture));
}
else if (typeof(T) == typeof(float) || typeof(T) == typeof(double))
{
Assert.Equal(String.Format(CultureInfo.InvariantCulture, "{0:R}", myOriginalObjectOfT), stringValue);
}
else if (typeof(T) == typeof(DateTime))
{
Assert.Equal(String.Format(CultureInfo.InvariantCulture, "{0:" + DateTimeFormat + "}", myOriginalObjectOfT), stringValue);
}
else
{
Assert.Equal(String.Format(CultureInfo.InvariantCulture, "{0}", myOriginalObjectOfT), stringValue);
}
}
void TestReadAsFromStringRoundtrip<T>(T value)
{
TestReadAsFromStringRoundtrip<T>(value, String.Format(CultureInfo.InvariantCulture, "{0}", value));
}
void TestReadAsFromStringRoundtrip<T>(T value, string valueString)
{
T tempOfT;
JsonPrimitive jsonPrim = new JsonPrimitive(valueString);
Assert.True(jsonPrim.TryReadAs<T>(out tempOfT));
Assert.Equal<T>(value, tempOfT);
}
}
}