You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
It is clear that generating functions last in a tuple rather than first (a hard-learned lesson from issue #8) is still a clear win for integrated shrinking. Still, there is quite a few more bindings reported in the above counterexample compared to QCheck.
Looking at the function generator and shrinker I can see a list of bindings is reduced using Tree.applicative_take which takes at 0-len bindings:
letshrinks : (k, v) t Tree.t Seq.t =fun() ->
(* This only gets evaluated *after* the test was run for [tbl], meaning it is correctly populated with bindings recorded during the test already *)letcurrent_bindings : (k * v Tree.t) list =List.rev !(root.p_tree_bindings_rev) inlettake_at_most_tree : int Tree.t =Tree.make_primitive (Shrink.int_towards 0) (List.length current_bindings) inletcurrent_tree_bindings : (k * v) Tree.t list =List.map (fun (k, tree) -> Tree.map (funv -> (k, v)) tree) current_bindings inletshrunk_bindings_tree : (k * v) list Tree.t =Tree.bind take_at_most_tree (funtake_at_most -> Tree.applicative_take take_at_most current_tree_bindings) in(* During shrinking, we don't want to record/add bindings, so [~extend:false]. *)letshrunk_poly_tbl_tree : (k, v) t Tree.t =Tree.map (funbindings -> List.to_seq bindings |>T.of_seq |> make ~extend:false) shrunk_bindings_tree in(* [shrunk_poly_tbl_tree] is a bit misleading: its root *should* be the same as [root] but because of the required laziness induced by the mutation of bindings, we don't use it, only graft its children to the original [root]. *)Tree.children shrunk_poly_tbl_tree ()inTree.Tree (root, shrinks)
This looks like a quick algorithmic list shrinker to me - also with opportunities for improvements.
It puzzled me that the take_at_most wasn't reducing the above list of bindings further. After all, the outlier binding (1, 0) -> 1 is in the middle!
I therefore added a shrink log of successful shrink attempts by replacing l.355 of QCheck2_expect_test.ml with:
QCheck_base_runner.run_tests ~colors:false~debug_shrink:(Some (open_out "funshrinklog.txt")) ~debug_shrink_list:["fold_left fold_right uncurried fun last"] ([
After rerunning the tests, this revealed the following in _build/default/test/core/funshrinklog.txt:
This looks fishy to me: while the first elements of the tuple are reduced, the last one (the function table) actually gets longer in each attempt!
I think this is actually due to how Gen.triple is currently defined (and thus shrinks). I'll therefore add some tests for it and report separately.
Sub-optimal function shrinkers
A number of the function tests illustrate a difference in the function shrinker's output (terminal cuts off at width 160):
The steps spent vary between the two approaches. The last two are perhaps most saying.
First off, here's the counterexamples reported by QCheck2:
It is clear that generating functions last in a tuple rather than first (a hard-learned lesson from issue #8) is still a clear win for integrated shrinking. Still, there is quite a few more bindings reported in the above counterexample compared to QCheck.
Looking at the function generator and shrinker I can see a list of
bindings
is reduced usingTree.applicative_take
which takes at 0-len
bindings:This looks like a quick algorithmic
list
shrinker to me - also with opportunities for improvements.It puzzled me that the
take_at_most
wasn't reducing the above list of bindings further. After all, the outlier binding(1, 0) -> 1
is in the middle!I therefore added a shrink log of successful shrink attempts by replacing l.355 of
QCheck2_expect_test.ml
with:After rerunning the tests, this revealed the following in _build/default/test/core/funshrinklog.txt:
This looks fishy to me: while the first elements of the tuple are reduced, the last one (the function table) actually gets longer in each attempt!
I think this is actually due to how
Gen.triple
is currently defined (and thus shrinks). I'll therefore add some tests for it and report separately.Originally posted by @jmid in #153 (comment)
The text was updated successfully, but these errors were encountered: