using FsCheck; namespace StellaOps.Testing.Determinism.Properties; /// /// FsCheck arbitrary generators for JSON-compatible data types. /// public static class JsonObjectArbitraries { /// /// Generates dictionaries with string keys and values. /// public static Arbitrary> StringDictionary() { return Gen.Sized(size => { var count = Gen.Choose(0, Math.Min(size, 20)); return count.SelectMany(n => { var keys = Gen.ArrayOf(n, Arb.Generate().Select(s => s.Get)) .Select(arr => arr.Distinct().ToArray()); var values = Gen.ArrayOf(n, Arb.Generate().Select(s => s.Get)); return keys.SelectMany(ks => values.Select(vs => { var dict = new Dictionary(); for (int i = 0; i < Math.Min(ks.Length, vs.Length); i++) { dict[ks[i]] = vs[i]; } return dict; })); }); }).ToArbitrary(); } /// /// Generates dictionaries with nullable object values. /// public static Arbitrary> ObjectDictionary() { return Gen.Sized(size => { var count = Gen.Choose(0, Math.Min(size, 15)); return count.SelectMany(n => { var keys = Gen.ArrayOf(n, Arb.Generate().Select(s => s.Get)) .Select(arr => arr.Distinct().ToArray()); var values = Gen.ArrayOf(n, JsonValueGen()); return keys.SelectMany(ks => values.Select(vs => { var dict = new Dictionary(); for (int i = 0; i < Math.Min(ks.Length, vs.Length); i++) { dict[ks[i]] = vs[i]; } return dict; })); }); }).ToArbitrary(); } /// /// Generates JSON-compatible values (strings, numbers, bools, nulls). /// private static Gen JsonValueGen() { return Gen.OneOf( Arb.Generate().Select(s => (object?)s.Get), Arb.Generate().Select(i => (object?)i), Arb.Generate() .Where(d => !double.IsNaN(d) && !double.IsInfinity(d)) .Select(d => (object?)d), Arb.Generate().Select(b => (object?)b), Gen.Constant(null) ); } }