1
0
Fork 0
mirror of https://github.com/VSadov/Satori.git synced 2025-06-11 02:13:38 +09:00
Satori/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonNode/JsonValueTests.cs
Eirik Tsarpalis 90d4c7d41a
Improve JsonNode.DeepEquals numeric equality. (#104255)
* Attempt at improving JsonNode.DeepEquals numeric equality.

* Implement arbitrary-precision decimal equality comparison.

* Address feedback

* Add more comments.

* Update src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.cs

Co-authored-by: Stephen Toub <stoub@microsoft.com>

* Address feedback

* Improve comments

* Update src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.cs

* Trim frac trailing zeros before trimming leading zeros.

* Add handling for exponent values > Int32

---------

Co-authored-by: Stephen Toub <stoub@microsoft.com>
2024-07-08 17:57:59 +01:00

630 lines
28 KiB
C#

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
using Xunit;
namespace System.Text.Json.Nodes.Tests
{
public static class JsonValueTests
{
[Fact]
public static void CreateFromNull()
{
Assert.Null(JsonValue.Create((bool?)null));
Assert.Null(JsonValue.Create((string)null));
Assert.Null(JsonValue.Create((JsonElement?)null));
Assert.Null(JsonValue.Create(JsonDocument.Parse("null").RootElement));
Assert.Null(JsonValue.Create((object)null));
Assert.Null(JsonValue.Create((bool?)null));
Assert.Null(JsonValue.Create((string)null));
Assert.Null(JsonValue.Create((JsonElement?)null));
Assert.Null(JsonValue.Create(JsonDocument.Parse("null").RootElement));
}
[Fact]
public static void CreateFromNode_Fail()
{
Assert.Throws<ArgumentException>(() => JsonValue.Create(new JsonArray()));
Assert.Throws<ArgumentException>(() => JsonValue.Create(new JsonObject()));
Assert.Throws<ArgumentException>(() => JsonValue.Create(JsonValue.Create(42)));
}
private class Polymorphic_Base { }
private class Polymorphic_Derived : Polymorphic_Base { }
[Fact]
public static void Polymorphic()
{
JsonValue value;
Polymorphic_Base baseClass = new Polymorphic_Derived();
value = JsonValue.Create(baseClass);
Assert.Same(baseClass, value.GetValue<Polymorphic_Derived>());
Polymorphic_Derived derivedClass = new Polymorphic_Derived();
value = JsonValue.Create(derivedClass);
Assert.Same(derivedClass, value.GetValue<Polymorphic_Base>());
Assert.Same(derivedClass, value.GetValue<object>());
}
[Fact]
public static void QuotedNumbers_Deserialize()
{
var options = new JsonSerializerOptions();
options.NumberHandling = JsonNumberHandling.AllowReadingFromString |
JsonNumberHandling.AllowNamedFloatingPointLiterals;
JsonNode node = JsonSerializer.Deserialize<JsonNode>("\"42\"", options);
Assert.IsAssignableFrom<JsonValue>(node);
Assert.Throws<InvalidOperationException>(() => node.GetValue<int>());
// A second pass is needed to obtain the quoted number.
Assert.Equal(42, JsonSerializer.Deserialize<int>(node.ToJsonString(), options));
node = JsonSerializer.Deserialize<JsonNode>("\"NaN\"", options);
Assert.IsAssignableFrom<JsonValue>(node);
Assert.Equal(double.NaN, JsonSerializer.Deserialize<double>(node.ToJsonString(), options));
Assert.Equal(float.NaN, JsonSerializer.Deserialize<float>(node.ToJsonString(), options));
}
[Fact]
public static void QuotedNumbers_Serialize()
{
var options = new JsonSerializerOptions();
options.NumberHandling = JsonNumberHandling.WriteAsString;
JsonValue obj = JsonValue.Create(42);
string json = obj.ToJsonString(options);
Assert.Equal("\"42\"", json);
obj = JsonValue.Create(double.NaN);
json = obj.ToJsonString(options);
Assert.Equal("\"NaN\"", json);
}
[Fact]
public static void FromElement()
{
using (JsonDocument document = JsonDocument.Parse("42"))
{
JsonValue jValue = JsonValue.Create(document.RootElement);
Assert.Equal(42, jValue.GetValue<int>());
}
using (JsonDocument document = JsonDocument.Parse("null"))
{
JsonValue? jValue = JsonValue.Create(document.RootElement);
Assert.Null(jValue);
}
}
[Fact]
public static void TryGetValue_FromString()
{
JsonValue jValue = JsonNode.Parse("\"MyString\"").AsValue();
Assert.True(jValue.TryGetValue(out string _));
Assert.False(jValue.TryGetValue(out char _));
Assert.False(jValue.TryGetValue(out byte _));
Assert.False(jValue.TryGetValue(out short _));
Assert.False(jValue.TryGetValue(out int _));
Assert.False(jValue.TryGetValue(out long _));
Assert.False(jValue.TryGetValue(out sbyte _));
Assert.False(jValue.TryGetValue(out ushort _));
Assert.False(jValue.TryGetValue(out uint _));
Assert.False(jValue.TryGetValue(out ulong _));
Assert.False(jValue.TryGetValue(out bool _));
Assert.False(jValue.TryGetValue(out float _));
Assert.False(jValue.TryGetValue(out double _));
Assert.False(jValue.TryGetValue(out decimal _));
Assert.False(jValue.TryGetValue(out DateTime _));
Assert.False(jValue.TryGetValue(out DateTimeOffset _));
Assert.False(jValue.TryGetValue(out Guid _));
}
[Fact]
public static void TryGetValue_FromNumber()
{
JsonValue jValue = JsonNode.Parse("42").AsValue();
Assert.True(jValue.TryGetValue(out byte _));
Assert.True(jValue.TryGetValue(out short _));
Assert.True(jValue.TryGetValue(out int _));
Assert.True(jValue.TryGetValue(out long _));
Assert.True(jValue.TryGetValue(out sbyte _));
Assert.True(jValue.TryGetValue(out ushort _));
Assert.True(jValue.TryGetValue(out uint _));
Assert.True(jValue.TryGetValue(out ulong _));
Assert.True(jValue.TryGetValue(out float _));
Assert.True(jValue.TryGetValue(out double _));
Assert.True(jValue.TryGetValue(out decimal _));
Assert.False(jValue.TryGetValue(out bool _));
Assert.False(jValue.TryGetValue(out string _));
Assert.False(jValue.TryGetValue(out char _));
Assert.False(jValue.TryGetValue(out DateTime _));
Assert.False(jValue.TryGetValue(out DateTimeOffset _));
Assert.False(jValue.TryGetValue(out Guid _));
}
[Fact]
public static void TryGetValue_FromGuid()
{
JsonValue jValue = JsonNode.Parse("\"ed957609-cdfe-412f-88c1-02daca1b4f51\"").AsValue();
Assert.True(jValue.TryGetValue(out Guid _));
Assert.True(jValue.TryGetValue(out string _));
Assert.False(jValue.TryGetValue(out char _));
Assert.False(jValue.TryGetValue(out byte _));
Assert.False(jValue.TryGetValue(out short _));
Assert.False(jValue.TryGetValue(out int _));
Assert.False(jValue.TryGetValue(out long _));
Assert.False(jValue.TryGetValue(out sbyte _));
Assert.False(jValue.TryGetValue(out ushort _));
Assert.False(jValue.TryGetValue(out uint _));
Assert.False(jValue.TryGetValue(out ulong _));
Assert.False(jValue.TryGetValue(out float _));
Assert.False(jValue.TryGetValue(out double _));
Assert.False(jValue.TryGetValue(out decimal _));
Assert.False(jValue.TryGetValue(out bool _));
Assert.False(jValue.TryGetValue(out DateTime _));
Assert.False(jValue.TryGetValue(out DateTimeOffset _));
}
[Theory]
[InlineData("\"2020-07-08T00:00:00\"")]
[InlineData("\"2019-01-30T12:01:02+01:00\"")]
public static void TryGetValue_FromDateTime(string json)
{
JsonValue jValue = JsonNode.Parse(json).AsValue();
Assert.True(jValue.TryGetValue(out DateTime _));
Assert.True(jValue.TryGetValue(out DateTimeOffset _));
Assert.True(jValue.TryGetValue(out string _));
Assert.False(jValue.TryGetValue(out char _));
Assert.False(jValue.TryGetValue(out byte _));
Assert.False(jValue.TryGetValue(out short _));
Assert.False(jValue.TryGetValue(out int _));
Assert.False(jValue.TryGetValue(out long _));
Assert.False(jValue.TryGetValue(out sbyte _));
Assert.False(jValue.TryGetValue(out ushort _));
Assert.False(jValue.TryGetValue(out uint _));
Assert.False(jValue.TryGetValue(out ulong _));
Assert.False(jValue.TryGetValue(out float _));
Assert.False(jValue.TryGetValue(out double _));
Assert.False(jValue.TryGetValue(out decimal _));
Assert.False(jValue.TryGetValue(out bool _));
Assert.False(jValue.TryGetValue(out Guid _));
}
[Fact]
public static void TryGetValue_FromBoolean()
{
JsonValue jValue = JsonNode.Parse("true").AsValue();
Assert.True(jValue.TryGetValue(out bool _));
Assert.False(jValue.TryGetValue(out byte _));
Assert.False(jValue.TryGetValue(out short _));
Assert.False(jValue.TryGetValue(out int _));
Assert.False(jValue.TryGetValue(out long _));
Assert.False(jValue.TryGetValue(out sbyte _));
Assert.False(jValue.TryGetValue(out ushort _));
Assert.False(jValue.TryGetValue(out uint _));
Assert.False(jValue.TryGetValue(out ulong _));
Assert.False(jValue.TryGetValue(out float _));
Assert.False(jValue.TryGetValue(out double _));
Assert.False(jValue.TryGetValue(out decimal _));
Assert.False(jValue.TryGetValue(out string _));
Assert.False(jValue.TryGetValue(out char _));
Assert.False(jValue.TryGetValue(out DateTime _));
Assert.False(jValue.TryGetValue(out DateTimeOffset _));
Assert.False(jValue.TryGetValue(out Guid _));
}
[Theory]
[InlineData("\"A\"")]
[InlineData("\" \"")]
public static void FromElement_Char(string json)
{
using (JsonDocument document = JsonDocument.Parse(json))
{
JsonValue jValue = JsonValue.Create(document.RootElement);
Assert.Equal(json[1], jValue.GetValue<char>());
bool success = jValue.TryGetValue(out char ch);
Assert.True(success);
Assert.Equal(json[1], ch);
}
}
[Theory]
[InlineData("\"A\"", "A")]
[InlineData("\"AB\"", "AB")]
public static void FromElement_ToElement(string json, string expected)
{
using (JsonDocument document = JsonDocument.Parse(json))
{
JsonValue jValue = JsonValue.Create(document.RootElement);
// Obtain the internal element
JsonElement element = jValue.GetValue<JsonElement>();
Assert.Equal(expected, element.GetString());
bool success = jValue.TryGetValue(out element);
Assert.True(success);
Assert.Equal(expected, element.GetString());
}
}
[Theory]
[InlineData("42")]
[InlineData("\"AB\"")]
[InlineData("\"\"")]
public static void FromElement_Char_Fail(string json)
{
using (JsonDocument document = JsonDocument.Parse(json))
{
JsonValue jValue = JsonValue.Create(document.RootElement);
Assert.Throws<InvalidOperationException>(() => jValue.GetValue<char>());
bool success = jValue.TryGetValue(out char ch);
Assert.False(success);
}
}
[Theory]
[InlineData("{}")]
[InlineData("[]")]
public static void FromElement_WrongNodeTypeThrows(string json)
{
using (JsonDocument document = JsonDocument.Parse(json))
Assert.Throws<InvalidOperationException>(() => JsonValue.Create(document.RootElement));
}
[Fact]
public static void WriteTo_Validation()
{
Assert.Throws<ArgumentNullException>(() => JsonValue.Create(42).WriteTo(null));
}
[Fact]
public static void WriteTo()
{
const string Json = "42";
JsonValue jObject = JsonNode.Parse(Json).AsValue();
var stream = new MemoryStream();
var writer = new Utf8JsonWriter(stream);
jObject.WriteTo(writer);
writer.Flush();
string json = Encoding.UTF8.GetString(stream.ToArray());
Assert.Equal(Json, json);
}
[Fact]
public static void DeepCloneNotTrimmable()
{
var student = new Student()
{
Id = 1,
Name = "test"
};
JsonValue jValue = JsonValue.Create(student);
JsonNode clone = jValue.DeepClone();
JsonNodeTests.AssertDeepEqual(jValue, clone);
string originalJson = jValue.ToJsonString();
string clonedJson = clone.ToJsonString();
Assert.Equal(originalJson, clonedJson);
}
[Theory]
[InlineData("42")]
[InlineData("\"AB\"")]
[InlineData("\"\"")]
public static void DeepCloneTrimmable(string json)
{
using (JsonDocument document = JsonDocument.Parse(json))
{
JsonValue jsonValue = JsonValue.Create(document.RootElement);
JsonNode clone = jsonValue.DeepClone();
JsonNodeTests.AssertDeepEqual(jsonValue, clone);
string originalJson = jsonValue.ToJsonString();
string clonedJson = clone.ToJsonString();
Assert.Equal(originalJson, clonedJson);
}
}
[Fact]
public static void DeepEqualsComplexType()
{
var student = new Student()
{
Id = 10,
Name = "test"
};
JsonValue jValue = JsonValue.Create(student);
var jObject = new JsonObject();
jObject.Add("Id", 10);
jObject.Add("Name", "test");
JsonNodeTests.AssertDeepEqual(jValue, jObject);
}
[Fact]
public static void DeepEqualsPrimitiveType()
{
JsonNodeTests.AssertDeepEqual(JsonValue.Create(10), JsonValue.Create((uint)10));
JsonNodeTests.AssertDeepEqual(JsonValue.Create(10), JsonValue.Create((ulong)10));
JsonNodeTests.AssertDeepEqual(JsonValue.Create(10), JsonValue.Create((float)10));
JsonNodeTests.AssertDeepEqual(JsonValue.Create(10), JsonValue.Create((decimal)10));
JsonNodeTests.AssertDeepEqual(JsonValue.Create(10), JsonValue.Create((short)10));
JsonNodeTests.AssertDeepEqual(JsonValue.Create(10), JsonValue.Create((ushort)10));
Guid guid = Guid.Empty;
JsonNodeTests.AssertDeepEqual(JsonValue.Create(guid), JsonValue.Create(guid.ToString()));
JsonNodeTests.AssertNotDeepEqual(JsonValue.Create(10), JsonValue.Create("10"));
}
[Theory]
[InlineData("-0.0", "0")]
[InlineData("0", "0.0000e4")]
[InlineData("0", "0.0000e-4")]
[InlineData("1", "1.0")]
[InlineData("1", "1e0")]
[InlineData("1", "1.0000")]
[InlineData("1", "1.0000e0")]
[InlineData("1", "0.10000e1")]
[InlineData("1", "10.0000e-1")]
[InlineData("10001", "1.0001e4")]
[InlineData("10001e-3", "1.0001e1")]
[InlineData("1", "0.1e1")]
[InlineData("0.1", "1e-1")]
[InlineData("0.001", "1e-3")]
[InlineData("1e9", "1000000000")]
[InlineData("11", "1.100000000e1")]
[InlineData("3.141592653589793", "3141592653589793E-15")]
[InlineData("0.000000000000000000000000000000000000000001", "1e-42")]
[InlineData("1000000000000000000000000000000000000000000", "1e42")]
[InlineData("-1.1e3", "-1100")]
[InlineData("79228162514264337593543950336", "792281625142643375935439503360e-1")] // decimal.MaxValue + 1
[InlineData("79228162514.264337593543950336", "792281625142643375935439503360e-19")]
[InlineData("1.75e+300", "1.75E+300")] // Variations in exponent casing
[InlineData( // > 256 digits
"1.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" +
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" +
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" +
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001" ,
"100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" +
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" +
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" +
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001" + "E-512")]
public static void DeepEqualsNumericType(string leftStr, string rightStr)
{
JsonNode left = JsonNode.Parse(leftStr);
JsonNode right = JsonNode.Parse(rightStr);
JsonNodeTests.AssertDeepEqual(left, right);
}
[Theory]
[InlineData("0", "1")]
[InlineData("1", "-1")]
[InlineData("1.1", "-1.1")]
[InlineData("1.1e5", "-1.1e5")]
[InlineData("0", "1e-1024")]
[InlineData("1", "0.1")]
[InlineData("1", "1.1")]
[InlineData("1", "1e1")]
[InlineData("1", "1.00001")]
[InlineData("1", "1.0000e1")]
[InlineData("1", "0.1000e-1")]
[InlineData("1", "10.0000e-2")]
[InlineData("10001", "1.0001e3")]
[InlineData("10001e-3", "1.0001e2")]
[InlineData("1", "0.1e2")]
[InlineData("0.1", "1e-2")]
[InlineData("0.001", "1e-4")]
[InlineData("1e9", "1000000001")]
[InlineData("11", "1.100000001e1")]
[InlineData("0.000000000000000000000000000000000000000001", "1e-43")]
[InlineData("1000000000000000000000000000000000000000000", "1e43")]
[InlineData("-1.1e3", "-1100.1")]
[InlineData("79228162514264337593543950336", "7922816251426433759354395033600e-1")] // decimal.MaxValue + 1
[InlineData("79228162514.264337593543950336", "7922816251426433759354395033601e-19")]
[InlineData("1.75e+300", "1.75E+301")] // Variations in exponent casing
[InlineData("1e2147483647", "1e-2147483648")] // int.MaxValue, int.MinValue exponents
[InlineData( // > 256 digits
"1.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" +
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" +
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" +
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
"100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" +
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" +
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" +
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003" + "E-512")]
public static void NotDeepEqualsNumericType(string leftStr, string rightStr)
{
JsonNode left = JsonNode.Parse(leftStr);
JsonNode right = JsonNode.Parse(rightStr);
JsonNodeTests.AssertNotDeepEqual(left, right);
}
[Theory]
[InlineData(int.MinValue - 1L)]
[InlineData(int.MaxValue + 1L)]
[InlineData(long.MinValue)]
[InlineData(long.MaxValue)]
public static void DeepEquals_ExponentExceedsInt32_ThrowsArgumentOutOfRangeException(long exponent)
{
JsonNode node = JsonNode.Parse($"1e{exponent}");
Assert.Throws<ArgumentOutOfRangeException>(() => JsonNode.DeepEquals(node, node));
}
[Fact]
public static void DeepEqualsJsonElement()
{
JsonDocument document1 = JsonDocument.Parse("10");
JsonValue jsonValue1 = JsonValue.Create(document1.RootElement);
JsonNodeTests.AssertDeepEqual(jsonValue1, JsonValue.Create(10));
JsonDocument document2 = JsonDocument.Parse("\"10\"");
JsonValue jsonValue2 = JsonValue.Create(document2.RootElement);
JsonNodeTests.AssertNotDeepEqual(jsonValue1, jsonValue2);
JsonNodeTests.AssertDeepEqual(jsonValue2, JsonValue.Create("10"));
}
[Fact]
public static void DeepEqualsJsonElement_Boolean()
{
JsonValue trueValue = JsonValue.Create(JsonDocument.Parse("true").RootElement);
JsonValue falseValue = JsonValue.Create(JsonDocument.Parse("false").RootElement);
JsonNodeTests.AssertNotDeepEqual(trueValue, falseValue);
JsonNodeTests.AssertDeepEqual(trueValue, trueValue.DeepClone());
}
[Fact]
public static void GetValueKind()
{
Assert.Equal(JsonValueKind.Object, JsonValue.Create(new Student()).GetValueKind());
Assert.Equal(JsonValueKind.Array, JsonValue.Create(new Student[] { }).GetValueKind());
using (JsonDocument document = JsonDocument.Parse("10"))
{
JsonValue jsonValue = JsonValue.Create(document.RootElement);
Assert.Equal(JsonValueKind.Number, jsonValue.GetValueKind());
}
}
[Theory]
[InlineData(JsonNumberHandling.Strict, JsonValueKind.Number)]
[InlineData(JsonNumberHandling.AllowReadingFromString, JsonValueKind.Number)]
[InlineData(JsonNumberHandling.AllowNamedFloatingPointLiterals, JsonValueKind.Number)]
[InlineData(JsonNumberHandling.WriteAsString, JsonValueKind.String)]
[InlineData(JsonNumberHandling.WriteAsString | JsonNumberHandling.AllowNamedFloatingPointLiterals, JsonValueKind.String)]
public static void GetValueKind_NumberHandling(JsonNumberHandling numberHandling, JsonValueKind expectedKind)
{
JsonSerializerOptions options = new(JsonSerializerOptions.Default) { NumberHandling = numberHandling };
JsonTypeInfo<int> typeInfo = (JsonTypeInfo<int>)options.GetTypeInfo(typeof(int));
JsonValue value = JsonValue.Create(42, typeInfo);
Assert.Equal(expectedKind, value.GetValueKind());
}
[Fact]
public static void DeepEquals_EscapedString()
{
JsonValue jsonValue = JsonValue.Create(JsonDocument.Parse("\"It\'s alright\"").RootElement);
JsonValue escapedJsonValue = JsonValue.Create(JsonDocument.Parse("\"It\\u0027s alright\"").RootElement);
JsonNodeTests.AssertDeepEqual(escapedJsonValue, jsonValue);
}
private class Student
{
public int Id { get; set; }
public string? Name { get; set; }
}
[Theory]
[MemberData(nameof(GetPrimitiveTypes))]
public static void PrimitiveTypes_ReturnExpectedTypeKind<T>(T value, JsonValueKind expectedKind)
{
JsonNode node = JsonValue.Create(value);
Assert.Equal(expectedKind, node.GetValueKind());
}
[Theory]
[MemberData(nameof(GetPrimitiveTypes))]
public static void PrimitiveTypes_EqualThemselves<T>(T value, JsonValueKind _)
{
JsonNode node = JsonValue.Create(value);
Assert.True(JsonNode.DeepEquals(node, node));
}
[Theory]
[MemberData(nameof(GetPrimitiveTypes))]
public static void PrimitiveTypes_EqualClonedValue<T>(T value, JsonValueKind _)
{
JsonNode node = JsonValue.Create(value);
JsonNode clone = node.DeepClone();
Assert.True(JsonNode.DeepEquals(clone, clone));
Assert.True(JsonNode.DeepEquals(node, clone));
Assert.True(JsonNode.DeepEquals(clone, node));
}
[Theory]
[MemberData(nameof(GetPrimitiveTypes))]
public static void PrimitiveTypes_EqualDeserializedValue<T>(T value, JsonValueKind _)
{
JsonNode node = JsonValue.Create(value);
JsonNode clone = JsonSerializer.Deserialize<JsonNode>(node.ToJsonString());
Assert.True(JsonNode.DeepEquals(clone, clone));
Assert.True(JsonNode.DeepEquals(node, clone));
Assert.True(JsonNode.DeepEquals(clone, node));
}
public static IEnumerable<object[]> GetPrimitiveTypes()
{
yield return Wrap(false, JsonValueKind.False);
yield return Wrap(true, JsonValueKind.True);
yield return Wrap((bool?)false, JsonValueKind.False);
yield return Wrap((bool?)true, JsonValueKind.True);
yield return Wrap((byte)42, JsonValueKind.Number);
yield return Wrap((sbyte)42, JsonValueKind.Number);
yield return Wrap((short)42, JsonValueKind.Number);
yield return Wrap((ushort)42, JsonValueKind.Number);
yield return Wrap(42, JsonValueKind.Number);
yield return Wrap((int?)42, JsonValueKind.Number);
yield return Wrap((uint)42, JsonValueKind.Number);
yield return Wrap((long)42, JsonValueKind.Number);
yield return Wrap((ulong)42, JsonValueKind.Number);
yield return Wrap(42.0f, JsonValueKind.Number);
yield return Wrap(42.0, JsonValueKind.Number);
yield return Wrap(42.0m, JsonValueKind.Number);
yield return Wrap('A', JsonValueKind.String);
yield return Wrap((char?)'A', JsonValueKind.String);
yield return Wrap("A", JsonValueKind.String);
yield return Wrap(new byte[] { 1, 2, 3 }, JsonValueKind.String);
yield return Wrap(new DateTimeOffset(2024, 06, 20, 10, 29, 0, TimeSpan.Zero), JsonValueKind.String);
yield return Wrap(new DateTime(2024, 06, 20, 10, 29, 0), JsonValueKind.String);
yield return Wrap(Guid.Empty, JsonValueKind.String);
yield return Wrap((Guid?)Guid.Empty, JsonValueKind.String);
yield return Wrap(new Uri("http://example.com"), JsonValueKind.String);
yield return Wrap(new Version(1, 2, 3, 4), JsonValueKind.String);
yield return Wrap(BindingFlags.Public, JsonValueKind.Number);
yield return Wrap((BindingFlags?)BindingFlags.Public, JsonValueKind.Number);
#if NET
yield return Wrap(Half.MaxValue, JsonValueKind.Number);
yield return Wrap((Int128)42, JsonValueKind.Number);
yield return Wrap((Int128)42, JsonValueKind.Number);
yield return Wrap((Memory<byte>)new byte[] { 1, 2, 3 }, JsonValueKind.String);
yield return Wrap((ReadOnlyMemory<byte>)new byte[] { 1, 2, 3 }, JsonValueKind.String);
yield return Wrap(new DateOnly(2024, 06, 20), JsonValueKind.String);
yield return Wrap(new TimeOnly(10, 29), JsonValueKind.String);
#endif
static object[] Wrap<T>(T value, JsonValueKind expectedKind) => [value, expectedKind];
}
}
}