src/Tools/quickcheck.ML
author nipkow
Tue, 21 Dec 2010 08:38:03 +0100
changeset 41341 e65a122057ad
parent 41086 b4cccce25d9a
child 41472 f6ab14e61604
permissions -rw-r--r--
merged
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
30824
bc6b24882834 fixed header;
wenzelm
parents: 30473
diff changeset
     1
(*  Title:      Tools/quickcheck.ML
40246
c03fc7d3fa97 changed global fixed timeout to a configurable timeout for quickcheck; test parameters in quickcheck are now fully passed around with the context
bulwahn
parents: 40225
diff changeset
     2
    Author:     Stefan Berghofer, Florian Haftmann, Lukas Bulwahn, TU Muenchen
28256
4e7f7d52f855 added quickcheck.ML
haftmann
parents:
diff changeset
     3
4e7f7d52f855 added quickcheck.ML
haftmann
parents:
diff changeset
     4
Generic counterexample search engine.
4e7f7d52f855 added quickcheck.ML
haftmann
parents:
diff changeset
     5
*)
4e7f7d52f855 added quickcheck.ML
haftmann
parents:
diff changeset
     6
4e7f7d52f855 added quickcheck.ML
haftmann
parents:
diff changeset
     7
signature QUICKCHECK =
4e7f7d52f855 added quickcheck.ML
haftmann
parents:
diff changeset
     8
sig
37910
555287ba8d8d reordering quickcheck signature; exporting test_params and inspection function
bulwahn
parents: 37909
diff changeset
     9
  val setup: theory -> theory
555287ba8d8d reordering quickcheck signature; exporting test_params and inspection function
bulwahn
parents: 37909
diff changeset
    10
  (* configuration *)
32740
9dd0a2f83429 explicit indication of Unsynchronized.ref;
wenzelm
parents: 32297
diff changeset
    11
  val auto: bool Unsynchronized.ref
34948
2d5f2a9f7601 refactoring the predicate compiler; adding theories for Sequences; adding retrieval to Spec_Rules; adding timing to Quickcheck
bulwahn
parents: 34128
diff changeset
    12
  val timing : bool Unsynchronized.ref
40908
e8806880819e adding configuration quickcheck_tester
bulwahn
parents: 40906
diff changeset
    13
  val tester : string Config.T 
40644
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
    14
  val size : int Config.T
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
    15
  val iterations : int Config.T
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
    16
  val no_assms : bool Config.T
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
    17
  val report : bool Config.T
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
    18
  val quiet : bool Config.T
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
    19
  val timeout : real Config.T
40648
1598ec648b0d splitting test_goal function in two functions; exporting new configurations in quickcheck; iterations depend on generator_name in quickcheck
bulwahn
parents: 40647
diff changeset
    20
  val finite_types : bool Config.T
1598ec648b0d splitting test_goal function in two functions; exporting new configurations in quickcheck; iterations depend on generator_name in quickcheck
bulwahn
parents: 40647
diff changeset
    21
  val finite_type_size : int Config.T
35378
95d0e3adf38e added basic reporting of test cases to quickcheck
bulwahn
parents: 35324
diff changeset
    22
  datatype report = Report of
95d0e3adf38e added basic reporting of test cases to quickcheck
bulwahn
parents: 35324
diff changeset
    23
    { iterations : int, raised_match_errors : int,
95d0e3adf38e added basic reporting of test cases to quickcheck
bulwahn
parents: 35324
diff changeset
    24
      satisfied_assms : int list, positive_concl_tests : int }
40644
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
    25
  datatype expectation = No_Expectation | No_Counterexample | Counterexample;  
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
    26
  datatype test_params = Test_Params of {default_type: typ list, expect : expectation};
40246
c03fc7d3fa97 changed global fixed timeout to a configurable timeout for quickcheck; test parameters in quickcheck are now fully passed around with the context
bulwahn
parents: 40225
diff changeset
    27
  val test_params_of : Proof.context -> test_params
40644
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
    28
  val map_test_params : (typ list * expectation -> typ list * expectation)
40246
c03fc7d3fa97 changed global fixed timeout to a configurable timeout for quickcheck; test parameters in quickcheck are now fully passed around with the context
bulwahn
parents: 40225
diff changeset
    29
    -> Context.generic -> Context.generic
37910
555287ba8d8d reordering quickcheck signature; exporting test_params and inspection function
bulwahn
parents: 37909
diff changeset
    30
  val add_generator:
40911
7febf76e0a69 moving iteration of tests to the testers in quickcheck
bulwahn
parents: 40910
diff changeset
    31
    string * (Proof.context -> term -> int -> term list option * report option)
39252
8f176e575a49 changing the container for the quickcheck options to a generic data
bulwahn
parents: 39138
diff changeset
    32
      -> Context.generic -> Context.generic
37910
555287ba8d8d reordering quickcheck signature; exporting test_params and inspection function
bulwahn
parents: 37909
diff changeset
    33
  (* testing terms and proof states *)
40909
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
    34
  val test_term: Proof.context -> bool -> term ->
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
    35
    (string * term) list option * ((string * int) list * ((int * report) list) option)
40648
1598ec648b0d splitting test_goal function in two functions; exporting new configurations in quickcheck; iterations depend on generator_name in quickcheck
bulwahn
parents: 40647
diff changeset
    36
  val test_goal_terms:
40909
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
    37
    Proof.context -> bool -> (string * typ) list -> term list
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
    38
      -> (string * term) list option * ((string * int) list * ((int * report) list) option) list
37909
583543ad6ad1 changed default types to a list of types; extended quickcheck parameters to be a list of values to parse a list of default types
bulwahn
parents: 36960
diff changeset
    39
  val quickcheck: (string * string list) list -> int -> Proof.state -> (string * term) list option
28256
4e7f7d52f855 added quickcheck.ML
haftmann
parents:
diff changeset
    40
end;
4e7f7d52f855 added quickcheck.ML
haftmann
parents:
diff changeset
    41
4e7f7d52f855 added quickcheck.ML
haftmann
parents:
diff changeset
    42
structure Quickcheck : QUICKCHECK =
4e7f7d52f855 added quickcheck.ML
haftmann
parents:
diff changeset
    43
struct
4e7f7d52f855 added quickcheck.ML
haftmann
parents:
diff changeset
    44
30980
fe0855471964 misc cleanup of auto_solve and quickcheck:
wenzelm
parents: 30973
diff changeset
    45
(* preferences *)
fe0855471964 misc cleanup of auto_solve and quickcheck:
wenzelm
parents: 30973
diff changeset
    46
32740
9dd0a2f83429 explicit indication of Unsynchronized.ref;
wenzelm
parents: 32297
diff changeset
    47
val auto = Unsynchronized.ref false;
30980
fe0855471964 misc cleanup of auto_solve and quickcheck:
wenzelm
parents: 30973
diff changeset
    48
34948
2d5f2a9f7601 refactoring the predicate compiler; adding theories for Sequences; adding retrieval to Spec_Rules; adding timing to Quickcheck
bulwahn
parents: 34128
diff changeset
    49
val timing = Unsynchronized.ref false;
2d5f2a9f7601 refactoring the predicate compiler; adding theories for Sequences; adding retrieval to Spec_Rules; adding timing to Quickcheck
bulwahn
parents: 34128
diff changeset
    50
30980
fe0855471964 misc cleanup of auto_solve and quickcheck:
wenzelm
parents: 30973
diff changeset
    51
val _ =
fe0855471964 misc cleanup of auto_solve and quickcheck:
wenzelm
parents: 30973
diff changeset
    52
  ProofGeneralPgip.add_preference Preferences.category_tracing
39616
8052101883c3 renamed setmp_noncritical to Unsynchronized.setmp to emphasize its meaning;
wenzelm
parents: 39329
diff changeset
    53
  (Unsynchronized.setmp auto true (fn () =>
30980
fe0855471964 misc cleanup of auto_solve and quickcheck:
wenzelm
parents: 30973
diff changeset
    54
    Preferences.bool_pref auto
fe0855471964 misc cleanup of auto_solve and quickcheck:
wenzelm
parents: 30973
diff changeset
    55
      "auto-quickcheck"
39329
0a85f960ac50 make Auto Solve part of the "Auto Tools"
blanchet
parents: 39324
diff changeset
    56
      "Run Quickcheck automatically.") ());
30980
fe0855471964 misc cleanup of auto_solve and quickcheck:
wenzelm
parents: 30973
diff changeset
    57
35378
95d0e3adf38e added basic reporting of test cases to quickcheck
bulwahn
parents: 35324
diff changeset
    58
(* quickcheck report *)
95d0e3adf38e added basic reporting of test cases to quickcheck
bulwahn
parents: 35324
diff changeset
    59
95d0e3adf38e added basic reporting of test cases to quickcheck
bulwahn
parents: 35324
diff changeset
    60
datatype report = Report of
95d0e3adf38e added basic reporting of test cases to quickcheck
bulwahn
parents: 35324
diff changeset
    61
  { iterations : int, raised_match_errors : int,
95d0e3adf38e added basic reporting of test cases to quickcheck
bulwahn
parents: 35324
diff changeset
    62
    satisfied_assms : int list, positive_concl_tests : int }
95d0e3adf38e added basic reporting of test cases to quickcheck
bulwahn
parents: 35324
diff changeset
    63
37929
22e0797857e6 adding checking of expected result for the tool quickcheck; annotated a few quickcheck examples
bulwahn
parents: 37913
diff changeset
    64
(* expectation *)
22e0797857e6 adding checking of expected result for the tool quickcheck; annotated a few quickcheck examples
bulwahn
parents: 37913
diff changeset
    65
22e0797857e6 adding checking of expected result for the tool quickcheck; annotated a few quickcheck examples
bulwahn
parents: 37913
diff changeset
    66
datatype expectation = No_Expectation | No_Counterexample | Counterexample; 
22e0797857e6 adding checking of expected result for the tool quickcheck; annotated a few quickcheck examples
bulwahn
parents: 37913
diff changeset
    67
22e0797857e6 adding checking of expected result for the tool quickcheck; annotated a few quickcheck examples
bulwahn
parents: 37913
diff changeset
    68
fun merge_expectation (expect1, expect2) =
22e0797857e6 adding checking of expected result for the tool quickcheck; annotated a few quickcheck examples
bulwahn
parents: 37913
diff changeset
    69
  if expect1 = expect2 then expect1 else No_Expectation
22e0797857e6 adding checking of expected result for the tool quickcheck; annotated a few quickcheck examples
bulwahn
parents: 37913
diff changeset
    70
28315
d3cf88fe77bc generic quickcheck framework
haftmann
parents: 28309
diff changeset
    71
(* quickcheck configuration -- default parameters, test generators *)
40908
e8806880819e adding configuration quickcheck_tester
bulwahn
parents: 40906
diff changeset
    72
val (tester, setup_tester) = Attrib.config_string "quickcheck_tester" (K "")
40644
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
    73
val (size, setup_size) = Attrib.config_int "quickcheck_size" (K 10)
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
    74
val (iterations, setup_iterations) = Attrib.config_int "quickcheck_iterations" (K 100)
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
    75
val (no_assms, setup_no_assms) = Attrib.config_bool "quickcheck_no_assms" (K false)
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
    76
val (report, setup_report) = Attrib.config_bool "quickcheck_report" (K true)
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
    77
val (quiet, setup_quiet) = Attrib.config_bool "quickcheck_quiet" (K false)
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
    78
val (timeout, setup_timeout) = Attrib.config_real "quickcheck_timeout" (K 30.0)
40646
3dfa41e89738 adding option finite_types to quickcheck
bulwahn
parents: 40644
diff changeset
    79
val (finite_types, setup_finite_types) = Attrib.config_bool "quickcheck_finite_types" (K true)
40647
6e92ca8e981b adding prototype for finite_type instantiations
bulwahn
parents: 40646
diff changeset
    80
val (finite_type_size, setup_finite_type_size) = Attrib.config_int "quickcheck_finite_type_size" (K 3)
38759
37a9092de102 simplification/standardization of some theory data;
wenzelm
parents: 38390
diff changeset
    81
40644
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
    82
val setup_config =
40908
e8806880819e adding configuration quickcheck_tester
bulwahn
parents: 40906
diff changeset
    83
  setup_tester #> setup_size #> setup_iterations #> setup_no_assms #> setup_report #> setup_quiet
e8806880819e adding configuration quickcheck_tester
bulwahn
parents: 40906
diff changeset
    84
    #> setup_timeout #> setup_finite_types #> setup_finite_type_size
40646
3dfa41e89738 adding option finite_types to quickcheck
bulwahn
parents: 40644
diff changeset
    85
40644
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
    86
datatype test_params = Test_Params of
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
    87
  {default_type: typ list, expect : expectation};
38759
37a9092de102 simplification/standardization of some theory data;
wenzelm
parents: 38390
diff changeset
    88
40644
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
    89
fun dest_test_params (Test_Params {default_type, expect}) = (default_type, expect);
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
    90
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
    91
fun make_test_params (default_type, expect) = Test_Params {default_type = default_type, expect = expect};
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
    92
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
    93
fun map_test_params' f (Test_Params {default_type, expect}) = make_test_params (f (default_type, expect));
38759
37a9092de102 simplification/standardization of some theory data;
wenzelm
parents: 38390
diff changeset
    94
37a9092de102 simplification/standardization of some theory data;
wenzelm
parents: 38390
diff changeset
    95
fun merge_test_params
40644
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
    96
 (Test_Params {default_type = default_type1, expect = expect1},
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
    97
  Test_Params {default_type = default_type2, expect = expect2}) =
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
    98
  make_test_params (merge (op =) (default_type1, default_type2), merge_expectation (expect1, expect2));
28309
c24bc53c815c some steps towards generic quickcheck framework
haftmann
parents: 28256
diff changeset
    99
39252
8f176e575a49 changing the container for the quickcheck options to a generic data
bulwahn
parents: 39138
diff changeset
   100
structure Data = Generic_Data
33522
737589bb9bb8 adapted Theory_Data;
wenzelm
parents: 33291
diff changeset
   101
(
38759
37a9092de102 simplification/standardization of some theory data;
wenzelm
parents: 38390
diff changeset
   102
  type T =
40911
7febf76e0a69 moving iteration of tests to the testers in quickcheck
bulwahn
parents: 40910
diff changeset
   103
    (string * (Proof.context -> term -> int -> term list option * report option)) list
38759
37a9092de102 simplification/standardization of some theory data;
wenzelm
parents: 38390
diff changeset
   104
      * test_params;
40644
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
   105
  val empty = ([], Test_Params {default_type = [], expect = No_Expectation});
28256
4e7f7d52f855 added quickcheck.ML
haftmann
parents:
diff changeset
   106
  val extend = I;
33522
737589bb9bb8 adapted Theory_Data;
wenzelm
parents: 33291
diff changeset
   107
  fun merge ((generators1, params1), (generators2, params2)) : T =
737589bb9bb8 adapted Theory_Data;
wenzelm
parents: 33291
diff changeset
   108
    (AList.merge (op =) (K true) (generators1, generators2),
28309
c24bc53c815c some steps towards generic quickcheck framework
haftmann
parents: 28256
diff changeset
   109
      merge_test_params (params1, params2));
33522
737589bb9bb8 adapted Theory_Data;
wenzelm
parents: 33291
diff changeset
   110
);
28256
4e7f7d52f855 added quickcheck.ML
haftmann
parents:
diff changeset
   111
39252
8f176e575a49 changing the container for the quickcheck options to a generic data
bulwahn
parents: 39138
diff changeset
   112
val test_params_of = snd o Data.get o Context.Proof;
37910
555287ba8d8d reordering quickcheck signature; exporting test_params and inspection function
bulwahn
parents: 37909
diff changeset
   113
40644
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
   114
val default_type = fst o dest_test_params o test_params_of
40246
c03fc7d3fa97 changed global fixed timeout to a configurable timeout for quickcheck; test parameters in quickcheck are now fully passed around with the context
bulwahn
parents: 40225
diff changeset
   115
40644
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
   116
val expect = snd o dest_test_params o test_params_of
40246
c03fc7d3fa97 changed global fixed timeout to a configurable timeout for quickcheck; test parameters in quickcheck are now fully passed around with the context
bulwahn
parents: 40225
diff changeset
   117
c03fc7d3fa97 changed global fixed timeout to a configurable timeout for quickcheck; test parameters in quickcheck are now fully passed around with the context
bulwahn
parents: 40225
diff changeset
   118
val map_test_params = Data.map o apsnd o map_test_params'
39253
0c47d615a69b removing report from the arguments of the quickcheck functions and refering to it by picking it from the context
bulwahn
parents: 39252
diff changeset
   119
28309
c24bc53c815c some steps towards generic quickcheck framework
haftmann
parents: 28256
diff changeset
   120
val add_generator = Data.map o apfst o AList.update (op =);
c24bc53c815c some steps towards generic quickcheck framework
haftmann
parents: 28256
diff changeset
   121
28315
d3cf88fe77bc generic quickcheck framework
haftmann
parents: 28309
diff changeset
   122
(* generating tests *)
d3cf88fe77bc generic quickcheck framework
haftmann
parents: 28309
diff changeset
   123
40909
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   124
fun mk_tester ctxt t =
28309
c24bc53c815c some steps towards generic quickcheck framework
haftmann
parents: 28256
diff changeset
   125
  let
40909
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   126
    val name = Config.get ctxt tester
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   127
    val tester = case AList.lookup (op =) ((fst o Data.get o Context.Proof) ctxt) name
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   128
      of NONE => error ("No such quickcheck tester: " ^ name)
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   129
      | SOME tester => tester ctxt;
40235
87998864284e use Exn.interruptible_capture to keep user-code interruptible (Exn.capture not immediately followed by Exn.release here);
wenzelm
parents: 40225
diff changeset
   130
  in
40909
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   131
    if Config.get ctxt quiet then
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   132
      try tester t
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   133
    else
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   134
      let
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   135
        val tester = Exn.interruptible_capture tester t
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   136
      in case Exn.get_result tester of
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   137
          NONE => SOME (Exn.release tester)
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   138
        | SOME tester => SOME tester
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   139
      end
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   140
  end
28315
d3cf88fe77bc generic quickcheck framework
haftmann
parents: 28309
diff changeset
   141
d3cf88fe77bc generic quickcheck framework
haftmann
parents: 28309
diff changeset
   142
(* testing propositions *)
d3cf88fe77bc generic quickcheck framework
haftmann
parents: 28309
diff changeset
   143
28309
c24bc53c815c some steps towards generic quickcheck framework
haftmann
parents: 28256
diff changeset
   144
fun prep_test_term t =
c24bc53c815c some steps towards generic quickcheck framework
haftmann
parents: 28256
diff changeset
   145
  let
29266
4a478f9d2847 use regular Term.add_vars, Term.add_frees etc.;
wenzelm
parents: 28952
diff changeset
   146
    val _ = (null (Term.add_tvars t []) andalso null (Term.add_tfrees t [])) orelse
28309
c24bc53c815c some steps towards generic quickcheck framework
haftmann
parents: 28256
diff changeset
   147
      error "Term to be tested contains type variables";
29266
4a478f9d2847 use regular Term.add_vars, Term.add_frees etc.;
wenzelm
parents: 28952
diff changeset
   148
    val _ = null (Term.add_vars t []) orelse
28309
c24bc53c815c some steps towards generic quickcheck framework
haftmann
parents: 28256
diff changeset
   149
      error "Term to be tested contains schematic variables";
31138
a51ce445d498 dropped legacy operations
haftmann
parents: 30980
diff changeset
   150
    val frees = Term.add_frees t [];
41086
b4cccce25d9a if only finite types and no real datatypes occur in the quantifiers only enumerate cardinality not size in quickcheck
bulwahn
parents: 41043
diff changeset
   151
  in (frees, list_abs_free (frees, t)) end
28256
4e7f7d52f855 added quickcheck.ML
haftmann
parents:
diff changeset
   152
35324
c9f428269b38 adopting mutabelle and quickcheck to return timing information; exporting make_case_combs in datatype package for predicate compiler; adding Spec_Rules declaration for tail recursive functions; improving the predicate compiler and function flattening
bulwahn
parents: 35077
diff changeset
   153
fun cpu_time description f =
c9f428269b38 adopting mutabelle and quickcheck to return timing information; exporting make_case_combs in datatype package for predicate compiler; adding Spec_Rules declaration for tail recursive functions; improving the predicate compiler and function flattening
bulwahn
parents: 35077
diff changeset
   154
  let
c9f428269b38 adopting mutabelle and quickcheck to return timing information; exporting make_case_combs in datatype package for predicate compiler; adding Spec_Rules declaration for tail recursive functions; improving the predicate compiler and function flattening
bulwahn
parents: 35077
diff changeset
   155
    val start = start_timing ()
c9f428269b38 adopting mutabelle and quickcheck to return timing information; exporting make_case_combs in datatype package for predicate compiler; adding Spec_Rules declaration for tail recursive functions; improving the predicate compiler and function flattening
bulwahn
parents: 35077
diff changeset
   156
    val result = Exn.capture f ()
c9f428269b38 adopting mutabelle and quickcheck to return timing information; exporting make_case_combs in datatype package for predicate compiler; adding Spec_Rules declaration for tail recursive functions; improving the predicate compiler and function flattening
bulwahn
parents: 35077
diff changeset
   157
    val time = Time.toMilliseconds (#cpu (end_timing start))
c9f428269b38 adopting mutabelle and quickcheck to return timing information; exporting make_case_combs in datatype package for predicate compiler; adding Spec_Rules declaration for tail recursive functions; improving the predicate compiler and function flattening
bulwahn
parents: 35077
diff changeset
   158
  in (Exn.release result, (description, time)) end
40648
1598ec648b0d splitting test_goal function in two functions; exporting new configurations in quickcheck; iterations depend on generator_name in quickcheck
bulwahn
parents: 40647
diff changeset
   159
  
40909
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   160
fun test_term ctxt is_interactive t =
28309
c24bc53c815c some steps towards generic quickcheck framework
haftmann
parents: 28256
diff changeset
   161
  let
41086
b4cccce25d9a if only finite types and no real datatypes occur in the quantifiers only enumerate cardinality not size in quickcheck
bulwahn
parents: 41043
diff changeset
   162
    val (names, t') = apfst (map fst) (prep_test_term t);
40366
a2866dbfbe6b changing timeout to real value; handling Interrupt and Timeout more like nitpick does
bulwahn
parents: 40253
diff changeset
   163
    val current_size = Unsynchronized.ref 0
a2866dbfbe6b changing timeout to real value; handling Interrupt and Timeout more like nitpick does
bulwahn
parents: 40253
diff changeset
   164
    fun excipit s =
a2866dbfbe6b changing timeout to real value; handling Interrupt and Timeout more like nitpick does
bulwahn
parents: 40253
diff changeset
   165
      "Quickcheck " ^ s ^ " while testing at size " ^ string_of_int (!current_size)
40909
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   166
    val (test_fun, comp_time) = cpu_time "quickcheck compilation" (fn () => mk_tester ctxt t');
40911
7febf76e0a69 moving iteration of tests to the testers in quickcheck
bulwahn
parents: 40910
diff changeset
   167
    fun with_size test_fun k reports =
7febf76e0a69 moving iteration of tests to the testers in quickcheck
bulwahn
parents: 40910
diff changeset
   168
      if k > Config.get ctxt size then
7febf76e0a69 moving iteration of tests to the testers in quickcheck
bulwahn
parents: 40910
diff changeset
   169
        (NONE, reports)
7febf76e0a69 moving iteration of tests to the testers in quickcheck
bulwahn
parents: 40910
diff changeset
   170
      else
35378
95d0e3adf38e added basic reporting of test cases to quickcheck
bulwahn
parents: 35324
diff changeset
   171
        let
40911
7febf76e0a69 moving iteration of tests to the testers in quickcheck
bulwahn
parents: 40910
diff changeset
   172
          val _ = if Config.get ctxt quiet then () else Output.urgent_message
7febf76e0a69 moving iteration of tests to the testers in quickcheck
bulwahn
parents: 40910
diff changeset
   173
            ("Test data size: " ^ string_of_int k)
40648
1598ec648b0d splitting test_goal function in two functions; exporting new configurations in quickcheck; iterations depend on generator_name in quickcheck
bulwahn
parents: 40647
diff changeset
   174
          val _ = current_size := k
40911
7febf76e0a69 moving iteration of tests to the testers in quickcheck
bulwahn
parents: 40910
diff changeset
   175
          val ((result, new_report), timing) =
7febf76e0a69 moving iteration of tests to the testers in quickcheck
bulwahn
parents: 40910
diff changeset
   176
            cpu_time ("size " ^ string_of_int k) (fn () => test_fun (k - 1))
7febf76e0a69 moving iteration of tests to the testers in quickcheck
bulwahn
parents: 40910
diff changeset
   177
          val reports = case new_report of NONE => reports | SOME rep => (k, rep) :: reports
7febf76e0a69 moving iteration of tests to the testers in quickcheck
bulwahn
parents: 40910
diff changeset
   178
        in case result of NONE => with_size test_fun (k + 1) reports | SOME q => (SOME q, reports) end;
34948
2d5f2a9f7601 refactoring the predicate compiler; adding theories for Sequences; adding retrieval to Spec_Rules; adding timing to Quickcheck
bulwahn
parents: 34128
diff changeset
   179
  in
40909
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   180
    case test_fun of NONE => (NONE, ([comp_time], NONE)) 
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   181
      | SOME test_fun =>
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   182
        TimeLimit.timeLimit (seconds (Config.get ctxt timeout)) (fn () =>
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   183
          let
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   184
            val ((result, reports), exec_time) =
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   185
              cpu_time "quickcheck execution" (fn () => with_size test_fun 1 [])
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   186
          in
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   187
            (case result of NONE => NONE | SOME ts => SOME (names ~~ ts),
40916
9928083506b6 improving presentation of quickcheck reports
bulwahn
parents: 40912
diff changeset
   188
              ([exec_time, comp_time],
9928083506b6 improving presentation of quickcheck reports
bulwahn
parents: 40912
diff changeset
   189
               if Config.get ctxt report andalso not (null reports) then SOME reports else NONE))
40909
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   190
          end) ()
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   191
        handle TimeLimit.TimeOut =>
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   192
          if is_interactive then error (excipit "ran out of time") else raise TimeLimit.TimeOut
28309
c24bc53c815c some steps towards generic quickcheck framework
haftmann
parents: 28256
diff changeset
   193
  end;
c24bc53c815c some steps towards generic quickcheck framework
haftmann
parents: 28256
diff changeset
   194
41086
b4cccce25d9a if only finite types and no real datatypes occur in the quantifiers only enumerate cardinality not size in quickcheck
bulwahn
parents: 41043
diff changeset
   195
(* FIXME: this function shows that many assumptions are made upon the generation *)
b4cccce25d9a if only finite types and no real datatypes occur in the quantifiers only enumerate cardinality not size in quickcheck
bulwahn
parents: 41043
diff changeset
   196
(* In the end there is probably no generic quickcheck interface left... *)
b4cccce25d9a if only finite types and no real datatypes occur in the quantifiers only enumerate cardinality not size in quickcheck
bulwahn
parents: 41043
diff changeset
   197
41043
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   198
fun test_term_with_increasing_cardinality ctxt is_interactive ts =
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   199
  let
41086
b4cccce25d9a if only finite types and no real datatypes occur in the quantifiers only enumerate cardinality not size in quickcheck
bulwahn
parents: 41043
diff changeset
   200
    val thy = ProofContext.theory_of ctxt
b4cccce25d9a if only finite types and no real datatypes occur in the quantifiers only enumerate cardinality not size in quickcheck
bulwahn
parents: 41043
diff changeset
   201
    val (freess, ts') = split_list (map prep_test_term ts)
b4cccce25d9a if only finite types and no real datatypes occur in the quantifiers only enumerate cardinality not size in quickcheck
bulwahn
parents: 41043
diff changeset
   202
    val Ts = map snd (hd freess)
41043
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   203
    val (test_funs, comp_time) = cpu_time "quickcheck compilation"
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   204
      (fn () => map (mk_tester ctxt) ts')
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   205
    fun test_card_size (card, size) =
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   206
      (* FIXME: why decrement size by one? *)
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   207
      case fst (the (nth test_funs (card - 1)) (size - 1)) of
41086
b4cccce25d9a if only finite types and no real datatypes occur in the quantifiers only enumerate cardinality not size in quickcheck
bulwahn
parents: 41043
diff changeset
   208
        SOME ts => SOME (map fst (nth freess (card - 1)) ~~ ts)
41043
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   209
      | NONE => NONE
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   210
    val enumeration_card_size =
41086
b4cccce25d9a if only finite types and no real datatypes occur in the quantifiers only enumerate cardinality not size in quickcheck
bulwahn
parents: 41043
diff changeset
   211
      if forall (fn T => Sign.of_sort thy (T,  ["Enum.enum"])) Ts then
b4cccce25d9a if only finite types and no real datatypes occur in the quantifiers only enumerate cardinality not size in quickcheck
bulwahn
parents: 41043
diff changeset
   212
        (* size does not matter *)
b4cccce25d9a if only finite types and no real datatypes occur in the quantifiers only enumerate cardinality not size in quickcheck
bulwahn
parents: 41043
diff changeset
   213
        map (rpair 0) (1 upto (length ts))
b4cccce25d9a if only finite types and no real datatypes occur in the quantifiers only enumerate cardinality not size in quickcheck
bulwahn
parents: 41043
diff changeset
   214
      else
b4cccce25d9a if only finite types and no real datatypes occur in the quantifiers only enumerate cardinality not size in quickcheck
bulwahn
parents: 41043
diff changeset
   215
        (* size does matter *)
b4cccce25d9a if only finite types and no real datatypes occur in the quantifiers only enumerate cardinality not size in quickcheck
bulwahn
parents: 41043
diff changeset
   216
        map_product pair (1 upto (length ts)) (1 upto (Config.get ctxt size))
b4cccce25d9a if only finite types and no real datatypes occur in the quantifiers only enumerate cardinality not size in quickcheck
bulwahn
parents: 41043
diff changeset
   217
        |> sort (fn ((c1, s1), (c2, s2)) => int_ord ((c1 + s1), (c2 + s2)))
41043
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   218
    in
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   219
      if (forall is_none test_funs) then
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   220
        (NONE, ([comp_time], NONE))
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   221
      else if (forall is_some test_funs) then
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   222
        TimeLimit.timeLimit (seconds (Config.get ctxt timeout)) (fn () =>
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   223
          (get_first test_card_size enumeration_card_size, ([comp_time], NONE))) ()
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   224
        handle TimeLimit.TimeOut =>
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   225
          if is_interactive then error ("Quickcheck ran out of time") else raise TimeLimit.TimeOut
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   226
      else
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   227
        error "Unexpectedly, testers of some cardinalities are executable but others are not"       
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   228
    end
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   229
40647
6e92ca8e981b adding prototype for finite_type instantiations
bulwahn
parents: 40646
diff changeset
   230
fun get_finite_types ctxt =
6e92ca8e981b adding prototype for finite_type instantiations
bulwahn
parents: 40646
diff changeset
   231
  fst (chop (Config.get ctxt finite_type_size)
6e92ca8e981b adding prototype for finite_type instantiations
bulwahn
parents: 40646
diff changeset
   232
    (map (Type o rpair []) ["Enum.finite_1", "Enum.finite_2", "Enum.finite_3",
6e92ca8e981b adding prototype for finite_type instantiations
bulwahn
parents: 40646
diff changeset
   233
     "Enum.finite_4", "Enum.finite_5"]))  
6e92ca8e981b adding prototype for finite_type instantiations
bulwahn
parents: 40646
diff changeset
   234
37913
e85f5ad02a8f correcting wellsortedness check and improving error message
bulwahn
parents: 37912
diff changeset
   235
exception WELLSORTED of string
e85f5ad02a8f correcting wellsortedness check and improving error message
bulwahn
parents: 37912
diff changeset
   236
28309
c24bc53c815c some steps towards generic quickcheck framework
haftmann
parents: 28256
diff changeset
   237
fun monomorphic_term thy insts default_T = 
c24bc53c815c some steps towards generic quickcheck framework
haftmann
parents: 28256
diff changeset
   238
  let
c24bc53c815c some steps towards generic quickcheck framework
haftmann
parents: 28256
diff changeset
   239
    fun subst (T as TFree (v, S)) =
40903
1332f6e856b9 corrected indentation
bulwahn
parents: 40656
diff changeset
   240
      let
1332f6e856b9 corrected indentation
bulwahn
parents: 40656
diff changeset
   241
        val T' = AList.lookup (op =) insts v
1332f6e856b9 corrected indentation
bulwahn
parents: 40656
diff changeset
   242
          |> the_default default_T
1332f6e856b9 corrected indentation
bulwahn
parents: 40656
diff changeset
   243
      in if Sign.of_sort thy (T', S) then T'
1332f6e856b9 corrected indentation
bulwahn
parents: 40656
diff changeset
   244
        else raise (WELLSORTED ("For instantiation with default_type " ^ Syntax.string_of_typ_global thy default_T ^
1332f6e856b9 corrected indentation
bulwahn
parents: 40656
diff changeset
   245
          ":\n" ^ Syntax.string_of_typ_global thy T' ^
1332f6e856b9 corrected indentation
bulwahn
parents: 40656
diff changeset
   246
          " to be substituted for variable " ^
1332f6e856b9 corrected indentation
bulwahn
parents: 40656
diff changeset
   247
          Syntax.string_of_typ_global thy T ^ " does not have sort " ^
1332f6e856b9 corrected indentation
bulwahn
parents: 40656
diff changeset
   248
          Syntax.string_of_sort_global thy S))
1332f6e856b9 corrected indentation
bulwahn
parents: 40656
diff changeset
   249
      end
28309
c24bc53c815c some steps towards generic quickcheck framework
haftmann
parents: 28256
diff changeset
   250
      | subst T = T;
c24bc53c815c some steps towards generic quickcheck framework
haftmann
parents: 28256
diff changeset
   251
  in (map_types o map_atyps) subst end;
c24bc53c815c some steps towards generic quickcheck framework
haftmann
parents: 28256
diff changeset
   252
37913
e85f5ad02a8f correcting wellsortedness check and improving error message
bulwahn
parents: 37912
diff changeset
   253
datatype wellsorted_error = Wellsorted_Error of string | Term of term
e85f5ad02a8f correcting wellsortedness check and improving error message
bulwahn
parents: 37912
diff changeset
   254
40909
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   255
fun test_goal_terms lthy is_interactive insts check_goals =
28309
c24bc53c815c some steps towards generic quickcheck framework
haftmann
parents: 28256
diff changeset
   256
  let
40648
1598ec648b0d splitting test_goal function in two functions; exporting new configurations in quickcheck; iterations depend on generator_name in quickcheck
bulwahn
parents: 40647
diff changeset
   257
    val thy = ProofContext.theory_of lthy 
40926
c600f6ae4b09 only instantiate type variable if there exists some in quickcheck
bulwahn
parents: 40916
diff changeset
   258
    val default_insts =
c600f6ae4b09 only instantiate type variable if there exists some in quickcheck
bulwahn
parents: 40916
diff changeset
   259
      if Config.get lthy finite_types then (get_finite_types lthy) else (default_type lthy)
40647
6e92ca8e981b adding prototype for finite_type instantiations
bulwahn
parents: 40646
diff changeset
   260
    val inst_goals =
41043
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   261
      map (fn check_goal =>
40926
c600f6ae4b09 only instantiate type variable if there exists some in quickcheck
bulwahn
parents: 40916
diff changeset
   262
        if not (null (Term.add_tfree_names check_goal [])) then
c600f6ae4b09 only instantiate type variable if there exists some in quickcheck
bulwahn
parents: 40916
diff changeset
   263
          map (fn T =>
41043
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   264
            (pair (SOME T) o Term o Object_Logic.atomize_term thy o monomorphic_term thy insts T) check_goal
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   265
              handle WELLSORTED s => (SOME T, Wellsorted_Error s)) default_insts
40926
c600f6ae4b09 only instantiate type variable if there exists some in quickcheck
bulwahn
parents: 40916
diff changeset
   266
        else
41043
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   267
          [(NONE, Term (Object_Logic.atomize_term thy check_goal))]) check_goals
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   268
    val error_msg = cat_lines (maps (map_filter (fn (_, Term t) => NONE | (_, Wellsorted_Error s) => SOME s)) inst_goals)
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   269
    fun is_wellsorted_term (T, Term t) = SOME (T, t)
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   270
      | is_wellsorted_term (_, Wellsorted_Error s) = NONE
37913
e85f5ad02a8f correcting wellsortedness check and improving error message
bulwahn
parents: 37912
diff changeset
   271
    val correct_inst_goals =
41043
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   272
      case map (map_filter is_wellsorted_term) inst_goals of
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   273
        [[]] => error error_msg
37913
e85f5ad02a8f correcting wellsortedness check and improving error message
bulwahn
parents: 37912
diff changeset
   274
      | xs => xs
40644
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
   275
    val _ = if Config.get lthy quiet then () else warning error_msg
37912
247042107f93 using multiple default types in quickcheck
bulwahn
parents: 37911
diff changeset
   276
    fun collect_results f reports [] = (NONE, rev reports)
247042107f93 using multiple default types in quickcheck
bulwahn
parents: 37911
diff changeset
   277
      | collect_results f reports (t :: ts) =
247042107f93 using multiple default types in quickcheck
bulwahn
parents: 37911
diff changeset
   278
        case f t of
247042107f93 using multiple default types in quickcheck
bulwahn
parents: 37911
diff changeset
   279
          (SOME res, report) => (SOME res, rev (report :: reports))
247042107f93 using multiple default types in quickcheck
bulwahn
parents: 37911
diff changeset
   280
        | (NONE, report) => collect_results f (report :: reports) ts
41043
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   281
    fun test_term' goal =
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   282
      case goal of
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   283
        [(NONE, t)] => test_term lthy is_interactive t
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   284
      | ts => test_term_with_increasing_cardinality lthy is_interactive (map snd ts)                           
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   285
  in
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   286
    if Config.get lthy finite_types then
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   287
      collect_results test_term' [] correct_inst_goals
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   288
    else
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   289
      collect_results (test_term lthy is_interactive) [] (maps (map snd) correct_inst_goals)
3750bdac1327 testing smartly in two dimensions (cardinality and size) in quickcheck
bulwahn
parents: 40931
diff changeset
   290
  end;
37912
247042107f93 using multiple default types in quickcheck
bulwahn
parents: 37911
diff changeset
   291
40909
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   292
fun test_goal insts i state =
40648
1598ec648b0d splitting test_goal function in two functions; exporting new configurations in quickcheck; iterations depend on generator_name in quickcheck
bulwahn
parents: 40647
diff changeset
   293
  let
1598ec648b0d splitting test_goal function in two functions; exporting new configurations in quickcheck; iterations depend on generator_name in quickcheck
bulwahn
parents: 40647
diff changeset
   294
    val lthy = Proof.context_of state;
1598ec648b0d splitting test_goal function in two functions; exporting new configurations in quickcheck; iterations depend on generator_name in quickcheck
bulwahn
parents: 40647
diff changeset
   295
    val thy = Proof.theory_of state;
1598ec648b0d splitting test_goal function in two functions; exporting new configurations in quickcheck; iterations depend on generator_name in quickcheck
bulwahn
parents: 40647
diff changeset
   296
    fun strip (Const ("all", _) $ Abs (_, _, t)) = strip t
1598ec648b0d splitting test_goal function in two functions; exporting new configurations in quickcheck; iterations depend on generator_name in quickcheck
bulwahn
parents: 40647
diff changeset
   297
      | strip t = t;
1598ec648b0d splitting test_goal function in two functions; exporting new configurations in quickcheck; iterations depend on generator_name in quickcheck
bulwahn
parents: 40647
diff changeset
   298
    val {goal = st, ...} = Proof.raw_goal state;
1598ec648b0d splitting test_goal function in two functions; exporting new configurations in quickcheck; iterations depend on generator_name in quickcheck
bulwahn
parents: 40647
diff changeset
   299
    val (gi, frees) = Logic.goal_params (prop_of st) i;
1598ec648b0d splitting test_goal function in two functions; exporting new configurations in quickcheck; iterations depend on generator_name in quickcheck
bulwahn
parents: 40647
diff changeset
   300
    val some_locale = case (Option.map #target o Named_Target.peek) lthy
1598ec648b0d splitting test_goal function in two functions; exporting new configurations in quickcheck; iterations depend on generator_name in quickcheck
bulwahn
parents: 40647
diff changeset
   301
     of NONE => NONE
1598ec648b0d splitting test_goal function in two functions; exporting new configurations in quickcheck; iterations depend on generator_name in quickcheck
bulwahn
parents: 40647
diff changeset
   302
      | SOME "" => NONE
1598ec648b0d splitting test_goal function in two functions; exporting new configurations in quickcheck; iterations depend on generator_name in quickcheck
bulwahn
parents: 40647
diff changeset
   303
      | SOME locale => SOME locale;
1598ec648b0d splitting test_goal function in two functions; exporting new configurations in quickcheck; iterations depend on generator_name in quickcheck
bulwahn
parents: 40647
diff changeset
   304
    val assms = if Config.get lthy no_assms then [] else case some_locale
1598ec648b0d splitting test_goal function in two functions; exporting new configurations in quickcheck; iterations depend on generator_name in quickcheck
bulwahn
parents: 40647
diff changeset
   305
     of NONE => Assumption.all_assms_of lthy
1598ec648b0d splitting test_goal function in two functions; exporting new configurations in quickcheck; iterations depend on generator_name in quickcheck
bulwahn
parents: 40647
diff changeset
   306
      | SOME locale => Assumption.local_assms_of lthy (Locale.init locale thy);
1598ec648b0d splitting test_goal function in two functions; exporting new configurations in quickcheck; iterations depend on generator_name in quickcheck
bulwahn
parents: 40647
diff changeset
   307
    val proto_goal = Logic.list_implies (map Thm.term_of assms, subst_bounds (frees, strip gi));
1598ec648b0d splitting test_goal function in two functions; exporting new configurations in quickcheck; iterations depend on generator_name in quickcheck
bulwahn
parents: 40647
diff changeset
   308
    val check_goals = case some_locale
1598ec648b0d splitting test_goal function in two functions; exporting new configurations in quickcheck; iterations depend on generator_name in quickcheck
bulwahn
parents: 40647
diff changeset
   309
     of NONE => [proto_goal]
1598ec648b0d splitting test_goal function in two functions; exporting new configurations in quickcheck; iterations depend on generator_name in quickcheck
bulwahn
parents: 40647
diff changeset
   310
      | SOME locale => map (fn (_, phi) => Morphism.term phi proto_goal)
1598ec648b0d splitting test_goal function in two functions; exporting new configurations in quickcheck; iterations depend on generator_name in quickcheck
bulwahn
parents: 40647
diff changeset
   311
        (Locale.registrations_of (Context.Theory thy) (*FIXME*) locale);
1598ec648b0d splitting test_goal function in two functions; exporting new configurations in quickcheck; iterations depend on generator_name in quickcheck
bulwahn
parents: 40647
diff changeset
   312
  in
40909
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   313
    test_goal_terms lthy true insts check_goals
40648
1598ec648b0d splitting test_goal function in two functions; exporting new configurations in quickcheck; iterations depend on generator_name in quickcheck
bulwahn
parents: 40647
diff changeset
   314
  end
1598ec648b0d splitting test_goal function in two functions; exporting new configurations in quickcheck; iterations depend on generator_name in quickcheck
bulwahn
parents: 40647
diff changeset
   315
37912
247042107f93 using multiple default types in quickcheck
bulwahn
parents: 37911
diff changeset
   316
(* pretty printing *)
28315
d3cf88fe77bc generic quickcheck framework
haftmann
parents: 28309
diff changeset
   317
40225
2de5dd0cd3a2 clear identification
blanchet
parents: 40148
diff changeset
   318
fun tool_name auto = (if auto then "Auto " else "") ^ "Quickcheck"
2de5dd0cd3a2 clear identification
blanchet
parents: 40148
diff changeset
   319
2de5dd0cd3a2 clear identification
blanchet
parents: 40148
diff changeset
   320
fun pretty_counterex ctxt auto NONE = Pretty.str (tool_name auto ^ " found no counterexample.")
2de5dd0cd3a2 clear identification
blanchet
parents: 40148
diff changeset
   321
  | pretty_counterex ctxt auto (SOME cex) =
2de5dd0cd3a2 clear identification
blanchet
parents: 40148
diff changeset
   322
      Pretty.chunks (Pretty.str (tool_name auto ^ " found a counterexample:\n") ::
28315
d3cf88fe77bc generic quickcheck framework
haftmann
parents: 28309
diff changeset
   323
        map (fn (s, t) =>
40916
9928083506b6 improving presentation of quickcheck reports
bulwahn
parents: 40912
diff changeset
   324
          Pretty.block [Pretty.str (s ^ " ="), Pretty.brk 1, Syntax.pretty_term ctxt t]) (rev cex));
28315
d3cf88fe77bc generic quickcheck framework
haftmann
parents: 28309
diff changeset
   325
35378
95d0e3adf38e added basic reporting of test cases to quickcheck
bulwahn
parents: 35324
diff changeset
   326
fun pretty_report (Report {iterations = iterations, raised_match_errors = raised_match_errors,
95d0e3adf38e added basic reporting of test cases to quickcheck
bulwahn
parents: 35324
diff changeset
   327
    satisfied_assms = satisfied_assms, positive_concl_tests = positive_concl_tests}) =
95d0e3adf38e added basic reporting of test cases to quickcheck
bulwahn
parents: 35324
diff changeset
   328
  let
95d0e3adf38e added basic reporting of test cases to quickcheck
bulwahn
parents: 35324
diff changeset
   329
    fun pretty_stat s i = Pretty.block ([Pretty.str (s ^ ": " ^ string_of_int i)])
95d0e3adf38e added basic reporting of test cases to quickcheck
bulwahn
parents: 35324
diff changeset
   330
  in
95d0e3adf38e added basic reporting of test cases to quickcheck
bulwahn
parents: 35324
diff changeset
   331
     ([pretty_stat "iterations" iterations,
95d0e3adf38e added basic reporting of test cases to quickcheck
bulwahn
parents: 35324
diff changeset
   332
     pretty_stat "match exceptions" raised_match_errors]
95d0e3adf38e added basic reporting of test cases to quickcheck
bulwahn
parents: 35324
diff changeset
   333
     @ map_index (fn (i, n) => pretty_stat ("satisfied " ^ string_of_int (i + 1) ^ ". assumption") n)
95d0e3adf38e added basic reporting of test cases to quickcheck
bulwahn
parents: 35324
diff changeset
   334
       satisfied_assms
95d0e3adf38e added basic reporting of test cases to quickcheck
bulwahn
parents: 35324
diff changeset
   335
     @ [pretty_stat "positive conclusion tests" positive_concl_tests])
95d0e3adf38e added basic reporting of test cases to quickcheck
bulwahn
parents: 35324
diff changeset
   336
  end
95d0e3adf38e added basic reporting of test cases to quickcheck
bulwahn
parents: 35324
diff changeset
   337
35380
6ac5b81a763d adopting Mutabelle to quickcheck reporting; improving quickcheck reporting
bulwahn
parents: 35379
diff changeset
   338
fun pretty_reports ctxt (SOME reports) =
40916
9928083506b6 improving presentation of quickcheck reports
bulwahn
parents: 40912
diff changeset
   339
  Pretty.chunks (Pretty.fbrk :: Pretty.str "Quickcheck report:" ::
40909
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   340
    maps (fn (size, report) =>
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   341
      Pretty.str ("size " ^ string_of_int size ^ ":") :: pretty_report report @ [Pretty.brk 1])
35378
95d0e3adf38e added basic reporting of test cases to quickcheck
bulwahn
parents: 35324
diff changeset
   342
      (rev reports))
35380
6ac5b81a763d adopting Mutabelle to quickcheck reporting; improving quickcheck reporting
bulwahn
parents: 35379
diff changeset
   343
  | pretty_reports ctxt NONE = Pretty.str ""
35378
95d0e3adf38e added basic reporting of test cases to quickcheck
bulwahn
parents: 35324
diff changeset
   344
40225
2de5dd0cd3a2 clear identification
blanchet
parents: 40148
diff changeset
   345
fun pretty_counterex_and_reports ctxt auto (cex, timing_and_reports) =
2de5dd0cd3a2 clear identification
blanchet
parents: 40148
diff changeset
   346
  Pretty.chunks (pretty_counterex ctxt auto cex ::
2de5dd0cd3a2 clear identification
blanchet
parents: 40148
diff changeset
   347
    map (pretty_reports ctxt) (map snd timing_and_reports))
28315
d3cf88fe77bc generic quickcheck framework
haftmann
parents: 28309
diff changeset
   348
d3cf88fe77bc generic quickcheck framework
haftmann
parents: 28309
diff changeset
   349
(* automatic testing *)
28309
c24bc53c815c some steps towards generic quickcheck framework
haftmann
parents: 28256
diff changeset
   350
33561
ab01b72715ef introduced Auto Nitpick in addition to Auto Quickcheck;
blanchet
parents: 33560
diff changeset
   351
fun auto_quickcheck state =
40931
061b8257ab9f run synchronous Auto Tools in parallel
blanchet
parents: 40926
diff changeset
   352
  let
061b8257ab9f run synchronous Auto Tools in parallel
blanchet
parents: 40926
diff changeset
   353
    val ctxt = Proof.context_of state;
061b8257ab9f run synchronous Auto Tools in parallel
blanchet
parents: 40926
diff changeset
   354
    val res =
061b8257ab9f run synchronous Auto Tools in parallel
blanchet
parents: 40926
diff changeset
   355
      state
061b8257ab9f run synchronous Auto Tools in parallel
blanchet
parents: 40926
diff changeset
   356
      |> Proof.map_context (Config.put report false #> Config.put quiet true)
061b8257ab9f run synchronous Auto Tools in parallel
blanchet
parents: 40926
diff changeset
   357
      |> try (test_goal [] 1);
061b8257ab9f run synchronous Auto Tools in parallel
blanchet
parents: 40926
diff changeset
   358
  in
061b8257ab9f run synchronous Auto Tools in parallel
blanchet
parents: 40926
diff changeset
   359
    case res of
061b8257ab9f run synchronous Auto Tools in parallel
blanchet
parents: 40926
diff changeset
   360
      NONE => (false, state)
061b8257ab9f run synchronous Auto Tools in parallel
blanchet
parents: 40926
diff changeset
   361
    | SOME (NONE, report) => (false, state)
061b8257ab9f run synchronous Auto Tools in parallel
blanchet
parents: 40926
diff changeset
   362
    | SOME (cex, report) => (true, Proof.goal_message (K (Pretty.chunks [Pretty.str "",
061b8257ab9f run synchronous Auto Tools in parallel
blanchet
parents: 40926
diff changeset
   363
        Pretty.mark Markup.hilite (pretty_counterex ctxt true cex)])) state)
061b8257ab9f run synchronous Auto Tools in parallel
blanchet
parents: 40926
diff changeset
   364
  end
33561
ab01b72715ef introduced Auto Nitpick in addition to Auto Quickcheck;
blanchet
parents: 33560
diff changeset
   365
40931
061b8257ab9f run synchronous Auto Tools in parallel
blanchet
parents: 40926
diff changeset
   366
val setup = Auto_Tools.register_tool (auto, auto_quickcheck)
40644
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
   367
  #> setup_config
28315
d3cf88fe77bc generic quickcheck framework
haftmann
parents: 28309
diff changeset
   368
30980
fe0855471964 misc cleanup of auto_solve and quickcheck:
wenzelm
parents: 30973
diff changeset
   369
(* Isar commands *)
28315
d3cf88fe77bc generic quickcheck framework
haftmann
parents: 28309
diff changeset
   370
28336
a8edf4c69a79 fixed quickcheck parameter syntax
haftmann
parents: 28315
diff changeset
   371
fun read_nat s = case (Library.read_int o Symbol.explode) s
a8edf4c69a79 fixed quickcheck parameter syntax
haftmann
parents: 28315
diff changeset
   372
 of (k, []) => if k >= 0 then k
a8edf4c69a79 fixed quickcheck parameter syntax
haftmann
parents: 28315
diff changeset
   373
      else error ("Not a natural number: " ^ s)
a8edf4c69a79 fixed quickcheck parameter syntax
haftmann
parents: 28315
diff changeset
   374
  | (_, _ :: _) => error ("Not a natural number: " ^ s);
37909
583543ad6ad1 changed default types to a list of types; extended quickcheck parameters to be a list of values to parse a list of default types
bulwahn
parents: 36960
diff changeset
   375
34128
8650a073dd9b made Quickcheck take structured proof assumptions into account (like Refute and Nitpick) by default;
blanchet
parents: 33583
diff changeset
   376
fun read_bool "false" = false
8650a073dd9b made Quickcheck take structured proof assumptions into account (like Refute and Nitpick) by default;
blanchet
parents: 33583
diff changeset
   377
  | read_bool "true" = true
8650a073dd9b made Quickcheck take structured proof assumptions into account (like Refute and Nitpick) by default;
blanchet
parents: 33583
diff changeset
   378
  | read_bool s = error ("Not a Boolean value: " ^ s)
28315
d3cf88fe77bc generic quickcheck framework
haftmann
parents: 28309
diff changeset
   379
40366
a2866dbfbe6b changing timeout to real value; handling Interrupt and Timeout more like nitpick does
bulwahn
parents: 40253
diff changeset
   380
fun read_real s =
a2866dbfbe6b changing timeout to real value; handling Interrupt and Timeout more like nitpick does
bulwahn
parents: 40253
diff changeset
   381
  case (Real.fromString s) of
a2866dbfbe6b changing timeout to real value; handling Interrupt and Timeout more like nitpick does
bulwahn
parents: 40253
diff changeset
   382
    SOME s => s
a2866dbfbe6b changing timeout to real value; handling Interrupt and Timeout more like nitpick does
bulwahn
parents: 40253
diff changeset
   383
  | NONE => error ("Not a real number: " ^ s)
a2866dbfbe6b changing timeout to real value; handling Interrupt and Timeout more like nitpick does
bulwahn
parents: 40253
diff changeset
   384
37929
22e0797857e6 adding checking of expected result for the tool quickcheck; annotated a few quickcheck examples
bulwahn
parents: 37913
diff changeset
   385
fun read_expectation "no_expectation" = No_Expectation
22e0797857e6 adding checking of expected result for the tool quickcheck; annotated a few quickcheck examples
bulwahn
parents: 37913
diff changeset
   386
  | read_expectation "no_counterexample" = No_Counterexample 
22e0797857e6 adding checking of expected result for the tool quickcheck; annotated a few quickcheck examples
bulwahn
parents: 37913
diff changeset
   387
  | read_expectation "counterexample" = Counterexample
22e0797857e6 adding checking of expected result for the tool quickcheck; annotated a few quickcheck examples
bulwahn
parents: 37913
diff changeset
   388
  | read_expectation s = error ("Not an expectation value: " ^ s)  
22e0797857e6 adding checking of expected result for the tool quickcheck; annotated a few quickcheck examples
bulwahn
parents: 37913
diff changeset
   389
40912
1108529100ce checking if parameter is name of a tester which allows e.g. quickcheck[random]
bulwahn
parents: 40911
diff changeset
   390
fun valid_tester_name genctxt = AList.defined (op =) (fst (Data.get genctxt))
1108529100ce checking if parameter is name of a tester which allows e.g. quickcheck[random]
bulwahn
parents: 40911
diff changeset
   391
1108529100ce checking if parameter is name of a tester which allows e.g. quickcheck[random]
bulwahn
parents: 40911
diff changeset
   392
fun parse_tester name genctxt =
1108529100ce checking if parameter is name of a tester which allows e.g. quickcheck[random]
bulwahn
parents: 40911
diff changeset
   393
  if valid_tester_name genctxt name then
1108529100ce checking if parameter is name of a tester which allows e.g. quickcheck[random]
bulwahn
parents: 40911
diff changeset
   394
    Config.put_generic tester name genctxt
1108529100ce checking if parameter is name of a tester which allows e.g. quickcheck[random]
bulwahn
parents: 40911
diff changeset
   395
  else
1108529100ce checking if parameter is name of a tester which allows e.g. quickcheck[random]
bulwahn
parents: 40911
diff changeset
   396
    error ("Unknown tester: " ^ name)
1108529100ce checking if parameter is name of a tester which allows e.g. quickcheck[random]
bulwahn
parents: 40911
diff changeset
   397
1108529100ce checking if parameter is name of a tester which allows e.g. quickcheck[random]
bulwahn
parents: 40911
diff changeset
   398
fun parse_test_param ("tester", [arg]) = parse_tester arg
40909
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   399
  | parse_test_param ("size", [arg]) = Config.put_generic size (read_nat arg)
40644
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
   400
  | parse_test_param ("iterations", [arg]) = Config.put_generic iterations (read_nat arg)
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
   401
  | parse_test_param ("default_type", arg) = (fn gen_ctxt =>
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
   402
    map_test_params ((apfst o K) (map (ProofContext.read_typ (Context.proof_of gen_ctxt)) arg)) gen_ctxt)
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
   403
  | parse_test_param ("no_assms", [arg]) = Config.put_generic no_assms (read_bool arg)
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
   404
  | parse_test_param ("expect", [arg]) = map_test_params ((apsnd o K) (read_expectation arg))
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
   405
  | parse_test_param ("report", [arg]) = Config.put_generic report (read_bool arg)
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
   406
  | parse_test_param ("quiet", [arg]) = Config.put_generic quiet (read_bool arg)
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
   407
  | parse_test_param ("timeout", [arg]) = Config.put_generic timeout (read_real arg)
40646
3dfa41e89738 adding option finite_types to quickcheck
bulwahn
parents: 40644
diff changeset
   408
  | parse_test_param ("finite_types", [arg]) = Config.put_generic finite_types (read_bool arg)
40647
6e92ca8e981b adding prototype for finite_type instantiations
bulwahn
parents: 40646
diff changeset
   409
  | parse_test_param ("finite_type_size", [arg]) = Config.put_generic finite_type_size (read_nat arg)
40912
1108529100ce checking if parameter is name of a tester which allows e.g. quickcheck[random]
bulwahn
parents: 40911
diff changeset
   410
  | parse_test_param (name, _) = fn genctxt =>
1108529100ce checking if parameter is name of a tester which allows e.g. quickcheck[random]
bulwahn
parents: 40911
diff changeset
   411
    if valid_tester_name genctxt name then
1108529100ce checking if parameter is name of a tester which allows e.g. quickcheck[random]
bulwahn
parents: 40911
diff changeset
   412
      Config.put_generic tester name genctxt
1108529100ce checking if parameter is name of a tester which allows e.g. quickcheck[random]
bulwahn
parents: 40911
diff changeset
   413
    else error ("Unknown tester or test parameter: " ^ name);
28315
d3cf88fe77bc generic quickcheck framework
haftmann
parents: 28309
diff changeset
   414
40909
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   415
fun parse_test_param_inst (name, arg) (insts, ctxt) =
28336
a8edf4c69a79 fixed quickcheck parameter syntax
haftmann
parents: 28315
diff changeset
   416
      case try (ProofContext.read_typ ctxt) name
40909
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   417
       of SOME (TFree (v, _)) => (apfst o AList.update (op =))
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   418
              (v, ProofContext.read_typ ctxt (the_single arg)) (insts, ctxt)
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   419
        | _ => (apsnd o Context.proof_map o parse_test_param) (name, arg) (insts, ctxt);
28309
c24bc53c815c some steps towards generic quickcheck framework
haftmann
parents: 28256
diff changeset
   420
40644
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
   421
fun quickcheck_params_cmd args = Context.theory_map (fold parse_test_param args);
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
   422
  
35378
95d0e3adf38e added basic reporting of test cases to quickcheck
bulwahn
parents: 35324
diff changeset
   423
fun gen_quickcheck args i state =
40644
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
   424
  state
40909
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   425
  |> Proof.map_context_result (fn ctxt => fold parse_test_param_inst args ([], ctxt))
e006d1e06920 renamed parameter from generator to tester; quickcheck only applies one tester on invocation
bulwahn
parents: 40908
diff changeset
   426
  |> (fn (insts, state') => test_goal insts i state'
40644
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
   427
  |> tap (fn (SOME x, _) => if expect (Proof.context_of state') = No_Counterexample then
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
   428
               error ("quickcheck expected to find no counterexample but found one") else ()
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
   429
           | (NONE, _) => if expect (Proof.context_of state') = Counterexample then
0850a2a16dce changed old-style quickcheck configurations to new Config.T configurations
bulwahn
parents: 40643
diff changeset
   430
               error ("quickcheck expected to find a counterexample but did not find one") else ()))
32297
3a4081abb3f7 Quickcheck callable from ML
boehmes
parents: 31599
diff changeset
   431
36960
01594f816e3a prefer structure Keyword, Parse, Parse_Spec, Outer_Syntax;
wenzelm
parents: 36610
diff changeset
   432
fun quickcheck args i state = fst (gen_quickcheck args i state);
35378
95d0e3adf38e added basic reporting of test cases to quickcheck
bulwahn
parents: 35324
diff changeset
   433
32297
3a4081abb3f7 Quickcheck callable from ML
boehmes
parents: 31599
diff changeset
   434
fun quickcheck_cmd args i state =
35378
95d0e3adf38e added basic reporting of test cases to quickcheck
bulwahn
parents: 35324
diff changeset
   435
  gen_quickcheck args i (Toplevel.proof_of state)
40225
2de5dd0cd3a2 clear identification
blanchet
parents: 40148
diff changeset
   436
  |> Pretty.writeln o pretty_counterex_and_reports (Toplevel.context_of state) false;
28309
c24bc53c815c some steps towards generic quickcheck framework
haftmann
parents: 28256
diff changeset
   437
37909
583543ad6ad1 changed default types to a list of types; extended quickcheck parameters to be a list of values to parse a list of default types
bulwahn
parents: 36960
diff changeset
   438
val parse_arg = Parse.name -- (Scan.optional (Parse.$$$ "=" |-- 
40366
a2866dbfbe6b changing timeout to real value; handling Interrupt and Timeout more like nitpick does
bulwahn
parents: 40253
diff changeset
   439
  (((Parse.name || Parse.float_number) >> single) || (Parse.$$$ "[" |-- Parse.list1 Parse.name --| Parse.$$$ "]"))) ["true"]);
28309
c24bc53c815c some steps towards generic quickcheck framework
haftmann
parents: 28256
diff changeset
   440
36960
01594f816e3a prefer structure Keyword, Parse, Parse_Spec, Outer_Syntax;
wenzelm
parents: 36610
diff changeset
   441
val parse_args = Parse.$$$ "[" |-- Parse.list1 parse_arg --| Parse.$$$ "]"
28336
a8edf4c69a79 fixed quickcheck parameter syntax
haftmann
parents: 28315
diff changeset
   442
  || Scan.succeed [];
a8edf4c69a79 fixed quickcheck parameter syntax
haftmann
parents: 28315
diff changeset
   443
36960
01594f816e3a prefer structure Keyword, Parse, Parse_Spec, Outer_Syntax;
wenzelm
parents: 36610
diff changeset
   444
val _ =
01594f816e3a prefer structure Keyword, Parse, Parse_Spec, Outer_Syntax;
wenzelm
parents: 36610
diff changeset
   445
  Outer_Syntax.command "quickcheck_params" "set parameters for random testing" Keyword.thy_decl
01594f816e3a prefer structure Keyword, Parse, Parse_Spec, Outer_Syntax;
wenzelm
parents: 36610
diff changeset
   446
    (parse_args >> (fn args => Toplevel.theory (quickcheck_params_cmd args)));
28309
c24bc53c815c some steps towards generic quickcheck framework
haftmann
parents: 28256
diff changeset
   447
36960
01594f816e3a prefer structure Keyword, Parse, Parse_Spec, Outer_Syntax;
wenzelm
parents: 36610
diff changeset
   448
val _ =
01594f816e3a prefer structure Keyword, Parse, Parse_Spec, Outer_Syntax;
wenzelm
parents: 36610
diff changeset
   449
  Outer_Syntax.improper_command "quickcheck" "try to find counterexample for subgoal" Keyword.diag
01594f816e3a prefer structure Keyword, Parse, Parse_Spec, Outer_Syntax;
wenzelm
parents: 36610
diff changeset
   450
    (parse_args -- Scan.optional Parse.nat 1
01594f816e3a prefer structure Keyword, Parse, Parse_Spec, Outer_Syntax;
wenzelm
parents: 36610
diff changeset
   451
      >> (fn (args, i) => Toplevel.no_timing o Toplevel.keep (quickcheck_cmd args i)));
28309
c24bc53c815c some steps towards generic quickcheck framework
haftmann
parents: 28256
diff changeset
   452
28315
d3cf88fe77bc generic quickcheck framework
haftmann
parents: 28309
diff changeset
   453
end;
28309
c24bc53c815c some steps towards generic quickcheck framework
haftmann
parents: 28256
diff changeset
   454
c24bc53c815c some steps towards generic quickcheck framework
haftmann
parents: 28256
diff changeset
   455
28315
d3cf88fe77bc generic quickcheck framework
haftmann
parents: 28309
diff changeset
   456
val auto_quickcheck = Quickcheck.auto;