Repository: c-cube/qcheck (ocaml)

Issue:

Pull request:
Fix QCheck2 float_range operator with negative bounds
Example crash fixed:
> # QCheck_base_runner.run_tests [QCheck2.Test.make ~count:100000 ~print:QCheck2.Print.float (QCheck2.Gen.float_range (-2.) (-1.)) (fun _ -> false)];;
> random seed: 143173129
> Exception:
> Invalid_argument
>  "Gen.float_bound_inclusive: origin value -1. is lower than low value 0.".

I also think we could generate `float_range` to avoid the range limit currently baked in.

I don't know a good way to generate the other expected files for alternative platforms.

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6258109..8c518b9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,7 @@
 
 ## NEXT RELEASE
 
+- Fix QCheck2 `float_range` operator which would fail on negative bounds
 - Fix `QCHECK_MSG_INTERVAL` not being applied to the first in-progress message
 
 ## 0.25
diff --git a/src/core/QCheck2.ml b/src/core/QCheck2.ml
index 7313784..32961cf 100644
--- a/src/core/QCheck2.ml
+++ b/src/core/QCheck2.ml
@@ -445,6 +445,7 @@ module Gen = struct
                    ~origin:(Option.value ~default:(pick_origin_within_range ~low ~high ~goal:0.) origin)
                    ~low
                    ~high in
+    let origin = origin -. low in
     (float_bound_inclusive ~origin (high -. low))
     >|= (fun x -> low +. x)
 


Test patch:
diff --git a/test/core/QCheck2_expect_test.expected.ocaml4.32 b/test/core/QCheck2_expect_test.expected.ocaml4.32
index 04472ca..957871f 100644
--- a/test/core/QCheck2_expect_test.expected.ocaml4.32
+++ b/test/core/QCheck2_expect_test.expected.ocaml4.32
@@ -239,6 +239,12 @@ Test char never produces '\255' failed (0 shrink steps):
 
 --- Failure --------------------------------------------------------------------
 
+Test regression test negative float range failed (1 shrink steps):
+
+-1.
+
+--- Failure --------------------------------------------------------------------
+
 Test big bound issue59 failed (0 shrink steps):
 
 1073741823
@@ -1682,7 +1688,7 @@ stats dist:
     6.. 10:                                                                   0
 ================================================================================
 1 warning(s)
-failure (75 tests failed, 3 tests errored, ran 167 tests)
+failure (76 tests failed, 3 tests errored, ran 168 tests)
 random seed: 153870556
 
 +++ Stats for int_dist_empty_bucket ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/test/core/QCheck2_expect_test.expected.ocaml4.64 b/test/core/QCheck2_expect_test.expected.ocaml4.64
index 51d318f..c86169a 100644
--- a/test/core/QCheck2_expect_test.expected.ocaml4.64
+++ b/test/core/QCheck2_expect_test.expected.ocaml4.64
@@ -301,6 +301,12 @@ Test char never produces '\255' failed (0 shrink steps):
 
 --- Failure --------------------------------------------------------------------
 
+Test regression test negative float range failed (1 shrink steps):
+
+-1.
+
+--- Failure --------------------------------------------------------------------
+
 Test big bound issue59 failed (0 shrink steps):
 
 4611686018427387903
@@ -1744,7 +1750,7 @@ stats dist:
     6.. 10:                                                                   0
 ================================================================================
 1 warning(s)
-failure (75 tests failed, 3 tests errored, ran 167 tests)
+failure (76 tests failed, 3 tests errored, ran 168 tests)
 random seed: 153870556
 
 +++ Stats for int_dist_empty_bucket ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/test/core/QCheck2_expect_test.expected.ocaml5.32 b/test/core/QCheck2_expect_test.expected.ocaml5.32
index 257cae2..1081225 100644
--- a/test/core/QCheck2_expect_test.expected.ocaml5.32
+++ b/test/core/QCheck2_expect_test.expected.ocaml5.32
@@ -222,6 +222,12 @@ Test char never produces '\255' failed (0 shrink steps):
 
 --- Failure --------------------------------------------------------------------
 
+Test regression test negative float range failed (1 shrink steps):
+
+-1.
+
+--- Failure --------------------------------------------------------------------
+
 Test big bound issue59 failed (0 shrink steps):
 
 1073741823
@@ -1666,7 +1672,7 @@ stats dist:
    -3..  0: #######################################################        1631
 ================================================================================
 1 warning(s)
-failure (75 tests failed, 3 tests errored, ran 167 tests)
+failure (76 tests failed, 3 tests errored, ran 168 tests)
 random seed: 153870556
 
 +++ Stats for int_dist_empty_bucket ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/test/core/QCheck2_expect_test.expected.ocaml5.64 b/test/core/QCheck2_expect_test.expected.ocaml5.64
index 4bef526..7f1cd68 100644
--- a/test/core/QCheck2_expect_test.expected.ocaml5.64
+++ b/test/core/QCheck2_expect_test.expected.ocaml5.64
@@ -284,6 +284,12 @@ Test char never produces '\255' failed (0 shrink steps):
 
 --- Failure --------------------------------------------------------------------
 
+Test regression test negative float range failed (1 shrink steps):
+
+-1.
+
+--- Failure --------------------------------------------------------------------
+
 Test big bound issue59 failed (0 shrink steps):
 
 4611686018427387903
@@ -1728,7 +1734,7 @@ stats dist:
    -3..  0: #######################################################        1631
 ================================================================================
 1 warning(s)
-failure (75 tests failed, 3 tests errored, ran 167 tests)
+failure (76 tests failed, 3 tests errored, ran 168 tests)
 random seed: 153870556
 
 +++ Stats for int_dist_empty_bucket ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/test/core/QCheck2_tests.ml b/test/core/QCheck2_tests.ml
index 1c5d247..1be43a4 100644
--- a/test/core/QCheck2_tests.ml
+++ b/test/core/QCheck2_tests.ml
@@ -340,6 +340,12 @@ module Generator = struct
       IntTree.gen_tree
       (fun tree -> IntTree.(rev_tree (rev_tree tree)) = tree)
 
+  let float_test =
+    Test.make ~name:"regression test negative float range" ~count:1000
+      ~print:Print.float
+      (Gen.float_range (-2.) (-1.))
+      (fun _ -> false)
+
   let tests = [
     char_dist_issue_23;
     char_test;
@@ -368,6 +374,7 @@ module Generator = struct
     int_option_test;
     int_string_result_test;
     passing_tree_rev;
+    float_test;
   ]
 end
 
@@ -688,6 +695,7 @@ module Shrink = struct
       Gen.(no_shrink @@ list small_int)
       (fun xs -> List.fold_left (+) 0 xs = 0)
 
+
   let tests = [
     (*test_fac_issue59;*)
     big_bound_issue59;
diff --git a/test/core/QCheck_expect_test.expected.ocaml4.32 b/test/core/QCheck_expect_test.expected.ocaml4.32
index bdfefeb..26fe2d2 100644
--- a/test/core/QCheck_expect_test.expected.ocaml4.32
+++ b/test/core/QCheck_expect_test.expected.ocaml4.32
@@ -215,6 +215,12 @@ Test char never produces '\255' failed (0 shrink steps):
 
 --- Failure --------------------------------------------------------------------
 
+Test regression test negative float range failed (0 shrink steps):
+
+-1.15084840857
+
+--- Failure --------------------------------------------------------------------
+
 Test big bound issue59 failed (20 shrink steps):
 
 209609
@@ -1659,7 +1665,7 @@ stats dist:
     6.. 10:                                                                   0
 ================================================================================
 1 warning(s)
-failure (75 tests failed, 3 tests errored, ran 175 tests)
+failure (76 tests failed, 3 tests errored, ran 176 tests)
 random seed: 153870556
 
 +++ Stats for int_dist_empty_bucket ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/test/core/QCheck_expect_test.expected.ocaml4.64 b/test/core/QCheck_expect_test.expected.ocaml4.64
index bd82619..8f0e045 100644
--- a/test/core/QCheck_expect_test.expected.ocaml4.64
+++ b/test/core/QCheck_expect_test.expected.ocaml4.64
@@ -247,6 +247,12 @@ Test char never produces '\255' failed (0 shrink steps):
 
 --- Failure --------------------------------------------------------------------
 
+Test regression test negative float range failed (0 shrink steps):
+
+-1.15084840857
+
+--- Failure --------------------------------------------------------------------
+
 Test big bound issue59 failed (52 shrink steps):
 
 209609
@@ -1691,7 +1697,7 @@ stats dist:
     6.. 10:                                                                   0
 ================================================================================
 1 warning(s)
-failure (75 tests failed, 3 tests errored, ran 175 tests)
+failure (76 tests failed, 3 tests errored, ran 176 tests)
 random seed: 153870556
 
 +++ Stats for int_dist_empty_bucket ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/test/core/QCheck_expect_test.expected.ocaml5.32 b/test/core/QCheck_expect_test.expected.ocaml5.32
index 355f7bb..2050fc4 100644
--- a/test/core/QCheck_expect_test.expected.ocaml5.32
+++ b/test/core/QCheck_expect_test.expected.ocaml5.32
@@ -225,6 +225,12 @@ Test char never produces '\255' failed (0 shrink steps):
 
 --- Failure --------------------------------------------------------------------
 
+Test regression test negative float range failed (0 shrink steps):
+
+-1.13811703367
+
+--- Failure --------------------------------------------------------------------
+
 Test big bound issue59 failed (20 shrink steps):
 
 209609
@@ -1670,7 +1676,7 @@ stats dist:
    -3..  0: #######################################################        1631
 ================================================================================
 1 warning(s)
-failure (75 tests failed, 3 tests errored, ran 175 tests)
+failure (76 tests failed, 3 tests errored, ran 176 tests)
 random seed: 153870556
 
 +++ Stats for int_dist_empty_bucket ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/test/core/QCheck_expect_test.expected.ocaml5.64 b/test/core/QCheck_expect_test.expected.ocaml5.64
index 0b9562f..595cae0 100644
--- a/test/core/QCheck_expect_test.expected.ocaml5.64
+++ b/test/core/QCheck_expect_test.expected.ocaml5.64
@@ -257,6 +257,12 @@ Test char never produces '\255' failed (0 shrink steps):
 
 --- Failure --------------------------------------------------------------------
 
+Test regression test negative float range failed (0 shrink steps):
+
+-1.13811703367
+
+--- Failure --------------------------------------------------------------------
+
 Test big bound issue59 failed (52 shrink steps):
 
 209609
@@ -1702,7 +1708,7 @@ stats dist:
    -3..  0: #######################################################        1631
 ================================================================================
 1 warning(s)
-failure (75 tests failed, 3 tests errored, ran 175 tests)
+failure (76 tests failed, 3 tests errored, ran 176 tests)
 random seed: 153870556
 
 +++ Stats for int_dist_empty_bucket ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/test/core/QCheck_tests.ml b/test/core/QCheck_tests.ml
index 2efa1f6..9476fa0 100644
--- a/test/core/QCheck_tests.ml
+++ b/test/core/QCheck_tests.ml
@@ -418,6 +418,9 @@ module Generator = struct
          && Array.for_all (fun k -> 0 < k) arr
          && Array.fold_left (+) 0 arr = n)
 
+  let float_test =
+    Test.make ~name:"regression test negative float range" ~count:1000 (float_range (-2.) (-1.)) (fun _ -> false)
+
   let tests = [
     char_dist_issue_23;
     char_test;
@@ -454,6 +457,7 @@ module Generator = struct
     nat_split_n_way;
     nat_split_smaller;
     pos_split;
+    float_test;
   ]
 end