Saturday, May 02, 2009

FsCheck -- a quick hack for bytes

This exceptionally trivial piece of FsCheck:

let popbyte (a: byte array) =
(a.[0], a.[1..])
let prop_popbyte (array:byte array) = array.Length < 1 or popbyte array = (array.[0], array.[1..])
quickCheck prop_popbyte
view raw gistfile1.fs hosted with ❤ by GitHub

surprised me by going Microsoft.FSharp.Core.FailureException : Geneflect: type not handled System.Byte. Especially so when the whole thing I was trying to write at the time was all about bytes, in arrays, in queues,...

So a little bit of diving into the FsCheck code later, a quick and dirty extension for handling bytes in Arbitrary.fs:

Later: now with fewer redundant parentheses and other clutter--

///Generate arbitrary byte in 0-n
static member Byte() =
{ new Arbitrary < byte >() with
override x.Arbitrary = sized <| fun n ->
(choose(0, if n > 255 then 255 else n)).Map byte
override x.CoArbitrary n = variant (if n >= (byte 0) then 2*(int n) else 2*( -(int n)) + 1)
override x.Shrink n =
let (|>|) x y = abs (int x) > abs (int y)
seq { if n < (byte 0) then yield byte(-(int n))
yield! Seq.map byte (Seq.unfold (fun st -> let st = st / 2 in Some (n - (byte st), st)) (int n)
|> Seq.cons (byte 0)
|> Seq.take_while ((|>|) n)) }
|> Seq.distinct
}
view raw gistfile1.fs hosted with ❤ by GitHub

which now gives Ok, passed 100 tests. which is what I had been wanting in the first place.

Instrumenting the function under test as

let popbyte (a: byte array) =
print_any a
(a.[0], a.[1..])
view raw gistfile1.fs hosted with ❤ by GitHub

shows a plausibly noisy set of inputs, so any remaining flaws will be subtle ones.

This example is believed to still be correct under the Feb 2010 CTP.

2 comments :

Kurt Schelfthout said...

Thanks Steve - FsCheck is currently indeed lacking some pretty important primitive generators (int64, float, long, uint come to mind, as well as byte, as you noticed).

Fortunately they're generally easy to write.

I'm sort of hoping that everyone that runs into this, posts or sends me generators. So thanks for stepping up, if you don't mind I'll add your byte generator to the FsCheck distribution.

Steve Gilham said...

Feel free! As the sidebar says "Code snippets released under the WTFPL".