From: buyaa-n Date: Tue, 11 Jun 2019 00:51:30 +0000 (-0700) Subject: Some tests imported from Newtonsoft Json (dotnet/corefx#38153) X-Git-Tag: submit/tizen/20210909.063632~11031^2~1339 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=89d76ea2e2a8ec4ba2c0bcc68482fbe5d895ebda;p=platform%2Fupstream%2Fdotnet%2Fruntime.git Some tests imported from Newtonsoft Json (dotnet/corefx#38153) Tests imported from Newtonsoft Json Commit migrated from https://github.com/dotnet/corefx/commit/ff6ce7de1c206a5d552d98395b22f47a8eba368e --- diff --git a/src/libraries/System.Text.Json/tests/NewtonsoftTests/CamelCaseTests.cs b/src/libraries/System.Text.Json/tests/NewtonsoftTests/CamelCaseTests.cs new file mode 100644 index 00000000000..ab975a3877c --- /dev/null +++ b/src/libraries/System.Text.Json/tests/NewtonsoftTests/CamelCaseTests.cs @@ -0,0 +1,116 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// Copyright (c) 2007 James Newton-King +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +using System.Text.Json.Serialization; +using Xunit; + +namespace System.Text.Json.Tests +{ + internal class Person + { + public string Name { get; set; } + + public DateTime BirthDate { get; set; } + + public DateTime LastModified { get; set; } + + [JsonIgnore] + public string Department { get; set; } + } + + internal class Product + { + public string Name { get; set; } + public DateTime ExpiryDate { get; set;} + public decimal Price { get; set; } + public string[] Sizes { get; set; } + } + + public class CamelCaseTests + { + private static readonly JsonSerializerOptions s_camelCaseAndIndentedOption = new JsonSerializerOptions + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + WriteIndented = true, + }; + + [Fact] + public void JsonSerializerCamelCaseSettings() + { + Person person = new Person(); + person.BirthDate = new DateTime(2000, 11, 20, 23, 55, 44, DateTimeKind.Utc); + person.LastModified = new DateTime(2000, 11, 20, 23, 55, 44, DateTimeKind.Utc); + person.Name = "Name!"; + + string json = JsonSerializer.ToString(person, s_camelCaseAndIndentedOption); + + Assert.Equal(@"{ + ""name"": ""Name!"", + ""birthDate"": ""2000-11-20T23:55:44Z"", + ""lastModified"": ""2000-11-20T23:55:44Z"" +}", json); + + Person deserializedPerson = JsonSerializer.Parse(json, s_camelCaseAndIndentedOption); + + Assert.Equal(person.BirthDate, deserializedPerson.BirthDate); + Assert.Equal(person.LastModified, deserializedPerson.LastModified); + Assert.Equal(person.Name, deserializedPerson.Name); + + json = JsonSerializer.ToString(person, new JsonSerializerOptions { WriteIndented = true }); + Assert.Equal(@"{ + ""Name"": ""Name!"", + ""BirthDate"": ""2000-11-20T23:55:44Z"", + ""LastModified"": ""2000-11-20T23:55:44Z"" +}", json); + } + + [Fact] + public void BlogPostExample() + { + Product product = new Product + { + ExpiryDate = new DateTime(2010, 12, 20, 18, 1, 0, DateTimeKind.Utc), + Name = "Widget", + Price = 9.99m, + Sizes = new[] { "Small", "Medium", "Large" } + }; + + string json = JsonSerializer.ToString(product, s_camelCaseAndIndentedOption); + + Assert.Equal(@"{ + ""name"": ""Widget"", + ""expiryDate"": ""2010-12-20T18:01:00Z"", + ""price"": 9.99, + ""sizes"": [ + ""Small"", + ""Medium"", + ""Large"" + ] +}", json); + } + } +} diff --git a/src/libraries/System.Text.Json/tests/NewtonsoftTests/CustomObjectConverterTests.cs b/src/libraries/System.Text.Json/tests/NewtonsoftTests/CustomObjectConverterTests.cs new file mode 100644 index 00000000000..3d2dfb139d2 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/NewtonsoftTests/CustomObjectConverterTests.cs @@ -0,0 +1,213 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// Copyright (c) 2007 James Newton-King +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +using System.Collections.Generic; +using Xunit; +using System.Text.Json.Serialization; + +namespace System.Text.Json.Tests +{ + public class CustomObjectConverterTests + { + [Fact] + public void SerializeAndConvertNullValue() + { + NullInterfaceTestClass initial = new NullInterfaceTestClass + { + Company = "Company!", + DecimalRange = new Range { First = 0, Last = 1 }, + Id = new Guid(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11), + IntRange = new Range { First = int.MinValue, Last = int.MaxValue }, + Year = 2010, + NullDecimalRange = null + }; + + string json = JsonSerializer.ToString(initial, new JsonSerializerOptions { WriteIndented = true }); + + Assert.Equal(@"{ + ""Id"": ""00000001-0002-0003-0405-060708090a0b"", + ""Year"": 2010, + ""Company"": ""Company!"", + ""DecimalRange"": { + ""First"": 0, + ""Last"": 1 + }, + ""IntRange"": { + ""First"": -2147483648, + ""Last"": 2147483647 + }, + ""NullDecimalRange"": null +}", json); + } + + [Fact] + public void DeserializeAndConvertNullValue() + { + string json = @"{ + ""Id"": ""00000001-0002-0003-0405-060708090a0b"", + ""Year"": 2010, + ""Company"": ""Company!"", + ""DecimalRange"": { + ""First"": 0, + ""Last"": 1 + }, + ""IntRange"": { + ""First"": -2147483648, + ""Last"": 2147483647 + }, + ""NullDecimalRange"": null +}"; + + JsonSerializer.ToString(json, new JsonSerializerOptions { WriteIndented = true }); + + NullInterfaceTestClass deserialized = JsonSerializer.Parse(json); + + Assert.Equal("Company!", deserialized.Company); + Assert.Equal(new Guid(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11), deserialized.Id); + Assert.Equal(0, deserialized.DecimalRange.First); + Assert.Equal(1, deserialized.DecimalRange.Last); + Assert.Equal(int.MinValue, deserialized.IntRange.First); + Assert.Equal(int.MaxValue, deserialized.IntRange.Last); + Assert.Equal(null, deserialized.NullDecimalRange); + Assert.Equal(2010, deserialized.Year); + } + + [Fact] + public void DeserializeByteArrayFromJsonArray() + { + string json = @"{ + ""ByteArray"": ""AAECAw=="", + ""NullByteArray"": null +}"; + + ByteArrayClass c = JsonSerializer.Parse(json); + Assert.NotNull(c.ByteArray); + Assert.Equal(4, c.ByteArray.Length); + Assert.Equal(new byte[] { 0, 1, 2, 3 }, c.ByteArray); + } + + [Fact] + public void SerializeByteArrayClass() + { + ByteArrayClass byteArrayClass = new ByteArrayClass(); + byteArrayClass.ByteArray = s_testData; + byteArrayClass.NullByteArray = null; + + string json = JsonSerializer.ToString(byteArrayClass, new JsonSerializerOptions { WriteIndented = true }); + + Assert.Equal(@"{ + ""ByteArray"": ""VGhpcyBpcyBzb21lIHRlc3QgZGF0YSEhIQ=="", + ""NullByteArray"": null +}", json); + } + + [Fact] + public void DeserializeByteArrayClass() + { + string json = @"{ + ""ByteArray"": ""VGhpcyBpcyBzb21lIHRlc3QgZGF0YSEhIQ=="", + ""NullByteArray"": null +}"; + + ByteArrayClass byteArrayClass = JsonSerializer.Parse(json); + + Assert.Equal(s_testData, byteArrayClass.ByteArray); + Assert.Equal(null, byteArrayClass.NullByteArray); + } + + private static readonly byte[] s_testData = Encoding.UTF8.GetBytes("This is some test data!!!"); + + [Fact] + public void AssertShouldSerializeTest() + { + MyClass myClass = new MyClass + { + Value = "Foo", + Thing = new MyThing { Number = 456, } + }; + string json = JsonSerializer.ToString(myClass); + + const string expected = @"{""Value"":""Foo"",""Thing"":{""Number"":456}}"; + Assert.Equal(expected, json); + } + + [Fact] + public void AssertDoesNotDeserializeInterface() + { + const string json = @"{ +""Value"": ""A value"", +""Thing"": { +""Number"": 123 +} +}"; + NotSupportedException e = Assert.Throws(() => + { + JsonSerializer.Parse>(json); + }); + Assert.Equal("Deserialization of interface types is not supported. Type 'System.Text.Json.Tests.IThing'", e.Message); + } + } + + internal class Range + { + public T First { get; set; } + public T Last { get; set; } + } + + internal class NullInterfaceTestClass + { + public virtual Guid Id { get; set; } + public virtual int Year { get; set; } + public virtual string Company { get; set; } + public virtual Range DecimalRange { get; set; } + public virtual Range IntRange { get; set; } + public virtual Range NullDecimalRange { get; set; } + } + + internal class MyClass + { + public string Value { get; set; } + + public IThing Thing { get; set; } + } + + internal interface IThing + { + int Number { get; set; } + } + + internal class MyThing : IThing + { + public int Number { get; set; } + } + + internal class ByteArrayClass + { + public byte[] ByteArray { get; set; } + public byte[] NullByteArray { get; set; } + } +} diff --git a/src/libraries/System.Text.Json/tests/NewtonsoftTests/DateTimeConverterTests.cs b/src/libraries/System.Text.Json/tests/NewtonsoftTests/DateTimeConverterTests.cs new file mode 100644 index 00000000000..6f813a91237 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/NewtonsoftTests/DateTimeConverterTests.cs @@ -0,0 +1,172 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// Copyright (c) 2007 James Newton-King +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +using System.Globalization; +using Xunit; +using System.Text.Json.Serialization; + +namespace System.Text.Json.Tests +{ + public class DateTimeConverterTests + { + internal static string GetUtcOffsetText(DateTime d) + { + TimeSpan utcOffset = TimeZoneInfo.Local.GetUtcOffset(d); + + return utcOffset.Hours.ToString("+00;-00", CultureInfo.InvariantCulture) + ":" + utcOffset.Minutes.ToString("00;00", CultureInfo.InvariantCulture); + } + + [Fact] + public void SerializeDateTime() + { + DateTime d = new DateTime(2000, 12, 15, 22, 11, 3, 55, DateTimeKind.Utc); + string result; + + result = JsonSerializer.ToString(d); + Assert.Equal(@"""2000-12-15T22:11:03.055Z""", result); + + Assert.Equal(d, JsonSerializer.Parse(result)); + + d = new DateTime(2000, 12, 15, 22, 11, 3, 55, DateTimeKind.Local); + result = JsonSerializer.ToString(d); + Assert.Equal(@"""2000-12-15T22:11:03.055" + GetUtcOffsetText(d) + @"""", result); + } + + [Fact] + public void SerializeDateTimeOffset() + { + DateTimeOffset d = new DateTimeOffset(2000, 12, 15, 22, 11, 3, 55, TimeSpan.Zero); + string result; + + result = JsonSerializer.ToString(d); + Assert.Equal(@"""2000-12-15T22:11:03.055+00:00""", result); + + Assert.Equal(d, JsonSerializer.Parse(result)); + } + + [Fact] + public void DeserializeDateTimeOffset() + { + // Intentionally use an offset that is unlikely in the real world, + // so the test will be accurate regardless of the local time zone setting. + TimeSpan offset = new TimeSpan(2, 15, 0); + DateTimeOffset dto = new DateTimeOffset(2014, 1, 1, 0, 0, 0, 0, offset); + + DateTimeOffset test = JsonSerializer.Parse("\"2014-01-01T00:00:00+02:15\""); + + Assert.Equal(dto, test); + Assert.Equal(dto.ToString("o"), test.ToString("o")); + } + + [Fact] + public void NullableSerializeUTC() + { + NullableDateTimeTestClass c = new NullableDateTimeTestClass(); + c.DateTimeField = new DateTime(2008, 12, 12, 12, 12, 12, 0, DateTimeKind.Utc).ToLocalTime(); + c.DateTimeOffsetField = new DateTime(2008, 12, 12, 12, 12, 12, 0, DateTimeKind.Utc).ToLocalTime(); + c.PreField = "Pre"; + c.PostField = "Post"; + string json = JsonSerializer.ToString(c); + + NullableDateTimeTestClass newOne = JsonSerializer.Parse(json); + Assert.Equal(newOne.DateTimeField, c.DateTimeField); + Assert.Equal(newOne.DateTimeOffsetField, c.DateTimeOffsetField); + Assert.Equal(newOne.PostField, c.PostField); + Assert.Equal(newOne.PreField, c.PreField); + + c.DateTimeField = null; + c.DateTimeOffsetField = null; + c.PreField = "Pre"; + c.PostField = "Post"; + json = JsonSerializer.ToString(c); + Assert.Equal(@"{""PreField"":""Pre"",""DateTimeField"":null,""DateTimeOffsetField"":null,""PostField"":""Post""}", json); + } + + [Fact] + public void SerializeUTC() + { + DateTimeTestClass c = new DateTimeTestClass(); + c.DateTimeField = new DateTime(2008, 12, 12, 12, 12, 12, 0, DateTimeKind.Utc).ToLocalTime(); + c.DateTimeOffsetField = new DateTime(2008, 12, 12, 12, 12, 12, 0, DateTimeKind.Utc).ToLocalTime(); + c.PreField = "Pre"; + c.PostField = "Post"; + string json = JsonSerializer.ToString(c); + + NullableDateTimeTestClass newOne = JsonSerializer.Parse(json); + Assert.Equal(newOne.DateTimeField, c.DateTimeField); + Assert.Equal(newOne.DateTimeOffsetField, c.DateTimeOffsetField); + Assert.Equal(newOne.PostField, c.PostField); + Assert.Equal(newOne.PreField, c.PreField); + + //test the other edge case too (start of a year) + c.DateTimeField = new DateTime(2008, 1, 1, 1, 1, 1, 0, DateTimeKind.Utc).ToLocalTime(); + c.DateTimeOffsetField = new DateTime(2008, 1, 1, 1, 1, 1, 0, DateTimeKind.Utc).ToLocalTime(); + c.PreField = "Pre"; + c.PostField = "Post"; + json = JsonSerializer.ToString(c); + + newOne = JsonSerializer.Parse(json); + Assert.Equal(newOne.DateTimeField, c.DateTimeField); + Assert.Equal(newOne.DateTimeOffsetField, c.DateTimeOffsetField); + Assert.Equal(newOne.PostField, c.PostField); + Assert.Equal(newOne.PreField, c.PreField); + } + + [Fact] + public void BlogCodeSample() + { + Person p = new Person + { + Name = "Keith", + BirthDate = new DateTime(1980, 3, 8), + LastModified = new DateTime(2009, 4, 12, 20, 44, 55), + }; + + string jsonText = JsonSerializer.ToString(p, new JsonSerializerOptions { IgnoreNullValues = true}); + + Assert.Equal(@"{""Name"":""Keith"",""BirthDate"":""1980-03-08T00:00:00"",""LastModified"":""2009-04-12T20:44:55""}", jsonText); + } + } + + internal class DateTimeTestClass + { + public string PreField { get; set; } + + public DateTime DateTimeField { get; set; } + + public DateTimeOffset DateTimeOffsetField { get; set; } + public string PostField { get; set; } + } + + internal class NullableDateTimeTestClass + { + public string PreField { get; set; } + public DateTime? DateTimeField { get; set; } + public DateTimeOffset? DateTimeOffsetField { get; set; } + public string PostField { get; set; } + } +} diff --git a/src/libraries/System.Text.Json/tests/NewtonsoftTests/EnumConverterTests.cs b/src/libraries/System.Text.Json/tests/NewtonsoftTests/EnumConverterTests.cs new file mode 100644 index 00000000000..db1a750d82c --- /dev/null +++ b/src/libraries/System.Text.Json/tests/NewtonsoftTests/EnumConverterTests.cs @@ -0,0 +1,375 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// Copyright (c) 2007 James Newton-King +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +using System.Collections.Generic; +using System.Runtime.Serialization; +using Xunit; +using System.Text.Json.Serialization; + +namespace System.Text.Json.Tests +{ + public class EnumConverterTests + { + [Fact] + public static void SerializeEnumClass() + { + EnumClass enumClass = new EnumClass() + { + StoreColor = StoreColor.Red, + NullableStoreColor1 = StoreColor.White, + NullableStoreColor2 = null + }; + + string json = JsonSerializer.ToString(enumClass, new JsonSerializerOptions { WriteIndented = true }); + + Assert.Equal(@"{ + ""StoreColor"": 2, + ""NullableStoreColor1"": 8, + ""NullableStoreColor2"": null +}", json); + } + + [Fact] + public static void SerializeEnumClassUndefined() + { + EnumClass enumClass = new EnumClass() + { + StoreColor = (StoreColor)1000, + NullableStoreColor1 = (StoreColor)1000, + NullableStoreColor2 = null + }; + + string json = JsonSerializer.ToString(enumClass, new JsonSerializerOptions { WriteIndented = true }); + + Assert.Equal(@"{ + ""StoreColor"": 1000, + ""NullableStoreColor1"": 1000, + ""NullableStoreColor2"": null +}", json); + } + + [Fact] + public static void SerializeFlagEnum() + { + EnumClass enumClass = new EnumClass() + { + StoreColor = StoreColor.Red | StoreColor.White, + NullableStoreColor1 = StoreColor.White & StoreColor.Yellow, + NullableStoreColor2 = StoreColor.Red | StoreColor.White | StoreColor.Black + }; + + string json = JsonSerializer.ToString(enumClass, new JsonSerializerOptions { WriteIndented = true }); + + Assert.Equal(@"{ + ""StoreColor"": 10, + ""NullableStoreColor1"": 0, + ""NullableStoreColor2"": 11 +}", json); + } + + [Fact] + public static void SerializeNegativeFlagsEnum() + { + NegativeFlagsEnumClass negativeEnumClass = new NegativeFlagsEnumClass(); + negativeEnumClass.Value1 = NegativeFlagsEnum.NegativeFour | NegativeFlagsEnum.NegativeTwo; + negativeEnumClass.Value2 = NegativeFlagsEnum.Two | NegativeFlagsEnum.Four; + + string json = JsonSerializer.ToString(negativeEnumClass, new JsonSerializerOptions { WriteIndented = true }); + + Assert.Equal(@"{ + ""Value1"": -2, + ""Value2"": 6 +}", json); + } + + [Fact] + public static void SerializeNegativeEnum() + { + NegativeEnumClass negativeEnumClass = new NegativeEnumClass() + { + Value1 = NegativeEnum.Negative, + Value2 = (NegativeEnum)int.MinValue + }; + + string json = JsonSerializer.ToString(negativeEnumClass, new JsonSerializerOptions { WriteIndented = true }); + + Assert.Equal(@"{ + ""Value1"": -1, + ""Value2"": -2147483648 +}", json); + } + + [Fact] + public static void EnumMemberPlusFlags() + { + List lfoo = + new List + { + Foo.Bat | Foo.SerializeAsBaz, + Foo.FooBar, + Foo.Bat, + Foo.SerializeAsBaz, + Foo.FooBar | Foo.SerializeAsBaz, + (Foo)int.MaxValue + }; + + string json1 = JsonSerializer.ToString(lfoo, new JsonSerializerOptions { WriteIndented = true, PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); + + Assert.Equal(@"[ + 6, + 1, + 2, + 4, + 5, + 2147483647 +]", json1); + + IList foos = JsonSerializer.Parse>(json1); + + Assert.Equal(6, foos.Count); + Assert.Equal(Foo.Bat | Foo.SerializeAsBaz, foos[0]); + Assert.Equal(Foo.FooBar, foos[1]); + Assert.Equal(Foo.Bat, foos[2]); + Assert.Equal(Foo.SerializeAsBaz, foos[3]); + Assert.Equal(Foo.FooBar | Foo.SerializeAsBaz, foos[4]); + Assert.Equal((Foo)int.MaxValue, foos[5]); + + List lbar = new List() { Bar.FooBar, Bar.Bat, Bar.SerializeAsBaz }; + + string json2 = JsonSerializer.ToString(lbar, new JsonSerializerOptions { WriteIndented = true, PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); + + Assert.Equal(@"[ + 0, + 1, + 2 +]", json2); + + IList bars = JsonSerializer.Parse>(json2); + + Assert.Equal(3, bars.Count); + Assert.Equal(Bar.FooBar, bars[0]); + Assert.Equal(Bar.Bat, bars[1]); + Assert.Equal(Bar.SerializeAsBaz, bars[2]); + } + + [Fact] + public static void TestValidIntegerValue() + { + StoreColor c = JsonSerializer.Parse("1"); + Assert.Equal(c, StoreColor.Black); + } + + [Fact] + public static void DuplicateNameEnumTest() + { + JsonException e = Assert.Throws(() => + JsonSerializer.Parse("\"foo_bar\"")); + } + + [Fact] + public static void InvalidValueStringNumber() + { + JsonException ex = Assert.Throws(() => + { + StoreColor s = JsonSerializer.Parse("\"1\""); + }); + } + + [Fact] + public static void SerializeEnumWithDifferentCases() + { + string json = JsonSerializer.ToString(EnumWithDifferentCases.M); + + Assert.Equal("0", json); + + json = JsonSerializer.ToString(EnumWithDifferentCases.m); + + Assert.Equal("1", json); + } + + [Fact] + public static void DeserializeEnumWithDifferentCases() + { + EnumWithDifferentCases e = JsonSerializer.Parse("0"); + Assert.Equal(EnumWithDifferentCases.M, e); + + e = JsonSerializer.Parse("1"); + Assert.Equal(EnumWithDifferentCases.m, e); + } + + [Fact] + public static void SerializeEnumMemberWithDifferentCases() + { + string json = JsonSerializer.ToString(EnumMemberWithDifferentCases.Month); + + Assert.Equal("0", json); + + json = JsonSerializer.ToString(EnumMemberWithDifferentCases.Minute); + + Assert.Equal("1", json); + } + + [Fact] + public static void InvalidValueDash() + { + JsonException ex = Assert.Throws(() => + { + JsonSerializer.Parse("\"-\""); + }); + } + + [Fact] + public static void DeserializeNegativeEnum() + { + string json = @"{ + ""Value1"": -1, + ""Value2"": -2147483648 +}"; + NegativeEnumClass negativeEnumClass = JsonSerializer.Parse(json); + Assert.Equal(NegativeEnum.Negative, negativeEnumClass.Value1); + Assert.Equal((NegativeEnum)int.MinValue, negativeEnumClass.Value2); + } + + [Fact] + public static void DeserializeEnumClass() + { + string json = @"{ + ""StoreColor"": 2, + ""NullableStoreColor1"": 8, + ""NullableStoreColor2"": null +}"; + EnumClass enumClass = JsonSerializer.Parse(json); + Assert.Equal(StoreColor.Red, enumClass.StoreColor); + Assert.Equal(StoreColor.White, enumClass.NullableStoreColor1); + Assert.Equal(null, enumClass.NullableStoreColor2); + } + + [Fact] + public static void DeserializeFlagEnum() + { + string json = @"{ + ""StoreColor"": 10, + ""NullableStoreColor1"": 0, + ""NullableStoreColor2"": 11 +}"; + EnumClass enumClass = JsonSerializer.Parse(json); + Assert.Equal(StoreColor.Red | StoreColor.White, enumClass.StoreColor); + Assert.Equal((StoreColor)0, enumClass.NullableStoreColor1); + Assert.Equal(StoreColor.Red | StoreColor.White | StoreColor.Black, enumClass.NullableStoreColor2); + } + } + + [Flags] + internal enum Foo + { + FooBar = 0x01, + Bat = 0x02, + SerializeAsBaz = 0x4, + } + + internal enum Bar + { + FooBar, + Bat, + SerializeAsBaz + } + + internal enum NegativeEnum + { + Negative = -1, + Zero = 0, + Positive = 1 + } + + [Flags] + internal enum NegativeFlagsEnum + { + NegativeFour = -4, + NegativeTwo = -2, + NegativeOne = -1, + Zero = 0, + One = 1, + Two = 2, + Four = 4 + } + + internal enum EnumWithDifferentCases + { + M, + m + } + + internal enum EnumMemberWithDifferentCases + { + Month, + Minute + } + + internal class NegativeEnumClass + { + public NegativeEnum Value1 { get; set; } + public NegativeEnum Value2 { get; set; } + } + + internal class NegativeFlagsEnumClass + { + public NegativeFlagsEnum Value1 { get; set; } + public NegativeFlagsEnum Value2 { get; set; } + } + + [Flags] + internal enum StoreColor + { + Black = 1, + Red = 2, + Yellow = 4, + White = 8, + DarkGoldenrod = 16 + } + + internal class EnumClass + { + public StoreColor StoreColor { get; set; } + public StoreColor NullableStoreColor1 { get; set; } + public StoreColor? NullableStoreColor2 { get; set; } + } + + internal enum DuplicateNameEnum + { + [EnumMember] + first = 0, + + [EnumMember] + foo_bar = 1, + + [EnumMember(Value = "foo_bar")] + FooBar = 2, + + [EnumMember] + foo_bar_NOT_USED = 3 + } +} diff --git a/src/libraries/System.Text.Json/tests/NewtonsoftTests/ImmutableCollectionsTests.cs b/src/libraries/System.Text.Json/tests/NewtonsoftTests/ImmutableCollectionsTests.cs new file mode 100644 index 00000000000..597ee2d7513 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/NewtonsoftTests/ImmutableCollectionsTests.cs @@ -0,0 +1,429 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// Copyright (c) 2007 James Newton-King +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Text.Json.Serialization; +using Xunit; + +namespace System.Text.Json.Tests +{ + public class ImmutableCollectionsTests + { + private static readonly JsonSerializerOptions s_indentedOption = new JsonSerializerOptions { WriteIndented = true }; + + #region List + [Fact] + public void SerializeList() + { + ImmutableList data = ImmutableList.CreateRange(new List + { + "One", + "II", + "3" + }); + + string json = JsonSerializer.ToString(data); + Assert.Equal(@"[""One"",""II"",""3""]", json); + } + + [Fact] + public void DeserializeList() + { + string json = @"[ + ""One"", + ""II"", + ""3"" +]"; + + ImmutableList data = JsonSerializer.Parse>(json); + + Assert.Equal(3, data.Count); + Assert.Equal("One", data[0]); + Assert.Equal("II", data[1]); + Assert.Equal("3", data[2]); + } + + [Fact] + public void DeserializeListInterface() + { + string json = @"[ + ""Volibear"", + ""Teemo"", + ""Katarina"" + ]"; + + IImmutableList champions = JsonSerializer.Parse>(json); + + Assert.Equal(3, champions.Count); + Assert.Equal("Volibear", champions[0]); + Assert.Equal("Teemo", champions[1]); + Assert.Equal("Katarina", champions[2]); + } + #endregion + + #region Array + [ActiveIssue(36643)] + [Fact] + public void SerializeArray() + { + ImmutableArray data = ImmutableArray.CreateRange(new List + { + "One", + "II", + "3" + }); + + string json = JsonSerializer.ToString(data, s_indentedOption); + Assert.Equal(@"[ + ""One"", + ""II"", + ""3"" +]", json); + } + + [ActiveIssue(36643)] + [Fact] + public void DeserializeArray() + { + string json = @"[ + ""One"", + ""II"", + ""3"" + ]"; + + ImmutableArray data = JsonSerializer.Parse>(json); + + Assert.Equal(3, data.Length); + Assert.Equal("One", data[0]); + Assert.Equal("II", data[1]); + Assert.Equal("3", data[2]); + } + + [ActiveIssue(36643)] + [Fact] + public void SerializeDefaultArray() + { + InvalidOperationException e = Assert.Throws( + () => JsonSerializer.ToString(default(ImmutableArray), s_indentedOption)); + Assert.Equal(e.Message, "This operation cannot be performed on a default instance of ImmutableArray. Consider initializing the array, or checking the ImmutableArray.IsDefault property."); + } + #endregion + + #region Queue + [Fact] + public void SerializeQueue() + { + ImmutableQueue data = ImmutableQueue.CreateRange(new List + { + "One", + "II", + "3" + }); + + string json = JsonSerializer.ToString(data); + Assert.Equal(@"[""One"",""II"",""3""]", json); + } + + [Fact] + public void DeserializeQueue() + { + string json = @"[ + ""One"", + ""II"", + ""3"" +]"; + + ImmutableQueue data = JsonSerializer.Parse>(json); + + Assert.False(data.IsEmpty); + Assert.Equal("One", data.Peek()); + data = data.Dequeue(); + Assert.Equal("II", data.Peek()); + data = data.Dequeue(); + Assert.Equal("3", data.Peek()); + } + + [Fact] + public void DeserializeQueueInterface() + { + string json = @"[ + ""One"", + ""II"", + ""3"" +]"; + + IImmutableQueue data = JsonSerializer.Parse>(json); + + Assert.False(data.IsEmpty); + Assert.Equal("One", data.Peek()); + data = data.Dequeue(); + Assert.Equal("II", data.Peek()); + data = data.Dequeue(); + Assert.Equal("3", data.Peek()); + } + #endregion + + #region Stack + [Fact] + public void SerializeStack() + { + ImmutableStack data = ImmutableStack.CreateRange(new List + { + "One", + "II", + "3" + }); + + string json = JsonSerializer.ToString(data); + Assert.Equal(@"[""3"",""II"",""One""]", json); + } + + [Fact] + public void DeserializeStack() + { + string json = @"[ + ""One"", + ""II"", + ""3"" +]"; + + ImmutableStack data = JsonSerializer.Parse>(json); + + Assert.False(data.IsEmpty); + Assert.Equal("3", data.Peek()); + data = data.Pop(); + Assert.Equal("II", data.Peek()); + data = data.Pop(); + Assert.Equal("One", data.Peek()); + } + + [Fact] + public void DeserializeStackInterface() + { + string json = @"[ + ""One"", + ""II"", + ""3"" +]"; + + IImmutableStack data = JsonSerializer.Parse>(json); + + Assert.False(data.IsEmpty); + Assert.Equal("3", data.Peek()); + data = data.Pop(); + Assert.Equal("II", data.Peek()); + data = data.Pop(); + Assert.Equal("One", data.Peek()); + } + #endregion + + #region HashSet + [Fact] + public void SerializeHashSet() + { + ImmutableHashSet data = ImmutableHashSet.CreateRange(new List + { + "One", + "II", + "3" + }); + + string json = JsonSerializer.ToString(data, s_indentedOption); + + ImmutableHashSet a = JsonSerializer.Parse>(json); + Assert.Equal(3, a.Count); + Assert.True(a.Contains("One")); + Assert.True(a.Contains("II")); + Assert.True(a.Contains("3")); + } + + [Fact] + public void DeserializeHashSet() + { + string json = @"[ + ""One"", + ""II"", + ""3"" +]"; + + ImmutableHashSet data = JsonSerializer.Parse>(json); + + Assert.Equal(3, data.Count); + Assert.True(data.Contains("3")); + Assert.True(data.Contains("II")); + Assert.True(data.Contains("One")); + } + + [Fact] + public void DeserializeHashSetInterface() + { + string json = @"[ + ""One"", + ""II"", + ""3"" +]"; + + IImmutableSet data = JsonSerializer.Parse>(json); + + Assert.Equal(3, data.Count); + Assert.True(data.Contains("3")); + Assert.True(data.Contains("II")); + Assert.True(data.Contains("One")); + } + #endregion + + #region SortedSet + [Fact] + public void SerializeSortedSet() + { + ImmutableSortedSet data = ImmutableSortedSet.CreateRange(new List + { + "One", + "II", + "3" + }); + + string json = JsonSerializer.ToString(data); + Assert.Equal(@"[""3"",""II"",""One""]", json); + } + + [Fact] + public void DeserializeSortedSet() + { + string json = @"[ + ""One"", + ""II"", + ""3"" +]"; + + ImmutableSortedSet data = JsonSerializer.Parse>(json); + + Assert.Equal(3, data.Count); + Assert.True(data.Contains("3")); + Assert.True(data.Contains("II")); + Assert.True(data.Contains("One")); + } + #endregion + + #region Dictionary + [ActiveIssue(36643)] + [Fact] + public void SerializeDictionary() + { + ImmutableDictionary data = ImmutableDictionary.CreateRange(new Dictionary + { + { 1, "One" }, + { 2, "II" }, + { 3, "3" } + }); + + string json = JsonSerializer.ToString(data, s_indentedOption); + ImmutableDictionary a = JsonSerializer.Parse>(json); + Assert.Equal(3, a.Count); + Assert.Equal("One", (string)a[1]); + Assert.Equal("II", (string)a[2]); + Assert.Equal("3", (string)a[3]); + } + + [ActiveIssue(36643)] + [Fact] + public void DeserializeDictionary() + { + string json = @"{ + ""1"": ""One"", + ""2"": ""II"", + ""3"": ""3"" +}"; + + ImmutableDictionary data = JsonSerializer.Parse>(json); + + Assert.Equal(3, data.Count); + Assert.Equal("One", data[1]); + Assert.Equal("II", data[2]); + Assert.Equal("3", data[3]); + } + + [ActiveIssue(36643)] + [Fact] + public void DeserializeDictionaryInterface() + { + string json = @"{ + ""1"": ""One"", + ""2"": ""II"", + ""3"": ""3"" +}"; + + IImmutableDictionary data = JsonSerializer.Parse>(json); + + Assert.Equal(3, data.Count); + Assert.Equal("One", data[1]); + Assert.Equal("II", data[2]); + Assert.Equal("3", data[3]); + } + #endregion + + #region SortedDictionary + [ActiveIssue(36643)] + [Fact] + public void SerializeSortedDictionary() + { + ImmutableSortedDictionary data = ImmutableSortedDictionary.CreateRange(new SortedDictionary + { + { 1, "One" }, + { 2, "II" }, + { 3, "3" } + }); + + string json = JsonSerializer.ToString(data, s_indentedOption); + Assert.Equal(@"{ + ""1"": ""One"", + ""2"": ""II"", + ""3"": ""3"" +}", json); + } + + [ActiveIssue(36643)] + [Fact] + public void DeserializeSortedDictionary() + { + string json = @"{ + ""1"": ""One"", + ""2"": ""II"", + ""3"": ""3"" +}"; + + ImmutableSortedDictionary data = JsonSerializer.Parse>(json); + + Assert.Equal(3, data.Count); + Assert.Equal("One", data[1]); + Assert.Equal("II", data[2]); + Assert.Equal("3", data[3]); + } + #endregion + } +} diff --git a/src/libraries/System.Text.Json/tests/NewtonsoftTests/JsonSerializerTests.cs b/src/libraries/System.Text.Json/tests/NewtonsoftTests/JsonSerializerTests.cs new file mode 100644 index 00000000000..2f70a5e2b75 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/NewtonsoftTests/JsonSerializerTests.cs @@ -0,0 +1,168 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// Copyright (c) 2007 James Newton-King +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +using System.Collections.Generic; +using System.Text.Json.Serialization; +using Xunit; + +namespace System.Text.Json.Tests +{ + public class IncompleteTestClass + { + public int Key { get; set; } + } + + public class JsonSerializerTests + { + [Fact] + public void DeserializeBoolean_Null() + { + Assert.Throws( + () => JsonSerializer.Parse>(@"[null]")); + } + + [Fact] + public void DeserializeBoolean_DateTime() + { + Assert.Throws( + () => JsonSerializer.Parse>(@"['2000-12-20T10:55:55Z']")); + } + + [Fact] + public void DeserializeBoolean_BadString() + { + Assert.Throws( + () => JsonSerializer.Parse>(@"['pie']")); + } + + [Fact] + public void DeserializeBoolean_EmptyString() + { + Assert.Throws( + () => JsonSerializer.Parse>(@"['']")); + } + + [Fact] + public void IncompleteContainers() + { + JsonException e = Assert.Throws(() => JsonSerializer.Parse>("[1,")); + Assert.Equal(e.Message, "Expected start of a property name or value, but instead reached end of data. Path: $[1] | LineNumber: 0 | BytePositionInLine: 2."); + + e = Assert.Throws(() => JsonSerializer.Parse>("[1,")); + Assert.Equal(e.Message, "Expected start of a property name or value, but instead reached end of data. Path: $[1] | LineNumber: 0 | BytePositionInLine: 2."); + + e = Assert.Throws(() => JsonSerializer.Parse>("[1")); + Assert.Equal(e.Message, "'1' is an invalid end of a number. Expected a delimiter. Path: $[0] | LineNumber: 0 | BytePositionInLine: 2."); + + e = Assert.Throws(() => JsonSerializer.Parse>("{\"key\":1,")); + Assert.Equal(e.Message, "Expected start of a property name or value, but instead reached end of data. Path: $.key | LineNumber: 0 | BytePositionInLine: 8."); + + e = Assert.Throws(() => JsonSerializer.Parse>("{\"key\":1")); + Assert.Equal(e.Message, "'1' is an invalid end of a number. Expected a delimiter. Path: $.key | LineNumber: 0 | BytePositionInLine: 8."); + + e = Assert.Throws(() => JsonSerializer.Parse("{\"key\":1,")); + Assert.Equal(e.Message, "Expected start of a property name or value, but instead reached end of data. Path: $ | LineNumber: 0 | BytePositionInLine: 8."); + } + + [Fact] + public void NewProperty() + { + Assert.Equal(@"{""IsTransient"":true}", JsonSerializer.ToString(new ChildClass { IsTransient = true })); + + ChildClass childClass = JsonSerializer.Parse(@"{""IsTransient"":true}"); + Assert.Equal(true, childClass.IsTransient); + } + + [Fact] + public void NewPropertyVirtual() + { + Assert.Equal(@"{""IsTransient"":true}", JsonSerializer.ToString(new ChildClassVirtual { IsTransient = true })); + + ChildClassVirtual childClass = JsonSerializer.Parse(@"{""IsTransient"":true}"); + Assert.Equal(true, childClass.IsTransient); + } + + [Fact] + public void DeserializeCommentTestObjectWithComments() + { + CommentTestObject o = JsonSerializer.Parse(@"{/* Test */}", new JsonSerializerOptions { ReadCommentHandling = JsonCommentHandling.Skip }); + Assert.Equal(false, o.A); + + o = JsonSerializer.Parse(@"{""A"": true/* Test */}", new JsonSerializerOptions { ReadCommentHandling = JsonCommentHandling.Skip }); + Assert.Equal(true, o.A); + } + + [Fact] + public void PreserveReferencesCallbackTest() + { + PersonReference p1 = new PersonReference + { + Name = "John Smith" + }; + PersonReference p2 = new PersonReference + { + Name = "Mary Sue", + }; + + p1.Spouse = p2; + p2.Spouse = p1; + Assert.Throws (() => JsonSerializer.ToString(p1)); + } + } + + public class PersonReference + { + internal Guid Id { get; set; } + public string Name { get; set; } + public PersonReference Spouse { get; set; } + } + + public class CommentTestObject + { + public bool A { get; set; } + } + + public class ChildClassVirtual : BaseClassVirtual + { + public new virtual bool IsTransient { get; set; } + } + + public class BaseClassVirtual + { + internal virtual bool IsTransient { get; set; } + } + + public class BaseClass + { + internal bool IsTransient { get; set; } + } + + public class ChildClass : BaseClass + { + public new bool IsTransient { get; set; } + } +} diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests.csproj b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests.csproj index 5d94215ea87..67958340d07 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests.csproj +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests.csproj @@ -23,6 +23,12 @@ + + + + + +