src/Tools/quickcheck.ML
changeset 41155 7febf76e0a69
parent 41154 508c83827364
child 41156 1108529100ce
     1.1 --- a/src/Tools/quickcheck.ML	Fri Dec 03 08:40:47 2010 +0100
     1.2 +++ b/src/Tools/quickcheck.ML	Fri Dec 03 08:40:47 2010 +0100
     1.3 @@ -28,7 +28,7 @@
     1.4    val map_test_params : (typ list * expectation -> typ list * expectation)
     1.5      -> Context.generic -> Context.generic
     1.6    val add_generator:
     1.7 -    string * (Proof.context -> term -> int -> term list option * (bool list * bool))
     1.8 +    string * (Proof.context -> term -> int -> term list option * report option)
     1.9        -> Context.generic -> Context.generic
    1.10    (* testing terms and proof states *)
    1.11    val test_term: Proof.context -> bool -> term ->
    1.12 @@ -57,26 +57,10 @@
    1.13  
    1.14  (* quickcheck report *)
    1.15  
    1.16 -datatype single_report = Run of bool list * bool | MatchExc
    1.17 -
    1.18  datatype report = Report of
    1.19    { iterations : int, raised_match_errors : int,
    1.20      satisfied_assms : int list, positive_concl_tests : int }
    1.21  
    1.22 -fun collect_single_report single_report
    1.23 -    (Report {iterations = iterations, raised_match_errors = raised_match_errors,
    1.24 -    satisfied_assms = satisfied_assms, positive_concl_tests = positive_concl_tests}) =
    1.25 -  case single_report
    1.26 -  of MatchExc =>
    1.27 -    Report {iterations = iterations + 1, raised_match_errors = raised_match_errors + 1,
    1.28 -      satisfied_assms = satisfied_assms, positive_concl_tests = positive_concl_tests}
    1.29 -   | Run (assms, concl) =>
    1.30 -    Report {iterations = iterations + 1, raised_match_errors = raised_match_errors,
    1.31 -      satisfied_assms =
    1.32 -        map2 (fn b => fn s => if b then s + 1 else s) assms
    1.33 -         (if null satisfied_assms then replicate (length assms) 0 else satisfied_assms),
    1.34 -      positive_concl_tests = if concl then positive_concl_tests + 1 else positive_concl_tests}
    1.35 -
    1.36  (* expectation *)
    1.37  
    1.38  datatype expectation = No_Expectation | No_Counterexample | Counterexample; 
    1.39 @@ -116,7 +100,7 @@
    1.40  structure Data = Generic_Data
    1.41  (
    1.42    type T =
    1.43 -    (string * (Proof.context -> term -> int -> term list option * (bool list * bool))) list
    1.44 +    (string * (Proof.context -> term -> int -> term list option * report option)) list
    1.45        * test_params;
    1.46    val empty = ([], Test_Params {default_type = [], expect = No_Expectation});
    1.47    val extend = I;
    1.48 @@ -172,11 +156,6 @@
    1.49      val result = Exn.capture f ()
    1.50      val time = Time.toMilliseconds (#cpu (end_timing start))
    1.51    in (Exn.release result, (description, time)) end
    1.52 -
    1.53 -(* we actually assume we know the generators and its behaviour *)
    1.54 -fun is_iteratable "SML" = true
    1.55 -  | is_iteratable "random" = true
    1.56 -  | is_iteratable _ = false
    1.57    
    1.58  fun test_term ctxt is_interactive t =
    1.59    let
    1.60 @@ -185,30 +164,18 @@
    1.61      fun excipit s =
    1.62        "Quickcheck " ^ s ^ " while testing at size " ^ string_of_int (!current_size)
    1.63      val (test_fun, comp_time) = cpu_time "quickcheck compilation" (fn () => mk_tester ctxt t');
    1.64 -    fun iterate f 0 report = (NONE, report)
    1.65 -      | iterate f j report =
    1.66 +    fun with_size test_fun k reports =
    1.67 +      if k > Config.get ctxt size then
    1.68 +        (NONE, reports)
    1.69 +      else
    1.70          let
    1.71 -          val (test_result, single_report) = apsnd Run (f ()) handle Match => 
    1.72 -            (if Config.get ctxt quiet then ()
    1.73 -             else warning "Exception Match raised during quickcheck"; (NONE, MatchExc))
    1.74 -          val report = collect_single_report single_report report
    1.75 -        in
    1.76 -          case test_result of NONE => iterate f (j - 1) report | SOME q => (SOME q, report)
    1.77 -        end
    1.78 -    val empty_report = Report { iterations = 0, raised_match_errors = 0,
    1.79 -      satisfied_assms = [], positive_concl_tests = 0 }
    1.80 -    fun with_size test_fun k reports =
    1.81 -      if k > Config.get ctxt size then (NONE, reports)
    1.82 -      else
    1.83 -       (if Config.get ctxt quiet then () else Output.urgent_message ("Test data size: " ^ string_of_int k);
    1.84 -        let
    1.85 +          val _ = if Config.get ctxt quiet then () else Output.urgent_message
    1.86 +            ("Test data size: " ^ string_of_int k)
    1.87            val _ = current_size := k
    1.88 -          val niterations =
    1.89 -            if is_iteratable (Config.get ctxt tester) then Config.get ctxt iterations else 1
    1.90 -          val ((result, new_report), timing) = cpu_time ("size " ^ string_of_int k)
    1.91 -            (fn () => iterate (fn () => test_fun (k - 1)) niterations empty_report)
    1.92 -          val reports = ((k, new_report) :: reports)
    1.93 -        in case result of NONE => with_size test_fun (k + 1) reports | SOME q => (SOME q, reports) end);
    1.94 +          val ((result, new_report), timing) =
    1.95 +            cpu_time ("size " ^ string_of_int k) (fn () => test_fun (k - 1))
    1.96 +          val reports = case new_report of NONE => reports | SOME rep => (k, rep) :: reports
    1.97 +        in case result of NONE => with_size test_fun (k + 1) reports | SOME q => (SOME q, reports) end;
    1.98    in
    1.99      case test_fun of NONE => (NONE, ([comp_time], NONE)) 
   1.100        | SOME test_fun =>