Create a gist now

Instantly share code, notes, and snippets.

@mavnn /XmlGen.fs
Last active Sep 2, 2016

What would you like to do?
Really naive xml generator for FsCheck.
<someDifferentNode>
<myOtherNode />
<someDifferentNode>
<someDifferentNode>
<myNode />
</someDifferentNode>
<myNode />
<myNode>
<someDifferentNode />
</myNode>
</someDifferentNode>
<someDifferentNode>
<myNode>
<myOtherNode />
</myNode>
<myOtherNode />
<myOtherNode>
<someDifferentNode />
</myOtherNode>
</someDifferentNode>
<myOtherNode />
<myNode>
<myNode />
<myNode>
<myNode />
</myNode>
<myOtherNode />
</myNode>
<myOtherNode />
<myOtherNode>
<myNode>
<someDifferentNode />
</myNode>
<myOtherNode />
<someDifferentNode>
<someDifferentNode />
</someDifferentNode>
</myOtherNode>
</someDifferentNode>
open FsCheck
type XmlTree =
| NodeName of string
| Container of string * List<XmlTree>
let nodeNames = ["myNode";"myOtherNode";"someDifferentNode"]
let tree =
let rec tree' s =
match s with
| 0 ->
Gen.map NodeName (Gen.elements nodeNames)
| n when n > 0 ->
let subtrees = Gen.sized <| fun s -> Gen.resize (s |> float |> sqrt |> int) (Gen.listOf (tree' (n / 2)))
Gen.oneof [
Gen.map NodeName (Gen.elements nodeNames)
Gen.map2 (fun name contents -> Container(name, contents)) (Gen.elements nodeNames) subtrees]
| _ -> invalidArg "s" "Size most be positive."
Gen.sized tree'
let treeToXDoc xmlTree =
let rec inner currentNode children =
let childMatch child =
match child with
| NodeName name ->
XElement(XName.Get name)
| Container (name, contents) ->
let element = XElement(XName.Get name)
inner element contents
currentNode.Add (List.map childMatch children |> List.toArray)
currentNode
match xmlTree with
| NodeName name ->
XDocument(XElement(XName.Get name))
| Container (name, contents) ->
let doc = XDocument(XElement(XName.Get name))
inner doc.Root contents |> ignore
doc
type XmlGenerator () =
static member XmlTree () =
{ new Arbitrary<XmlTree>() with
override x.Generator = tree
override x.Shrinker t =
match t with
| NodeName _ ->
Seq.empty
| Container (name, contents) ->
match contents with
| [] -> seq { yield NodeName name }
| c ->
seq { for n in c -> n } }
static member XDocument () =
{ new Arbitrary<XDocument>() with
override x.Generator = Gen.map treeToXDoc tree
override x.Shrinker t = Seq.empty }
Arb.register<XmlGenerator>() |> ignore
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment