diff --git a/lib_bam/std.ml b/lib_bam/std.ml index 77f4fe9..c0e4318 100644 --- a/lib_bam/std.ml +++ b/lib_bam/std.ml @@ -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 diff --git a/lib_bam/std.mli b/lib_bam/std.mli index 6407cdd..04f3bcb 100644 --- a/lib_bam/std.mli +++ b/lib_bam/std.mli @@ -118,7 +118,7 @@ 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]. *) @@ -126,7 +126,7 @@ val int : ?shrinker:int Shrinker.t -> ?min:int -> ?max:int -> unit -> int t 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]. *) @@ -134,7 +134,7 @@ val int32 : 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]. *) @@ -142,7 +142,7 @@ val int64 : 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.]. *) diff --git a/test/expected/std.ml/std oneof.out b/test/expected/std.ml/std oneof.out new file mode 100644 index 0000000..3d64d84 --- /dev/null +++ b/test/expected/std.ml/std oneof.out @@ -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 diff --git a/test/main.ml b/test/main.ml index ac7ae4e..6e8ff9c 100644 --- a/test/main.ml +++ b/test/main.ml @@ -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 () diff --git a/test/std.ml b/test/std.ml new file mode 100644 index 0000000..757cea5 --- /dev/null +++ b/test/std.ml @@ -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 () diff --git a/tezt-bam.opam b/tezt-bam.opam index aa1647e..73e947d 100644 --- a/tezt-bam.opam +++ b/tezt-bam.opam @@ -14,7 +14,7 @@ depends: [ "dune" {>= "3.7"} "tezt" "bam" - "mtime" + "mtime" {>= "2.0"} "odoc" {with-doc} ] build: [