Skip to content

Instantly share code, notes, and snippets.

@dangerman
Last active April 29, 2024 17:25
Show Gist options
  • Save dangerman/b3d674f4628dc9e5225f0618e1459215 to your computer and use it in GitHub Desktop.
Save dangerman/b3d674f4628dc9e5225f0618e1459215 to your computer and use it in GitHub Desktop.
Stack overflow test
using System.Runtime.CompilerServices;
using Argon;
namespace OverflowTest;
public static class ModuleInit
{
[ModuleInitializer]
public static void Init()
{
VerifierSettings.SortJsonObjects();
}
}
public class UnitTest1
{
[Fact]
public Task FruitsTest()
{
var localeFile = "../../../data/fruits.json";
var localeJsonRaw = File.ReadAllText(localeFile);
var locale = JToken.Parse(localeJsonRaw);
var settings = new VerifySettings();
settings.AddExtraSettings(jss => jss.ContractResolver = new InterceptedContractResolver(jss.ContractResolver!));
return Verify(locale, settings)
.UseDirectory("./data/")
.UseFileName($"fruits.schema");
}
[Fact]
public Task FixedFruitsTest()
{
var localeFile = "../../../data/fruits.json";
var localeJsonRaw = File.ReadAllText(localeFile);
var locale = JToken.Parse(localeJsonRaw);
var settings = new VerifySettings();
settings.AddExtraSettings(jss => jss.ContractResolver = new FixedContractResolver(jss.ContractResolver!));
return Verify(locale, settings)
.UseDirectory("./data/")
.UseFileName($"fruits-fixed.schema");
}
}
// From https://github.com/bchavez/Bogus/blob/master/Source/Bogus.Tests/SchemaTests/LocaleSchemaTests.cs#L63
// with some console output added
public JsonContract ResolveContract(Type type)
{
var contract = this.defaultResolver.ResolveContract(type);
if (contract is JsonDictionaryContract jdc)
{
var defaultIntercept = jdc.InterceptSerializeItem;
jdc.InterceptSerializeItem = (key, val) =>
{
if (val is JArray arr && arr.Children().OfType<JValue>().Any())
{
var children = arr.Children();
var first = children.First();
return InterceptResult.Replace($"[Array {first.Type}; {children.Count()}]");
}
Console.Write($" {val} ");
return defaultIntercept(key, val);
};
Console.WriteLine("\n🟢 assigned InterceptSerializeItem");
}
return contract;
}
}
// Checks updatedIntercept
public class FixedContractResolver : IContractResolver
{
private readonly IContractResolver defaultResolver;
private InterceptSerializeDictionaryItem? updatedIntercept;
public FixedContractResolver(IContractResolver defaultResolver)
{
this.defaultResolver = defaultResolver;
}
public JsonNameTable GetNameTable()
{
return defaultResolver.GetNameTable();
}
public JsonContract ResolveContract(Type type)
{
var contract = this.defaultResolver.ResolveContract(type);
if (contract is JsonDictionaryContract jdc && jdc.InterceptSerializeItem != updatedIntercept)
{
var defaultIntercept = jdc.InterceptSerializeItem;
jdc.InterceptSerializeItem = (key, val) =>
{
if (val is JArray arr && arr.Children().OfType<JValue>().Any())
{
var children = arr.Children();
var first = children.First();
return InterceptResult.Replace($"[Array {first.Type}; {children.Count()}]");
}
Console.Write($"{val} ");
return defaultIntercept(key, val);
};
this.updatedIntercept = jdc.InterceptSerializeItem;
Console.WriteLine("\n🟢 assigned InterceptSerializeItem");
}
return contract;
}
}
@dangerman
Copy link
Author

Contents of the fruits.json file in the data folder:

{
  "fruits": [
    {
      "name": "apple",
      "symbol": "🍎"
    },
    {
      "name": "banana",
      "symbol": "🍌"
    },
    {
      "name": "orange",
      "symbol": "🍊"
    },
    {
      "name": "pear",
      "symbol": "🍐"
    }
  ]
}

@dangerman
Copy link
Author

Test output:

Before After
fruits_test_before fruits_test_after

Without the fix, we can see that after n assignments, the intercept callback is run n times.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment