Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix QCheck2.gen.list_size Stack overflow #160

Merged
merged 3 commits into from
Sep 7, 2021
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
12 changes: 7 additions & 5 deletions src/core/QCheck2.ml
Original file line number Diff line number Diff line change
Expand Up @@ -527,14 +527,16 @@ module Gen = struct

let ui64 : int64 t = map Int64.abs int64

(* A tail-recursive implementation over Tree.t *)
let list_size (size : int t) (gen : 'a t) : 'a list t =
size >>= fun size ->
let rec loop n =
fun st ->
Tree.bind (size st) @@ fun size ->
let rec loop n acc =
if n <= 0
then pure []
else liftA2 List.cons gen (loop (n - 1))
then acc
else (loop [@tailcall]) (n - 1) (Tree.liftA2 List.cons (gen st) acc)
in
loop size
loop size (Tree.pure [])

let list (gen : 'a t) : 'a list t = list_size nat gen

Expand Down
16 changes: 8 additions & 8 deletions test/core/QCheck2_expect_test.ml
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ module Shrink = struct

let strings_are_empty =
Test.make ~name:"strings are empty" ~count:1000 ~print:Print.string
Gen.string (fun s -> (*Printf.printf "\"%s\"\n" (String.escaped s);*) s = "")
Gen.string (fun s -> s = "")

let string_never_has_000_char =
Test.make ~name:"string never has a \\000 char" ~count:1000 ~print:Print.string
Expand All @@ -164,7 +164,7 @@ module Shrink = struct

let list_shorter_10 =
Test.make ~name:"lists shorter than 10" ~print:Print.(list int)
Gen.(list small_int) (fun xs -> (*print_list xs;*) List.length xs < 10)
Gen.(list small_int) (fun xs -> List.length xs < 10)

let length_printer xs =
Printf.sprintf "[...] list length: %i" (List.length xs)
Expand All @@ -173,17 +173,17 @@ module Shrink = struct

let list_shorter_432 =
Test.make ~name:"lists shorter than 432" ~print:length_printer
Gen.(list_size size_gen small_int) (*Gen.(list small_int)*)
(fun xs -> (*print_list xs;*) List.length xs < 432)
Gen.(list_size size_gen small_int)
(fun xs -> List.length xs < 432)

let list_shorter_4332 =
Test.make ~name:"lists shorter than 4332" ~print:length_printer
Gen.(list_size size_gen small_int) (*Gen.(list small_int)*)
(fun xs -> (*print_list xs;*) List.length xs < 4332)
Gen.(list_size size_gen small_int)
(fun xs -> List.length xs < 4332)

let list_equal_dupl =
Test.make ~name:"lists equal to duplication" ~print:length_printer
Gen.(list_size size_gen small_int) (*Gen.(list small_int)*)
Test.make ~name:"lists equal to duplication" ~print:Print.(list int)
Gen.(list_size size_gen small_int)
(fun xs -> try xs = xs @ xs
with Stack_overflow -> false)

Expand Down
13 changes: 6 additions & 7 deletions test/core/QCheck_expect_test.ml
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ module Shrink = struct

let strings_are_empty =
Test.make ~name:"strings are empty" ~count:1000
string (fun s -> (*Printf.printf "\"%s\"\n" (String.escaped s);*) s = "")
string (fun s -> s = "")

let string_never_has_000_char =
Test.make ~name:"string never has a \\000 char" ~count:1000
Expand All @@ -157,7 +157,7 @@ module Shrink = struct

let list_shorter_10 =
Test.make ~name:"lists shorter than 10"
(list small_int) (fun xs -> (*print_list xs;*) List.length xs < 10)
(list small_int) (fun xs -> List.length xs < 10)

let length_printer xs =
Printf.sprintf "[...] list length: %i" (List.length xs)
Expand All @@ -166,18 +166,17 @@ module Shrink = struct

let list_shorter_432 =
Test.make ~name:"lists shorter than 432"
(set_print length_printer (list_of_size size_gen small_int)) (*(list small_int)*)
(fun xs -> (*print_list xs;*) List.length xs < 432)
(set_print length_printer (list_of_size size_gen small_int))
(fun xs -> List.length xs < 432)

let list_shorter_4332 =
Test.make ~name:"lists shorter than 4332"
(set_shrink Shrink.list_spine (set_print length_printer (list_of_size size_gen small_int)))
(fun xs -> (*print_list xs;*) List.length xs < 4332)
(fun xs -> List.length xs < 4332)

let list_equal_dupl =
Test.make ~name:"lists equal to duplication"
(set_print length_printer (list_of_size size_gen small_int))
(*(set_print length_printer (list small_int))*)
(list_of_size size_gen small_int)
(fun xs -> try xs = xs @ xs
with Stack_overflow -> false)

Expand Down
18 changes: 6 additions & 12 deletions test/core/qcheck2_output.txt.expected
Original file line number Diff line number Diff line change
Expand Up @@ -316,27 +316,21 @@ Test lists shorter than 10 failed (16 shrink steps):

--- Failure --------------------------------------------------------------------

Test lists shorter than 432 failed:
Test lists shorter than 432 failed (412 shrink steps):

ERROR: uncaught exception in generator for test lists shorter than 432 after 100 steps:
Exception: Stack overflow
Backtrace:
[...] list length: 432

--- Failure --------------------------------------------------------------------

Test lists shorter than 4332 failed:
Test lists shorter than 4332 failed (4022 shrink steps):

ERROR: uncaught exception in generator for test lists shorter than 4332 after 100 steps:
Exception: Stack overflow
Backtrace:
[...] list length: 4332

--- Failure --------------------------------------------------------------------

Test lists equal to duplication failed:
Test lists equal to duplication failed (4 shrink steps):

ERROR: uncaught exception in generator for test lists equal to duplication after 100 steps:
Exception: Stack overflow
Backtrace:
[0]

--- Failure --------------------------------------------------------------------

Expand Down
2 changes: 1 addition & 1 deletion test/core/qcheck_output.txt.expected
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ Test lists shorter than 4332 failed (13 shrink steps):

Test lists equal to duplication failed (20 shrink steps):

[...] list length: 1
[0]

--- Failure --------------------------------------------------------------------

Expand Down