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

Std: Fix the Std.oneof generator #1

Merged
merged 5 commits into from
May 3, 2024
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
4 changes: 2 additions & 2 deletions lib_bam/std.ml
Original file line number Diff line number Diff line change
Expand Up @@ -257,14 +257,14 @@ let oneof : ?shrinker:int Shrinker.t -> (int * 'a Gen.t) list -> 'a Gen.t =
raise
@@ invalid_arg
"[Std.oneof] was called with a weighted_list whose weights sum is 0." ;
let* i = int ?shrinker ~min:0 ~max:total () in
let* i = int ?shrinker ~min:0 ~max:(total - 1) () in
List.fold_left
(fun (acc, gen') (weight, gen) ->
match gen' with
| Some gen ->
(acc, Some gen)
| None ->
if i <= acc then (acc, Some gen) else (acc + weight, None) )
if i < acc + weight then (acc, Some gen) else (acc + weight, None) )
(0, None) weighted_list
|> snd
|> function None -> assert false | Some gen -> gen
Expand Down
8 changes: 4 additions & 4 deletions lib_bam/std.mli
Original file line number Diff line number Diff line change
Expand Up @@ -118,31 +118,31 @@ val crunch : int -> 'a t -> 'a t

val int : ?shrinker:int Shrinker.t -> ?min:int -> ?max:int -> unit -> int t
(** [int ?shrinker ?(min=0) ?(max=Int.max_int) ()] is a generator for
integers. [min] is inclusive while [max] is exclusive.
integers. Bounds are inclusive.

Default strategy is {!constructor:Shrinker.Int}[0].
*)

val int32 :
?shrinker:int32 Shrinker.t -> ?min:int32 -> ?max:int32 -> unit -> int32 t
(** [int ?shrinker ?(min=0) ?(max=Int.max_int) ()] is a generator for
integers. [min] is inclusive while [max] is exclusive.
integers. Bounds are inclusive.

Default strategy is {!constructor:Shrinker.Int}[0].
*)

val int64 :
?shrinker:int64 Shrinker.t -> ?min:int64 -> ?max:int64 -> unit -> int64 t
(** [int ?shrinker ?(min=0) ?(max=Int.max_int) ()] is a generator for
integers. [min] is inclusive while [max] is exclusive.
integers. Bounds are inclusive.

Default strategy is {!constructor:Shrinker.Int}[0].
*)

val float :
?shrinker:float Shrinker.t -> ?min:float -> ?max:float -> unit -> float t
(** [float ?shrinker ?(min=0.) ?(max=Float.max_float) ()] generates
integers. [min] is inclusive while [max] is exclusive.
integers. Bounds are inclusive.

Default strategy is {!constructor:Shrinker.Float}[0.].
*)
Expand Down
1 change: 1 addition & 0 deletions test/expected/std.ml/std oneof.out
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1 1 2 4 5 5 5 6 7 7 8 9 9 10 103 124 124 134 135 135 160 161 161 175 1461 1913 4545 4684 4968 9349
7 changes: 6 additions & 1 deletion test/main.ml
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
open Tezt

let () = Tree.register () ; Gen.register () ; Pbt.register () ; Test.run ()
let () =
Tree.register () ;
Gen.register () ;
Std.register () ;
Pbt.register () ;
Test.run ()
38 changes: 38 additions & 0 deletions test/std.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
open Tezt_bam

let std_int_range_inclusive_bounds () =
Test.register ~__FILE__ ~title:"std int range inclusive bounds"
~tags:["std"; "int"; "range"]
@@ fun () ->
let values =
Seq.ints 0 |> Seq.take 10_000
|> Seq.map (fun i ->
let gen = Bam.Std.int ~min:0 ~max:10 () in
Bam.Gen.run gen (Bam.Gen.Random.make [|i|]) |> Bam.Tree.root )
|> List.of_seq |> List.sort_uniq compare
in
let expected = List.init 11 Fun.id in
if values = expected then Lwt.return_unit
else Test.fail "Did not draw all the integers in the interval"

let std_oneof () =
Regression.register ~__FILE__ ~title:"std oneof" ~tags:["std"; "oneof"]
@@ fun () ->
let values =
Seq.ints 0 |> Seq.take 30
|> Seq.map (fun i ->
let small_gen = Bam.Std.int ~min:0 ~max:10 () in
let medium_gen = Bam.Std.int ~min:100 ~max:200 () in
let large_gen = Bam.Std.int ~min:1000 ~max:10_000 () in
let gen =
Bam.Std.oneof [(3, small_gen); (2, medium_gen); (1, large_gen)]
in
Bam.Gen.run gen (Bam.Gen.Random.make [|i|]) |> Bam.Tree.root )
|> List.of_seq |> List.sort compare
in
let str = values |> List.map string_of_int |> String.concat " " in
Regression.capture str ; Lwt.return_unit

let register () =
std_int_range_inclusive_bounds () ;
std_oneof ()
2 changes: 1 addition & 1 deletion tezt-bam.opam
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ depends: [
"dune" {>= "3.7"}
"tezt"
"bam"
"mtime"
"mtime" {>= "2.0"}
"odoc" {with-doc}
]
build: [
Expand Down