XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEExtension

【DLL】XFE各类拓展是一个C#的DLL库,旨在优化C#代码中常用语句的使用,并提供更简洁的访问方式,同时提供Xunit测试框架,快速搭建服务器/客户端,免费ChatGPTAPI接口,免费通讯服务器,XFE下载器,新增格式等

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Text.Json;
using XFEExtension.NetCore.XFETransform.Json;

namespace XFEExtension.NetCore.Test.Json;

public class XFEJsonDifferentialTests
{
    [Fact]
    public void RandomValidDocuments_RoundTripSemantically()
    {
        var random = new Random(0x584645);
        for (var iteration = 0; iteration < 200; iteration++)
        {
            var value = CreateValue(random, 0);
            var systemJson = JsonSerializer.Serialize(value);

            XFEJson.Validate(systemJson);
            var dynamicValue = XFEJson.Deserialize<object>(systemJson);
            var xfeJson = XFEJson.Serialize(dynamicValue);
            using var expected = JsonDocument.Parse(systemJson);
            using var actual = JsonDocument.Parse(xfeJson);

            Assert.True(JsonElement.DeepEquals(expected.RootElement, actual.RootElement),
                $"Semantic mismatch. expected={systemJson}; actual={xfeJson}");
        }
    }

    [Fact]
    public void DuplicateProperties_FirstOccurrenceWinsForQueryAndBinding()
    {
        var node = XFEJson.Parse("{\"value\":1,\"value\":2}");
        Assert.Equal(1, node["value"]!.GetInt32());

        var model = XFEJson.Deserialize<DuplicateModel>("{\"value\":1,\"value\":2}")!;
        Assert.Equal(1, model.Value);
    }

    [Fact]
    public void MaxDepth_IsEnforcedDuringValidationAndNavigation()
    {
        var options = new XFEJsonOptions { MaxDepth = 3 };
        const string json = "{\"a\":{\"b\":{\"c\":{\"d\":1}}}}";

        Assert.Throws<XFEJsonException>(() => XFEJson.Validate(json, options));
        var node = XFEJson.Parse(json, options);
        Assert.Throws<XFEJsonException>(() => _ = node["a"]!["b"]!["c"]!.Kind);
    }

    [Fact]
    public void Validation_UsesExplicitStackForVeryDeepJson()
    {
        const int depth = 1_000;
        var json = new string('[', depth) + "0" + new string(']', depth);

        XFEJson.Validate(json, new XFEJsonOptions { MaxDepth = depth + 1 });
    }

    private static object? CreateValue(Random random, int depth)
    {
        if (depth >= 3)
            return CreateScalar(random);
        return random.Next(6) switch
        {
            0 => CreateScalar(random),
            1 or 2 => Enumerable.Range(0, random.Next(0, 5)).Select(_ => CreateValue(random, depth + 1)).ToList(),
            _ => Enumerable.Range(0, random.Next(0, 5)).ToDictionary(
                index => $"p{depth}_{index}_{random.Next(1000)}",
                _ => CreateValue(random, depth + 1))
        };
    }

    private static object? CreateScalar(Random random) => random.Next(7) switch
    {
        0 => null,
        1 => random.Next(2) == 0,
        2 => random.Next(-1_000_000, 1_000_000),
        3 => random.NextDouble() * 1000 - 500,
        4 => $"text-{random.Next()}-\"-\\-\n-你好-😀",
        5 => (decimal)random.NextDouble() * 10_000m,
        _ => random.NextInt64()
    };

    public sealed class DuplicateModel
    {
        public int Value { get; set; }
    }
}