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

[qcheck-STM] Emit a function to shrink cmd arguments #269

Open
jmid opened this issue Oct 24, 2024 · 0 comments · May be fixed by #272
Open

[qcheck-STM] Emit a function to shrink cmd arguments #269

jmid opened this issue Oct 24, 2024 · 0 comments · May be fixed by #272
Labels
enhancement New feature or request good first issue Good for newcomers qcheck-stm

Comments

@jmid
Copy link

jmid commented Oct 24, 2024

QCheck-STM will by default only shrink cmd lists.
In practice, this means that, e.g., the random argument -5 passed to Hashtbl.create (-5) will not be shrunk to the minimal Hashtbl.create (-1) before being printed.

To enable argument shrinking one has to write/emit a shrink_cmd function and pass it to arb_cmd.
Here's an example from multicoretests:
https://github.com/ocaml-multicore/multicoretests/blob/160394955526794ab5349ce683d9b7664d43bcb9/src/weak/stm_tests.ml#L33-L47

  let shrink_cmd c = match c with
    | Length -> Iter.empty
    | Set (i, d_opt) -> Iter.map (fun i -> Set (i,d_opt)) (Shrink.int i)
    | Get i      -> Iter.map (fun i -> Get i) (Shrink.int i)
    | Get_copy i -> Iter.map (fun i -> Get_copy i) (Shrink.int i)
    | Check i    -> Iter.map (fun i -> Check i) (Shrink.int i)
    | Fill (i,j,d_opt) ->
      Iter.(map (fun i -> Fill (i,j,d_opt)) (Shrink.int i)
            <+>
            map (fun j -> Fill (i,j,d_opt)) (Shrink.int j))

  let arb_cmd s =
    [...]
    QCheck.make ~print:show_cmd ~shrink:shrink_cmd [...]
  • When no shrinking is needed (e.g., if there are no arguments or only a unit arg) one can just return the empty iterator Iter.empty
  • When there's only one argument, one can use Iter.map over a built-in shrinker combinator from QCheck, e.g., of int, char, string, ...
  • When there's more than one argument, we should shrink each argument separately. The Fill above case does this by composing two iterators with <+> (a shorthand for Iter.append). Why? Because a shrinker of i may return the empty iterator, if i is already minimal, e.g., 0 and we don't want the shrinker to only reduce when both i and j can be reduced. Their shrinking should be independent.
@n-osborne n-osborne added enhancement New feature or request good first issue Good for newcomers qcheck-stm labels Oct 24, 2024
@nikolaushuber nikolaushuber linked a pull request Nov 2, 2024 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request good first issue Good for newcomers qcheck-stm
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants