Skip to content

Less exhaustive string shrinking #278

@jmid

Description

@jmid

As the new QCheck.Shrink.string unit tests document, on a failure path (going through all shrinking candidates without luck) the current approach may be a bit too exhaustive:

("string \"vi5x92xgG\"", "vi5x92xgG", (* A less exhaustive string shrinker would be preferable *)
["vi5x9"; "vi52xgG"; "vix92xgG"; "5x92xgG";
"v5x92xgG"; "i5x92xgG"; "li5x92xgG"; "qi5x92xgG"; "ti5x92xgG"; "ui5x92xgG";
"ve5x92xgG"; "vg5x92xgG"; "vh5x92xgG";
"viKx92xgG"; "vi@x92xgG"; "vi:x92xgG"; "vi7x92xgG"; "vi6x92xgG";
"vi5m92xgG"; "vi5s92xgG"; "vi5v92xgG"; "vi5w92xgG";
"vi5xM2xgG"; "vi5xC2xgG"; "vi5x>2xgG"; "vi5x;2xgG"; "vi5x:2xgG";
"vi5x9IxgG"; "vi5x9=xgG"; "vi5x97xgG"; "vi5x94xgG"; "vi5x93xgG";
"vi5x92mgG"; "vi5x92sgG"; "vi5x92vgG"; "vi5x92wgG";
"vi5x92xdG"; "vi5x92xfG";
"vi5x92xgT"; "vi5x92xgM"; "vi5x92xgJ"; "vi5x92xgH"]);

By falling back on Shrink.list_spine we get a nice and short candidate sequence when we stay clear of element reduction:

# Shrink.string ~shrink:Shrink.nil "zzzzz" (fun xs -> Printf.printf "%s\n" Print.(string xs));;
zzz
zzzz
zzz
zzzz

However, exhaustively trying to reduce all O(n) entries, say O(log n) times, brings this to O(n log n) which may be a bit much:

# Shrink.string ~shrink:Shrink.char "zzzzz" (fun xs -> Printf.printf "%s\n" Print.(string xs));;
zzz
zzzz
zzz
zzzz
nzzzz
tzzzz
wzzzz
yzzzz
znzzz
ztzzz
zwzzz
zyzzz
zznzz
zztzz
zzwzz
zzyzz
zzznz
zzztz
zzzwz
zzzyz
zzzzn
zzzzt
zzzzw
zzzzy

We are getting bitten by this in ocaml-multicore/multicoretests, as remarked by @edwintorok here: ocaml-multicore/multicoretests#329 (comment)

As an alternative to avoiding character-shrinks above a certain threshold, one could consider alternative approaches, e.g.

  • reducing only the first non-'a' char
  • reducing several chars simultaneously "zzzzz" -> "aaazz"
  • ...

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions