Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
- `TestResult.stats` `TestResult.warnings` `TestResult.collect`
- Clarify documentation for the `int*` and `nat*` generators
- Disabled duplicated pretty-printed feedback when using `QCheck_alcotest` runner
- Fixed the overflow bug when `~count > max_int - 200` affecting `Test.{make_cell,make,make_neg}` in both QCheck and QCheck2


## 0.91 (2025-12-21)
Expand Down
4 changes: 2 additions & 2 deletions src/core/QCheck2.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1618,7 +1618,7 @@ module Test = struct
let count = global_count count in
let long_factor = global_long_factor long_factor in
let positive = not negative in
let max_gen = match max_gen with None -> count + 200 | Some x->x in
let max_gen = match max_gen with None -> max count (count + 200) | Some x->x in
{
law;
gen;
Expand All @@ -1645,7 +1645,7 @@ module Test = struct
let positive = not negative in
(* Make a "fake" QCheck2 arbitrary with no shrinking *)
let fake_gen = Gen.make_primitive ~gen ~shrink:(fun _ -> Seq.empty) in
let max_gen = match max_gen with None -> count + 200 | Some x->x in
let max_gen = match max_gen with None -> max count (count + 200) | Some x->x in
{
law;
gen = fake_gen;
Expand Down
19 changes: 19 additions & 0 deletions test/core/QCheck2_unit_tests.ml
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,23 @@ module TestCount = struct
with
| _ -> ()

(* Regression for https://github.com/c-cube/qcheck/issues/408:
[make_cell] computed [max_gen = count + 200] without checking for
overflow, so [count >= max_int - 199] wrapped to a negative int
and [check_cell] silently ran zero iterations. *)
let test_count_max_int_no_overflow () =
let cell =
QCheck2.(Test.make_cell ~name:"never_true" ~count:max_int
Gen.int (fun _ -> false))
in
let result =
QCheck2.Test.check_cell ~rand:(Random.State.make [|0|]) cell
in
let tested = QCheck2.TestResult.get_count_gen result in
Alcotest.(check bool)
"check_cell with count=max_int runs at least one iteration"
true (tested >= 1)

let tests =
("Test.make ~count", Alcotest.[
test_case "make with custom count" `Quick test_count_10;
Expand All @@ -625,6 +642,8 @@ module TestCount = struct
test_case "make with 0 count" `Quick test_count_0;
test_case "make with negative count should fail"
`Quick test_count_negative_fail;
test_case "check_cell with count=max_int does not overflow"
`Quick test_count_max_int_no_overflow;
])
end

Expand Down
Loading