namespace WoofWare.Myriad.Plugins.Test open System open System.Collections.Generic open System.IO open System.Text open System.Text.Json open System.Text.Json.Nodes open NUnit.Framework open FsCheck open FsUnitTyped open ConsumePlugin [] module TestJsonSerde = let uriGen : Gen = gen { let! suffix = Arb.generate return Uri $"https://example.com/%i{suffix}" } let rec innerGen (count : int) : Gen = gen { let! guid = Arb.generate let! mapKeys = Gen.listOf Arb.generate> let mapKeys = mapKeys |> List.map _.Get |> List.distinct let! mapValues = Gen.listOfLength mapKeys.Length uriGen let map = List.zip mapKeys mapValues |> Map.ofList let! concreteDictKeys = if count > 0 then Gen.listOf Arb.generate> else Gen.constant [] let concreteDictKeys = concreteDictKeys |> List.map _.Get |> List.distinct |> fun x -> List.take (min 3 x.Length) x let! concreteDictValues = if count > 0 then Gen.listOfLength concreteDictKeys.Length (innerGen (count - 1)) else Gen.constant [] let concreteDict = List.zip concreteDictKeys concreteDictValues |> List.map KeyValuePair |> Dictionary let! readOnlyDictKeys = Gen.listOf Arb.generate> let readOnlyDictKeys = readOnlyDictKeys |> List.map _.Get |> List.distinct let! readOnlyDictValues = Gen.listOfLength readOnlyDictKeys.Length (Gen.listOf Arb.generate) let readOnlyDict = List.zip readOnlyDictKeys readOnlyDictValues |> readOnlyDict let! dictKeys = Gen.listOf uriGen let! dictValues = Gen.listOfLength dictKeys.Length Arb.generate let dict = List.zip dictKeys dictValues |> dict return { Thing = guid Map = map ReadOnlyDict = readOnlyDict Dict = dict ConcreteDict = concreteDict } } let outerGen : Gen = gen { let! a = Arb.generate let! b = Arb.generate> let! c = Gen.listOf Arb.generate let! depth = Gen.choose (0, 2) let! d = innerGen depth let! e = Gen.arrayOf Arb.generate> let! f = Gen.arrayOf Arb.generate return { A = a B = b.Get C = c D = d E = e |> Array.map _.Get F = f } } [] let ``It just works`` () = let property (o : JsonRecordTypeWithBoth) : bool = o |> JsonRecordTypeWithBoth.toJsonNode |> fun s -> s.ToJsonString () |> JsonNode.Parse |> JsonRecordTypeWithBoth.jsonParse |> shouldEqual o true property |> Prop.forAll (Arb.fromGen outerGen) |> Check.QuickThrowOnFailure [] let ``Guids are treated just like strings`` () = let guidStr = "b1e7496e-6e79-4158-8579-a01de355d3b2" let guid = Guid.Parse guidStr let node = { Thing = guid Map = Map.empty ReadOnlyDict = readOnlyDict [] Dict = dict [] ConcreteDict = Dictionary () } |> InnerTypeWithBoth.toJsonNode node.ToJsonString () |> shouldEqual ( sprintf """{"it\u0027s-a-me":"%s","map":{},"readOnlyDict":{},"dict":{},"concreteDict":{}}""" guidStr )