// 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 { /// /// JsonPrimitive unit tests /// public class JsonPrimitiveTests { const string DateTimeFormat = "yyyy-MM-ddTHH:mm:ss.fffK"; /// /// Validates round-trip of values created from values. /// [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(new JsonPrimitive(values[i]), values[i]); } } /// /// Validates round-trip of values created from values. /// [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(new JsonPrimitive(values[i]), values[i]); } } /// /// Validates round-trip of values created from values. /// [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(new JsonPrimitive(values[i]), values[i]); } } /// /// Validates round-trip of values created from values. /// [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(new JsonPrimitive(values[i]), values[i]); } } /// /// Validates round-trip of values created from values. /// [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(new JsonPrimitive(values[i]), values[i]); } } /// /// Validates round-trip of values created from values. /// [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(new JsonPrimitive(values[i]), values[i]); } } /// /// Validates round-trip of values created from values. /// [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(new JsonPrimitive(values[i]), values[i]); } } /// /// Validates round-trip of values created from values. /// [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(new JsonPrimitive(values[i]), values[i]); } } /// /// Validates round-trip of values created from values. /// [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(new JsonPrimitive(values[i]), values[i]); } } /// /// Validates round-trip of values created from values. /// [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(new JsonPrimitive(values[i]), values[i]); } } /// /// Validates round-trip of values created from values. /// [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(new JsonPrimitive(values[i]), values[i]); } } /// /// Validates round-trip of values created from values. /// [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(new JsonPrimitive(values[i]), values[i]); } } /// /// Validates round-trip of values created from values. /// [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(new JsonPrimitive(values[i]), values[i]); } } /// /// Validates round-trip of values created from values. /// [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(new JsonPrimitive(values[i]), values[i]); } } /// /// Validates round-trip of values created from values. /// [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(new JsonPrimitive(values[i]), values[i]); } } /// /// Validates round-trip of values created from values. /// [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(new JsonPrimitive(values[i]), values[i]); } } /// /// Validates round-trip of values created from values. /// [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(new JsonPrimitive(values[i]), values[i]); } } /// /// Validates round-trip of values created from different types of values. /// [Fact] public void JsonPrimitiveFromObject() { List> values = new List> { new KeyValuePair(true, JsonType.Boolean), new KeyValuePair((short)1, JsonType.Number), new KeyValuePair(234, JsonType.Number), new KeyValuePair(3435434233443L, JsonType.Number), new KeyValuePair(UInt64.MaxValue, JsonType.Number), new KeyValuePair(UInt32.MaxValue, JsonType.Number), new KeyValuePair(UInt16.MaxValue, JsonType.Number), new KeyValuePair(Byte.MaxValue, JsonType.Number), new KeyValuePair(SByte.MinValue, JsonType.Number), new KeyValuePair(double.MaxValue, JsonType.Number), new KeyValuePair(float.Epsilon, JsonType.Number), new KeyValuePair(decimal.MinusOne, JsonType.Number), new KeyValuePair("hello", JsonType.String), new KeyValuePair(Guid.NewGuid(), JsonType.String), new KeyValuePair(DateTime.UtcNow, JsonType.String), new KeyValuePair(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); } } /// /// Negative tests for constructors with null values. /// [Fact] public void NullChecks() { ExpectException(() => new JsonPrimitive((string)null)); ExpectException(() => new JsonPrimitive((Uri)null)); } /// /// Tests for casting string values into non-string values. /// [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(delegate { var d = (double)(new JsonPrimitive("INF")); }); ExpectException(delegate { var d = (double)(new JsonPrimitive("-INF")); }); ExpectException(delegate { var d = (double)(new JsonPrimitive("infinity")); }); ExpectException(delegate { var d = (double)(new JsonPrimitive("INFINITY")); }); ExpectException(delegate { var d = (double)(new JsonPrimitive("nan")); }); ExpectException(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(delegate { var f = (float)(new JsonPrimitive("INF")); }); ExpectException(delegate { var f = (float)(new JsonPrimitive("-INF")); }); ExpectException(delegate { var f = (float)(new JsonPrimitive("infinity")); }); ExpectException(delegate { var f = (float)(new JsonPrimitive("INFINITY")); }); ExpectException(delegate { var f = (float)(new JsonPrimitive("nan")); }); ExpectException(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)))); } /// /// Tests for casting created from special floating point values (infinity, NaN). /// [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))); } /// /// Tests for the many formats which can be cast to a . /// [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()); Assert.Equal(dateLocal.Date, new JsonPrimitive(localDate).ReadAs()); DateTime timeOnly = new JsonPrimitive(localTime).ReadAs(); 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()); } 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()); } } } /// /// Tests for date parsing form the RFC2822 format. /// [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(); 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(""); } } /// /// Tests for the function from string values. /// [Fact] public void ReadAsFromStringTests() { int seed = MethodBase.GetCurrentMethod().Name.GetHashCode(); Random rndGen = new Random(seed); TestReadAsFromStringRoundtrip(false, "false"); TestReadAsFromStringRoundtrip(false, "False"); TestReadAsFromStringRoundtrip(true, "true"); TestReadAsFromStringRoundtrip(true, "True"); TestReadAsFromStringRoundtrip(PrimitiveCreator.CreateInstanceOfByte(rndGen)); TestReadAsFromStringRoundtrip(PrimitiveCreator.CreateInstanceOfChar(rndGen)); TestReadAsFromStringRoundtrip(PrimitiveCreator.CreateInstanceOfDecimal(rndGen)); TestReadAsFromStringRoundtrip(PrimitiveCreator.CreateInstanceOfInt32(rndGen)); TestReadAsFromStringRoundtrip(PrimitiveCreator.CreateInstanceOfInt64(rndGen)); TestReadAsFromStringRoundtrip(PrimitiveCreator.CreateInstanceOfSByte(rndGen)); TestReadAsFromStringRoundtrip(PrimitiveCreator.CreateInstanceOfInt16(rndGen)); TestReadAsFromStringRoundtrip(PrimitiveCreator.CreateInstanceOfUInt16(rndGen)); TestReadAsFromStringRoundtrip(PrimitiveCreator.CreateInstanceOfUInt32(rndGen)); TestReadAsFromStringRoundtrip(PrimitiveCreator.CreateInstanceOfUInt64(rndGen)); double dbl = rndGen.NextDouble() * rndGen.Next(); TestReadAsFromStringRoundtrip(dbl, dbl.ToString("R", CultureInfo.InvariantCulture)); TestReadAsFromStringRoundtrip(double.PositiveInfinity, "Infinity"); TestReadAsFromStringRoundtrip(double.NegativeInfinity, "-Infinity"); TestReadAsFromStringRoundtrip(double.NaN, "NaN"); float flt = (float)(rndGen.NextDouble() * rndGen.Next()); TestReadAsFromStringRoundtrip(flt, flt.ToString("R", CultureInfo.InvariantCulture)); TestReadAsFromStringRoundtrip(float.PositiveInfinity, "Infinity"); TestReadAsFromStringRoundtrip(float.NegativeInfinity, "-Infinity"); TestReadAsFromStringRoundtrip(float.NaN, "NaN"); Guid guid = PrimitiveCreator.CreateInstanceOfGuid(rndGen); TestReadAsFromStringRoundtrip(guid, guid.ToString("N", CultureInfo.InvariantCulture)); TestReadAsFromStringRoundtrip(guid, guid.ToString("D", CultureInfo.InvariantCulture)); TestReadAsFromStringRoundtrip(guid, guid.ToString("B", CultureInfo.InvariantCulture)); TestReadAsFromStringRoundtrip(guid, guid.ToString("P", CultureInfo.InvariantCulture)); TestReadAsFromStringRoundtrip(guid, guid.ToString("X", CultureInfo.InvariantCulture)); TestReadAsFromStringRoundtrip(guid, guid.ToString("X", CultureInfo.InvariantCulture).Replace("0x", "0X")); TestReadAsFromStringRoundtrip(guid, guid.ToString("X", CultureInfo.InvariantCulture).Replace("{", " { ")); TestReadAsFromStringRoundtrip(guid, guid.ToString("X", CultureInfo.InvariantCulture).Replace("}", " } ")); TestReadAsFromStringRoundtrip(guid, guid.ToString("X", CultureInfo.InvariantCulture).Replace(",", " , ")); TestReadAsFromStringRoundtrip(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); TestReadAsFromStringRoundtrip(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, dateTimeOffset.ToUniversalTime().ToString(@"ddd, d MMM yyyy HH:mm:ss \U\T\C")); TestReadAsFromStringRoundtrip(dateTime, dateTimeOffset.ToUniversalTime().ToString(@"ddd, d MMM yyyy HH:mm:ss \G\M\T")); TestReadAsFromStringRoundtrip(dateTime.ToLocalTime(), dateTimeOffset.ToString(@"ddd, d MMM yyyy HH:mm:ss zzz")); TestReadAsFromStringRoundtrip(dateTime, dateTime.ToString("yyyy-MM-ddTHH:mm:ssK")); TestReadAsFromStringRoundtrip(dateTime.ToLocalTime(), dateTimeOffset.ToString(@"ddd, d MMM yyyy HH:mm:ss zzz")); TestReadAsFromStringRoundtrip(dateTime.ToLocalTime(), dateTimeOffset.ToString("yyyy-MM-ddTHH:mm:sszzz")); TestReadAsFromStringRoundtrip(dateTimeOffset.UtcDateTime, dateTimeOffset.ToUniversalTime().ToString(@"ddd, d MMM yyyy HH:mm:ss \U\T\C")); TestReadAsFromStringRoundtrip(dateTimeOffset.UtcDateTime, dateTimeOffset.ToUniversalTime().ToString(@"ddd, d MMM yyyy HH:mm:ss \G\M\T")); TestReadAsFromStringRoundtrip(dateTimeOffset, dateTimeOffset.ToUniversalTime().ToString(@"ddd, d MMM yyyy HH:mm:ss zzz")); TestReadAsFromStringRoundtrip(dateTimeOffset, dateTime.ToString("yyyy-MM-ddTHH:mm:ssK")); TestReadAsFromStringRoundtrip(dateTimeOffset, dateTimeOffset.ToString("yyyy-MM-ddTHH:mm:sszzz")); TestReadAsFromStringRoundtrip(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, AspNetFormattedDateTime); TestReadAsFromStringRoundtrip(dateTime.ToLocalTime(), AspNetFormattedDateTimeWithValidTZ); TestReadAsFromStringRoundtrip(dateTimeOffset, AspNetFormattedDateTime); TestReadAsFromStringRoundtrip(dateTimeOffset, AspNetFormattedDateTimeWithValidTZ); ExpectException(delegate { new JsonPrimitive(AspNetFormattedDateTimeInvalid1).ReadAs(); }); ExpectException(delegate { new JsonPrimitive(AspNetFormattedDateTimeInvalid2).ReadAs(); }); ExpectException(delegate { new JsonPrimitive(AspNetFormattedDateTimeInvalid1).ReadAs(); }); ExpectException(delegate { new JsonPrimitive(AspNetFormattedDateTimeInvalid2).ReadAs(); }); ExpectException(delegate { new JsonPrimitive("INF").ReadAs(); }); ExpectException(delegate { new JsonPrimitive("-INF").ReadAs(); }); ExpectException(delegate { new JsonPrimitive("infinity").ReadAs(); }); ExpectException(delegate { new JsonPrimitive("INFINITY").ReadAs(); }); ExpectException(delegate { new JsonPrimitive("nan").ReadAs(); }); ExpectException(delegate { new JsonPrimitive("Nan").ReadAs(); }); ExpectException(delegate { new JsonPrimitive("INF").ReadAs(); }); ExpectException(delegate { new JsonPrimitive("-INF").ReadAs(); }); ExpectException(delegate { new JsonPrimitive("infinity").ReadAs(); }); ExpectException(delegate { new JsonPrimitive("INFINITY").ReadAs(); }); ExpectException(delegate { new JsonPrimitive("nan").ReadAs(); }); ExpectException(delegate { new JsonPrimitive("Nan").ReadAs(); }); } /// /// Tests for the JsonValue.ReadAs<string> method from number values. /// [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()); uint uintValue = PrimitiveCreator.CreateInstanceOfUInt32(rndGen); jv = uintValue; Assert.Equal(uintValue.ToString(CultureInfo.InvariantCulture), jv.ToString()); Assert.Equal(uintValue.ToString(CultureInfo.InvariantCulture), jv.ReadAs()); long longValue = PrimitiveCreator.CreateInstanceOfInt64(rndGen); jv = longValue; Assert.Equal(longValue.ToString(CultureInfo.InvariantCulture), jv.ToString()); Assert.Equal(longValue.ToString(CultureInfo.InvariantCulture), jv.ReadAs()); ulong ulongValue = PrimitiveCreator.CreateInstanceOfUInt64(rndGen); jv = ulongValue; Assert.Equal(ulongValue.ToString(CultureInfo.InvariantCulture), jv.ToString()); Assert.Equal(ulongValue.ToString(CultureInfo.InvariantCulture), jv.ReadAs()); short shortValue = PrimitiveCreator.CreateInstanceOfInt16(rndGen); jv = shortValue; Assert.Equal(shortValue.ToString(CultureInfo.InvariantCulture), jv.ToString()); Assert.Equal(shortValue.ToString(CultureInfo.InvariantCulture), jv.ReadAs()); ushort ushortValue = PrimitiveCreator.CreateInstanceOfUInt16(rndGen); jv = ushortValue; Assert.Equal(ushortValue.ToString(CultureInfo.InvariantCulture), jv.ToString()); Assert.Equal(ushortValue.ToString(CultureInfo.InvariantCulture), jv.ReadAs()); byte byteValue = PrimitiveCreator.CreateInstanceOfByte(rndGen); jv = byteValue; Assert.Equal(byteValue.ToString(CultureInfo.InvariantCulture), jv.ToString()); Assert.Equal(byteValue.ToString(CultureInfo.InvariantCulture), jv.ReadAs()); sbyte sbyteValue = PrimitiveCreator.CreateInstanceOfSByte(rndGen); jv = sbyteValue; Assert.Equal(sbyteValue.ToString(CultureInfo.InvariantCulture), jv.ToString()); Assert.Equal(sbyteValue.ToString(CultureInfo.InvariantCulture), jv.ReadAs()); decimal decValue = PrimitiveCreator.CreateInstanceOfDecimal(rndGen); jv = decValue; Assert.Equal(decValue.ToString(CultureInfo.InvariantCulture), jv.ToString()); Assert.Equal(decValue.ToString(CultureInfo.InvariantCulture), jv.ReadAs()); 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()); 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()); } /// /// Tests for the JsonValue.ReadAs<string> method from date values. /// [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()); } /// /// Tests for the JsonValue.ReadAs<string> method from char values. /// [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 actual2 = (string)jv; Assert.Equal(expected, actual1); Assert.Equal(expected, actual2); } } /// /// Tests for the method where T is a number type and the value is created from a string. /// [Fact] public void TestReadAsNumberFromStrings() { Dictionary> valuesToNonOverflowingTypesMapping = new Dictionary> { { double.NaN.ToString("R", CultureInfo.InvariantCulture), new List { typeof(float), typeof(double) } }, { double.NegativeInfinity.ToString("R", CultureInfo.InvariantCulture), new List { typeof(float), typeof(double) } }, { double.PositiveInfinity.ToString("R", CultureInfo.InvariantCulture), new List { typeof(float), typeof(double) } }, { double.MaxValue.ToString("R", CultureInfo.InvariantCulture), new List { typeof(double), typeof(float) } }, { double.MinValue.ToString("R", CultureInfo.InvariantCulture), new List { typeof(double), typeof(float) } }, { float.MaxValue.ToString("R", CultureInfo.InvariantCulture), new List { typeof(double), typeof(float) } }, { float.MinValue.ToString("R", CultureInfo.InvariantCulture), new List { typeof(double), typeof(float) } }, { Int64.MaxValue.ToString(), new List { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(ulong) } }, { Int64.MinValue.ToString(), new List { typeof(double), typeof(float), typeof(decimal), typeof(long) } }, { Int32.MaxValue.ToString(), new List { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(ulong), typeof(uint) } }, { Int32.MinValue.ToString(), new List { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int) } }, { Int16.MaxValue.ToString(), new List { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(ulong), typeof(uint), typeof(ushort) } }, { Int16.MinValue.ToString(), new List { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short) } }, { SByte.MaxValue.ToString(), new List { 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 { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte) } }, { UInt64.MaxValue.ToString(), new List { typeof(double), typeof(float), typeof(decimal), typeof(ulong) } }, { UInt32.MaxValue.ToString(), new List { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(ulong), typeof(uint) } }, { UInt16.MaxValue.ToString(), new List { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(ulong), typeof(uint), typeof(ushort) } }, { Byte.MaxValue.ToString(), new List { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte) } }, { "-1.0", new List { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte) } }, { "-01.0", new List { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte) } }, { "-01.0e+01", new List { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte) } }, { "-01.0e-01", new List { 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 { 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 { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte) } }, }; foreach (KeyValuePair> mapping in valuesToNonOverflowingTypesMapping) { ConvertValueToNumber(mapping); ConvertValueToNumber(mapping); ConvertValueToNumber(mapping); ConvertValueToNumber(mapping); ConvertValueToNumber(mapping); ConvertValueToNumber(mapping); ConvertValueToNumber(mapping); ConvertValueToNumber(mapping); ConvertValueToNumber(mapping); ConvertValueToNumber(mapping); ConvertValueToNumber(mapping); } Dictionary> valuesThatAreInvalidNumber = new Dictionary> { { "1L", new List { } }, { "0x1", new List { } }, { "1e309", new List { } }, { "", new List { } }, { "-", new List { } }, { "e10", new List { } }, }; foreach (KeyValuePair> mapping in valuesThatAreInvalidNumber) { ConvertValueToNumber(mapping); ConvertValueToNumber(mapping); ConvertValueToNumber(mapping); ConvertValueToNumber(mapping); ConvertValueToNumber(mapping); ConvertValueToNumber(mapping); ConvertValueToNumber(mapping); ConvertValueToNumber(mapping); ConvertValueToNumber(mapping); ConvertValueToNumber(mapping); ConvertValueToNumber(mapping); } } /// /// Tests for the method where T is a number type and the value is created from a number. /// This is essentially a number conversion test. /// [Fact] public void TestReadAsNumberFromNumber() { Dictionary> valuesToNonOverflowingTypesMapping = new Dictionary> { { double.NaN, new List { typeof(float), typeof(double) } }, { double.NegativeInfinity, new List { typeof(float), typeof(double) } }, { double.PositiveInfinity, new List { typeof(float), typeof(double) } }, { float.NaN, new List { typeof(float), typeof(double) } }, { float.NegativeInfinity, new List { typeof(float), typeof(double) } }, { float.PositiveInfinity, new List { typeof(float), typeof(double) } }, { double.MaxValue, new List { typeof(double), typeof(float) } }, { double.MinValue, new List { typeof(double), typeof(float) } }, { float.MaxValue, new List { typeof(double), typeof(float) } }, { float.MinValue, new List { typeof(double), typeof(float) } }, { Int64.MaxValue, new List { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(ulong) } }, { Int64.MinValue, new List { typeof(double), typeof(float), typeof(decimal), typeof(long) } }, { Int32.MaxValue, new List { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(ulong), typeof(uint) } }, { Int32.MinValue, new List { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int) } }, { Int16.MaxValue, new List { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(ulong), typeof(uint), typeof(ushort) } }, { Int16.MinValue, new List { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short) } }, { SByte.MaxValue, new List { 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 { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte) } }, { UInt64.MaxValue, new List { typeof(double), typeof(float), typeof(decimal), typeof(ulong) } }, { UInt64.MinValue, new List { 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 { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(ulong), typeof(uint) } }, { UInt32.MinValue, new List { 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 { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(ulong), typeof(uint), typeof(ushort) } }, { UInt16.MinValue, new List { 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 { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(ulong), typeof(uint), typeof(ushort), typeof(byte) } }, { Byte.MinValue, new List { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(int), typeof(short), typeof(sbyte), typeof(ulong), typeof(uint), typeof(ushort), typeof(byte) } }, }; foreach (KeyValuePair> mapping in valuesToNonOverflowingTypesMapping) { ConvertValueToNumber(mapping); ConvertValueToNumber(mapping); ConvertValueToNumber(mapping); ConvertValueToNumber(mapping); ConvertValueToNumber(mapping); ConvertValueToNumber(mapping); ConvertValueToNumber(mapping); ConvertValueToNumber(mapping); ConvertValueToNumber(mapping); ConvertValueToNumber(mapping); ConvertValueToNumber(mapping); } } static void ConvertValueToNumber(KeyValuePair> mapping) { ConvertValueToNumber(mapping); } static void ConvertValueToNumber(KeyValuePair> 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(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(castValue, valueOfT); } } else { Console.Write("Conversion should fail... "); T valueOfT; Assert.False(jsonValue.TryReadAs(out valueOfT), String.Format("It was possible to read the value as {0}", valueOfT)); ExpectException(delegate { jsonValue.ReadAs(); }); } 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(Action action) where T : Exception { JsonValueTests.ExpectException(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(JsonPrimitive jsonPrim, T myOriginalObjectOfT) { T myReadObjectOfT = jsonPrim.ReadAs(); T myTryReadObjectOfT; Assert.True(jsonPrim.TryReadAs(out myTryReadObjectOfT)); Assert.Equal(myOriginalObjectOfT, myReadObjectOfT); Assert.Equal(myOriginalObjectOfT, myTryReadObjectOfT); string stringValue; Assert.True(jsonPrim.TryReadAs(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 value) { TestReadAsFromStringRoundtrip(value, String.Format(CultureInfo.InvariantCulture, "{0}", value)); } void TestReadAsFromStringRoundtrip(T value, string valueString) { T tempOfT; JsonPrimitive jsonPrim = new JsonPrimitive(valueString); Assert.True(jsonPrim.TryReadAs(out tempOfT)); Assert.Equal(value, tempOfT); } } }