Skip to content

Instantly share code, notes, and snippets.

@enricosada
Last active November 10, 2016 16:01
Show Gist options
  • Save enricosada/02558b8962511e33f56b9d3b31fe8a7b to your computer and use it in GitHub Desktop.
Save enricosada/02558b8962511e33f56b9d3b31fe8a7b to your computer and use it in GitHub Desktop.
.net project.json and pcl

Tested with dotnet --version

1.0.0-preview2-003131`

To run it:

  • dotnet restore
  • dotnet run

How to add pcl 259 to project.json:

From dotnet new -l fsharp template:

  • remove FSharp.Core.netcore package because we are going to use the one referenced (trasitive) by the PCL library
  • add Microsoft.NETCore.Portable.Compatibility package (used to shim mscorlib/bcl assemblies)
  • add import of pcl 259 target (portable-net45+win8+wp8+wpa81)
open FsCheck
open System
open System.Threading
open System.Reflection
open Microsoft.FSharp.Reflection
open Microsoft.FSharp.Collections
open System.Collections.Generic
open Prop
//init bug
let sizedString = Arb.generate<char> |> Gen.sample 10 10
//---too early initialization bug (put this first): fixed---
type Generators =
static member Int64() =
{ new Arbitrary<int64>() with
override x.Generator = Arb.generate<int> |> Gen.map int64 }
Arb.register<Generators>() |> ignore
//check that registering typeclass instances with a class that does not define any no longer fails silently
//type internal NoInstancesFails() =
// static member Int64() =
// { new Arbitrary<int64>() with
// override x.Arbitrary = arbitrary |> fmapGen int64 }
//overwriteGenerators<NoInstancesFails>()
type TestEnum =
| First = 0
| Second = 1
| Third = 2
let testEnum (e:TestEnum) = e = TestEnum.First
Check.Quick testEnum
//bug: exception escapes: fixed
let prop_EscapingException (x:int) =
if x=0 then lazy (failwith "nul") else lazy true
|> label "bla"
Check.Verbose prop_EscapingException
//more escaping exceptions?
let somefailingFunction() = failwith "escaped"
let prop_EscapingException2 (x:int) =
x <> 0 ==> lazy (if x=0 then false else (somefailingFunction()))
Check.Quick prop_EscapingException2
//bug: label not printed because of exception. Workaround: use lazy.
//actually I don't hink this is fixable, as the exception rolls up the stack, so the labelling
//that happens when a property "returns" gets bypassed.
//this is irritating when using Assert statements from unit testing frameworks though.
let prop_LabelBug (x:int) =
if x=0 then lazy (failwith "nul") else lazy true
|> label "bla"
Check.Quick prop_LabelBug
//smart shrinking
[<StructuredFormatDisplay("{Display}")>]
type Smart<'a> =
Smart of int * 'a with
override x.ToString() = match x with Smart (_,a) -> sprintf "%A" a
member x.Display = x.ToString()
type SmartShrinker =
static member Smart() =
{ new Arbitrary<Smart<'a>>() with
override x.Generator = Arb.generate |> Gen.map (fun arb -> Smart (0,arb))
override x.Shrinker (Smart (i,x)) =
let ys = Seq.zip {0..Int32.MaxValue} (Arb.shrink x) |> Seq.map Smart
let i' = Math.Max(0,i-2)
let rec interleave left right =
match (left,right) with
| ([],rs) -> rs
| (ls,[]) -> ls
| (l::ls,r::rs) -> l::r::(interleave ls rs)
interleave (Seq.take i' ys |> Seq.toList) (Seq.skip i' ys |> Seq.toList) |> List.toSeq
}
Arb.register<SmartShrinker>() |> ignore
let smartShrink (Smart (_,i)) = i < 20
Check.Quick smartShrink
//-------------examples from QuickCheck paper-------------
let prop_RevUnit (x:char) = List.rev [x] = [x]
let prop_RevApp (x:string) xs =
List.rev (x::xs) = List.rev xs @ [x]
|> trivial (xs = [])
|> trivial (xs.Length = 1)
let prop_MaxLe (x:float) y = (x <= y) ==> (lazy (max x y = y))
//----------various examples-------------------------------
//convoluted property, but shows the power of the combinators: it's no problem to return
//functions that return properties.
Check.Quick (fun b y (x:char,z) -> if b then (fun q -> y+1 = z + int q) else (fun q -> q =10.0))
//arrays
let prop_RevRevArr (xs:int[]) = Array.rev(Array.rev xs) = xs
Check.Quick prop_RevRevArr
let prop_RevRevArr2 (xs:int[][]) = xs.Rank = 1
Check.Quick prop_RevRevArr2
Check.Quick (fun (arr:int[]) -> Array.rev arr = arr)
type ARecord = { XPos : int; YPos : int; Name: string }
Check.Quick (fun (record:ARecord) -> (record.XPos > 0 && record.YPos > 0) ==> lazy (record.XPos * record.YPos > 0))
Check.Quick (fun (a:int,b,c,d:int,e,f) (g,h,i) -> a > b && b > c && d > e && f > g && e > f && h > i && a > i)
type ADisc =
| First of int
| Second of char
| Third of ADisc
| Fourth of ADisc[]
Check.Quick (fun (d:ADisc) -> match d with First i -> i = 2 | Second c -> true | Third _ -> true | Fourth _ -> raise <| InvalidOperationException())
type Properties =
static member Test1 (b,(b2:bool)) = (b = b2)
static member Test2 i = (i < 100)
static member Test3 (i,j) = (i < 10 && j < 5.1)
//static member Test4 l = List.rev l = l //generic args no longer work in Check.QuickAll
static member Test5 (l:list<float>) = List.rev l = l
//this property is falsifiable: sometimes the generator for float generates nan; and nan <> nan
//so when checking the reverse of the reverse list's equality with the original list, the check fails.
static member Test6 (l:list<list<int*int> * float>) = ((l |> List.rev |> List.rev) = l) |> trivial (List.length l = 0)
static member Test7 (a:int*bool,b:float*int) = (fst a = snd b)
static member Test8 (l:list<obj>) = ( List.rev l = l)
static member Test9 (s:string) = ( new String(s.ToCharArray()) = s )
static member Test10 i = (i = 'r')
static member NoTest i = "30"
static member OptionTest (o:option<int>) = match o with Some _ -> false | _ -> true
Check.QuickAll<Properties>()
//-----------ReflectArbitrary tests------------------------
//a record type containing an array type
type List<'a> = {list : 'a[]}
//a recursive union type containing a record type
type Tree<'a> =
| Leaf of string
| Branch of List<Tree<'a>>
let rec xmlSafeTree (x : Tree<string>) =
match x with
| Leaf x -> not (x.StartsWith " " && x.EndsWith " ")
| Branch xs -> Array.forall xmlSafeTree xs.list
let product (x:int,y:int) = (x > 0 && y > 0) ==> (x*y > 0)
let revString (x : string) =
let cs = x.ToCharArray()
Array.Reverse cs
new String(cs)
let revRevString x = revString (revString x) = x
let private idempotent f x = let y = f x in f y = y
Check.Quick (idempotent (fun (x : string) -> x.ToUpper()))
let bigTuple (a:bool,b:float,c:string,d:char,e:byte,f:float,g:string,h:option<float>,i) = if i > 10 then false else true
Check.Quick("bigTuple",bigTuple)
//-----property combinators------------------
let private withPositiveInteger (p : int -> 'a) = fun n -> n <> 0 ==> lazy (p (abs n))
let testProp = withPositiveInteger ( fun x -> x > 0 |> classify true "bla" )
Check.Quick testProp
let testProp2 = withPositiveInteger ( fun x -> withPositiveInteger (fun y -> x + y > 0 ))
Check.Quick testProp2
let blah (s:string) = if s = "" then raise (new System.Exception("foo")) else s.Length > 3
let private withNonEmptyString (p : string -> 'a) = forAll (Gen.elements [ "A"; "AA"; "AAA" ] |> Arb.fromGen) p
Check.Quick (withNonEmptyString blah)
let prop_Exc = forAll (Arb.fromGenShrink(Gen.resize 100 Arb.generate,Arb.shrink)) (fun (s:string) -> failwith "error")
Check.Quick("prop_Exc",prop_Exc)
//-----------------test reflective shrinking--------
type RecordStuff<'a> = { Yes:bool; Name:'a; NogIets:list<int*char> }
let bigSize = { Config.Quick with StartSize = 100; EndSize = 100 }
Check.One(bigSize,fun (s:RecordStuff<string>) -> s.Yes)
type Recursive<'a> = Void | Leaf of 'a | Branch of Recursive<'a> * 'a * Recursive<'a>
Check.One(bigSize,fun (s:Recursive<string>) -> match s with Branch _ -> false | _ -> true)
type Simple = Void | Void2 | Void3 | Leaf of int | Leaf2 of string * int *char * float
//should yield a simplified Leaf2
Check.One(bigSize,fun (s:Simple) -> match s with Leaf2 _ -> false | _ -> true)
//should yield a Void3
Check.One(bigSize,fun (s:Simple) -> match s with Leaf2 _ -> false | Void3 -> false | _ -> true)
Check.One(bigSize,fun i -> (-10 < i && i < 0) || (0 < i) && (i < 10 ))
Check.Quick (fun opt -> match opt with None -> false | Some b -> b )
Check.Quick (fun opt -> match opt with Some n when n<0 -> false | Some n when n >= 0 -> true | _ -> true )
let prop_RevId' (xs:list<int>) (x:int) = if (xs.Length > 2) && (x >10) then false else true
Check.Quick prop_RevId'
//----------Checking toplevel properties trick------------------
Console.WriteLine("----------Check all toplevel properties----------------");
type Marker = class end
Check.QuickAll (typeof<Marker>.DeclaringType)
Console.ReadKey() |> ignore
{
"version": "1.0.0-*",
"buildOptions": {
"debugType": "portable",
"emitEntryPoint": true,
"compilerName": "fsc",
"compile": {
"includeFiles": [
"Program.fs"
]
}
},
"tools": {
"dotnet-compile-fsc":"1.0.0-preview2-*"
},
"frameworks": {
"netcoreapp1.0": {
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.1"
},
"FsCheck": "2.6.2",
"Microsoft.NETCore.Portable.Compatibility": "1.0.1"
},
"imports": [ "portable-net45+win8+wp8+wpa81" ]
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment