jon.recoil.org

Module Base_quickcheck.GeneratorSource

Generators are sources of random values. Every randomized test needs a generator to produce its inputs.

Sourcetype +('a : any) t

Basic Generators

These are good default generators for tests over types from OCaml and Base. They are designed to hit corner cases reasonably often, and also generate reasonably good coverage of common cases and arbitrary values.

Sourceval either : ('a : value_or_null) ('b : value_or_null). 'a Base_quickcheck.Generator.t -> 'b Base_quickcheck.Generator.t -> ('a, 'b) Base.Either.t Base_quickcheck.Generator.t
Sourceval result : ('a : value_or_null) ('b : value_or_null). 'a Base_quickcheck.Generator.t -> 'b Base_quickcheck.Generator.t -> ('a, 'b) Base.Result.t Base_quickcheck.Generator.t

This helper module type exists separately just to open Bigarray in its scope.

Sourceval fn : ('a : value_or_null) ('b : value_or_null). 'a Base_quickcheck__.Observer0.t -> 'b Base_quickcheck.Generator.t -> ('a -> 'b) Base_quickcheck.Generator.t @@ portable

Generates random functions that use the given observer to perturb the pseudo-random state that is then used to generate the output value. The resulting functions are therefore deterministic, assuming the observer is deterministic.

Sourceval map_t_m : 'key 'data 'cmp. ('key, 'cmp) Base.Comparator.Module.t -> 'key Base_quickcheck.Generator.t -> 'data Base_quickcheck.Generator.t -> ('key, 'data, 'cmp) Base.Map.t Base_quickcheck.Generator.t @@ portable
Sourceval set_t_m : ('elt, 'cmp) Base.Comparator.Module.t -> 'elt Base_quickcheck.Generator.t -> ('elt, 'cmp) Base.Set.t Base_quickcheck.Generator.t @@ portable
Sourceval map_tree_using_comparator : 'key 'data 'cmp. comparator:('key, 'cmp) Base.Comparator.t -> 'key Base_quickcheck.Generator.t -> 'data Base_quickcheck.Generator.t -> ('key, 'data, 'cmp) Base.Map.Using_comparator.Tree.t Base_quickcheck.Generator.t @@ portable
Sourceval set_tree_using_comparator : comparator:('elt, 'cmp) Base.Comparator.t -> 'elt Base_quickcheck.Generator.t -> ('elt, 'cmp) Base.Set.Using_comparator.Tree.t Base_quickcheck.Generator.t @@ portable

Combining and Modifying Generators

Sourceval of_list : 'a. 'a Base.list -> 'a Base_quickcheck.Generator.t @@ portable

Produces any of the given values, weighted uniformly.

Sourceval union : ('a : value_or_null). 'a Base_quickcheck.Generator.t Base.list -> 'a Base_quickcheck.Generator.t @@ portable

Chooses among the given generators, weighted uniformly; then chooses a value from that generator.

include Base.Applicative.S__'value_or_null_mod_maybe_null' with type ('a : value_or_null) t := 'a Base_quickcheck.Generator.t

Applies the functions in one t to the values in another. Well-behaved applicatives satisfy these "laws", using <*> as infix apply:

  • return Fn.id <*> t is equivalent to t
  • return Fn.compose <*> tf <*> tg <*> tx is equivalent to tf <*> (tg <*> tx)
  • return f <*> return x is equivalent to return (f x)
  • tf <*> return x is equivalent to return (fun f -> f x) <*> tf

Combines values in two ts as tuples. Using <*> as infix apply, equivalent to return (fun a b -> a, b) <*> ta <*> tb.

Sourceval map2 : 'a 'b 'c 'p 'q. 'a Base_quickcheck.Generator.t -> 'b Base_quickcheck.Generator.t -> f:('a -> 'b -> 'c) -> 'c Base_quickcheck.Generator.t

Combines the contents of two ts. Using <*> as infix apply, equivalent to return f <*> ta <*> tb.

Sourceval map3 : 'a 'b 'c 'd 'p 'q. 'a Base_quickcheck.Generator.t -> 'b Base_quickcheck.Generator.t -> 'c Base_quickcheck.Generator.t -> f:('a -> 'b -> 'c -> 'd) -> 'd Base_quickcheck.Generator.t

Combines the contents of three ts. Using <*> as infix apply, equivalent to return f <*> ta <*> tb <*> tc.

Sourcemodule Applicative_infix : sig ... end
include Base.Monad.S__'value_or_null_mod_maybe_null' with type ('a : value_or_null) t := 'a Base_quickcheck.Generator.t
Sourceval return : 'a 'i 'p 'q. 'a -> 'a Base_quickcheck.Generator.t

Convert a value to a t.

Sourceval map : 'a 'b 'i 'j 'p 'q. 'a Base_quickcheck.Generator.t -> f:('a -> 'b) -> 'b Base_quickcheck.Generator.t

Transforms the contents of a t.

Sourceval bind : 'a 'b 'i 'j 'k 'p 'q. 'a Base_quickcheck.Generator.t -> f:('a -> 'b Base_quickcheck.Generator.t) -> 'b Base_quickcheck.Generator.t

Sequences computations. bind t ~f computes f v for value(s) v in t. Well-behaved monads satisfy these "laws" (where ( >>= ) is the infix bind operator):

  • map t ~f is equivalent to bind t ~f:(fun x -> return (f x))
  • return x >>= f is equivalent to f x
  • t >>= return is equivalent to t
  • (t >>= f) >>= g is equivalent to t >>= fun x -> f x >>= g

Combines nested t into just one layer. Equivalent to bind t ~f:Fn.id.

Sourceval ignore_m : 'a 'i 'j 'p 'q. 'a Base_quickcheck.Generator.t -> unit Base_quickcheck.Generator.t

Ignores contained values of t. Equivalent to map t ~f:ignore.

Sourceval all : 'a 'i 'p 'q. 'a Base_quickcheck.Generator.t list -> 'a list Base_quickcheck.Generator.t

Combines a list of t.

Sourceval all_unit : 'i 'p 'q. unit Base_quickcheck.Generator.t list -> unit Base_quickcheck.Generator.t

Combines a list of t whose contents are unimportant.

Sourceval (>>=) : 'a 'b 'i 'j 'k 'p 'q. 'a Base_quickcheck.Generator.t -> ('a -> 'b Base_quickcheck.Generator.t) -> 'b Base_quickcheck.Generator.t

Infix bind.

Sourceval (>>|) : 'a 'b 'i 'j 'p 'q. 'a Base_quickcheck.Generator.t -> ('a -> 'b) -> 'b Base_quickcheck.Generator.t

Infix map.

Sourcemodule Monad_infix : sig ... end
Sourcemodule Let_syntax : sig ... end
Sourcemodule Portable : sig ... end

Size of Random Values

Base_quickcheck threads a size parameter through generators to limit the size of unbounded types. Users of Base_quickcheck often do not need to think about the size parameter; the default generators handle it sensibly. Generators of atomic types ignore it, generators of bounded-size containers like both and either thread it through unchanged, and generators of unbounded-size containers like list and set_t_m distribute the size they are given among their constituents.

The bindings below allow direct manipulation of the size parameter in cases where users want a custom treatment of sizes. There is no prescribed meaning of the size parameter for any given type other than that it must be non-negative. As a general guideline, however, the time and space used to generate a value should be proportional to the size parameter at most.

The size parameter should be treated as an upper bound but not as a lower bound, so for example a generator given a size parameter of 2 should have a chance to generate values of size 0 or 1 as well. If the size parameter is treated as a lower bound, then for example members of tuples will always be generated at the same size, and test cases for members of different size will not be covered.

Returns the current size parameter.

Sourceval with_size : ('a : value_or_null). 'a Base_quickcheck.Generator.t -> size:Base.int -> 'a Base_quickcheck.Generator.t @@ portable

Produces a generator that ignores the size parameter passed in by Base_quickcheck and instead uses the given ~size argument. Most often used with size to reduce the size when dispatching to generators for subparts of a value.

For example, here is a use of with_size and size to create a generator for optional lists. We are careful to generate None even at non-zero sizes; see the note above about not using size as a lower bound.

  let optional_list generator =
    let open Let_syntax in
    match%bind both size bool with
    | 0, _ | _, false -> return None
    | k, _ ->
      let%map elements = with_size ~size:(k - 1) (list generator) in
      Some elements
  ;;
Sourceval sizes : ?min_length:Base.int -> ?max_length:Base.int -> Base.unit -> Base.int Base.list Base_quickcheck.Generator.t @ portable @@ portable

Produces a list of sizes that distribute the current size among list elements. The min_length and max_length parameters can be used to bound the length of the result.

This is the distribution used by generators such as list to divide up size among elements.

This function is designed so that elements of list are always generated at strictly smaller size than the list itself. The technical invariant is: if size_list is generated by with_size ~size:n (sizes ~min_length ()), then:

  List.length size_list - min_length + List.sum (module Int) size_list <= n

Filtering Generators

Sourceval filter : ('a : value_or_null). 'a Base_quickcheck.Generator.t -> f:('a -> Base.bool) -> 'a Base_quickcheck.Generator.t @@ portable

Produces values for which f returns true. If f returns false, retries with size incremented by 1. This avoids filter getting stuck if all values at a given size fail f; see the note above about not using size as a lower bound.

Sourceval filter_map : ('a : value_or_null) ('b : value_or_null). 'a Base_quickcheck.Generator.t -> f:('a -> 'b Base.option) -> 'b Base_quickcheck.Generator.t @@ portable

When f produces Some x, produces x. If f returns None, retries with size incremented by 1, as with filter.

Generating Recursive Values

Ties the recursive knot to produce generators for recursive types that have multiple clauses, separating base cases from recursive cases. At size 0, only base cases are produced; at size n > 0, the base cases are produced at size n along with the recursive cases at size n-1. Raises if the list of base cases is empty or if the list of recursive cases is empty.

For example, here is a use of recursive_union to create a generator for an expression datatype.

  type exp =
    | Int of int
    | Bool of bool
    | If of exp * exp * exp
    | Add of exp * exp

  let exp_generator =
    recursive_union
      [ map int ~f:(fun i -> Int i); map bool ~f:(fun b -> Bool b) ]
      ~f:(fun exp ->
        let open Let_syntax in
        [ (let%map a = exp
           and b = exp
           and c = exp in
           If (a, b, c))
        ; (let%map a = exp
           and b = exp in
           Add (a, b))
        ])
  ;;
Sourceval fixed_point : ('a : value_or_null). ('a Base_quickcheck.Generator.t -> 'a Base_quickcheck.Generator.t) -> 'a Base_quickcheck.Generator.t @@ portable

Like recursive_union, without separate clauses or automatic size management. Useful for generating recursive types that don't fit the clause structure of recursive_union.

For example, here is a use of fixed_point to create a generator for N-ary trees. No manual size management is needed, as Generator.list guarantees to generate list elements at strictly smaller sizes than the list itself.

  type tree = Node of tree list

  let tree_generator =
    fixed_point (fun tree -> map (list tree) ~f:(fun trees -> Node trees))
  ;;
Sourceval of_lazy : ('a : value_or_null). 'a Base_quickcheck.Generator.t Base.Lazy.t -> 'a Base_quickcheck.Generator.t @@ portable

Creates a t that forces the lazy argument as necessary. Can be used to tie (mutually) recursive knots.

Sourceval of_portable_lazy : ('a : value_or_null). 'a Base_quickcheck.Generator.t Base.Portable_lazy.t @ portable -> 'a Base_quickcheck.Generator.t @ portable @@ portable

Like of_lazy, but for Portable_lazy.t.

Custom Random Distributions

Sourceval of_weighted_list : ('a : value_or_null). (Base.float * 'a) Base.list -> 'a Base_quickcheck.Generator.t @@ portable

Produces one of the given values, chosen with the corresponding weight. Weights must be non-negative and must have a strictly positive sum.

Sourceval weighted_union : ('a : value_or_null). (Base.float * 'a Base_quickcheck.Generator.t) Base.list -> 'a Base_quickcheck.Generator.t @@ portable

Produces one of the given generators, chosen with the corresponding weight, then chooses a value from that generator. Weights must be non-negative and must have a strictly positive sum.

Sourceval weighted_recursive_union : ('a : value_or_null). (Base.float * 'a Base_quickcheck.Generator.t) Base.list -> f: ('a Base_quickcheck.Generator.t -> (Base.float * 'a Base_quickcheck.Generator.t) Base.list) -> 'a Base_quickcheck.Generator.t @@ portable

Like recursive_union, with explicit weights for each clause. Weights must be non-negative and the recursive case weights must have a strictly positive sum.

Integer Distributions

Sourceval small_positive_or_zero_int : Base.int Base_quickcheck.Generator.t @@ portable

Produces an integer between 0 and an unspecified upper bound which is proportional to size. This is a good generator to use for sizes of values like strings which have a variable number of fixed-size elements.

Sourceval small_strictly_positive_int : Base.int Base_quickcheck.Generator.t @@ portable

Like small_positive_or_zero_int but with a minimum of 1.

Uniform Unbounded Distributions

These generators produce any value of the relevant integer type with uniform weight. The default generators for these types differ in that they give higher weight to corner cases, e.g. min_value and max_value.

Sourceval int_uniform : Base.int Base_quickcheck.Generator.t @@ portable
Sourceval int32_uniform : Base.int32 Base_quickcheck.Generator.t @@ portable
Sourceval int63_uniform : Base.Int63.t Base_quickcheck.Generator.t @@ portable
Sourceval int64_uniform : Base.int64 Base_quickcheck.Generator.t @@ portable
Sourceval nativeint_uniform : Base.nativeint Base_quickcheck.Generator.t @@ portable
Bounded Distributions

These generators produce any value between the given inclusive bounds, which must be given in nondecreasing order. Higher weight is given to corner cases, e.g. the bounds themselves.

Sourceval int_inclusive : Base.int -> Base.int -> Base.int Base_quickcheck.Generator.t @ portable @@ portable
Sourceval int32_inclusive : Base.int32 -> Base.int32 -> Base.int32 Base_quickcheck.Generator.t @ portable @@ portable
Sourceval int63_inclusive : Base.Int63.t -> Base.Int63.t -> Base.Int63.t Base_quickcheck.Generator.t @ portable @@ portable
Sourceval int64_inclusive : Base.int64 -> Base.int64 -> Base.int64 Base_quickcheck.Generator.t @ portable @@ portable
Sourceval nativeint_inclusive : Base.nativeint -> Base.nativeint -> Base.nativeint Base_quickcheck.Generator.t @ portable @@ portable
Uniform Bounded Distributions

These generators produce any value between the given inclusive bounds, which must be given in nondecreasing order. All values are given equal weight.

Sourceval int_uniform_inclusive : Base.int -> Base.int -> Base.int Base_quickcheck.Generator.t @ portable @@ portable
Sourceval int32_uniform_inclusive : Base.int32 -> Base.int32 -> Base.int32 Base_quickcheck.Generator.t @ portable @@ portable
Sourceval int63_uniform_inclusive : Base.Int63.t -> Base.Int63.t -> Base.Int63.t Base_quickcheck.Generator.t @ portable @@ portable
Sourceval int64_uniform_inclusive : Base.int64 -> Base.int64 -> Base.int64 Base_quickcheck.Generator.t @ portable @@ portable
Sourceval nativeint_uniform_inclusive : Base.nativeint -> Base.nativeint -> Base.nativeint Base_quickcheck.Generator.t @ portable @@ portable
Uniform in Log Space Distributions

These generators produce any value between the given inclusive, non-negative bounds, choosing bit-length in that range uniformly and then uniformly among values with that bit-length between the bounds. The bounds must be given in nondecreasing order.

Sourceval int_log_uniform_inclusive : Base.int -> Base.int -> Base.int Base_quickcheck.Generator.t @ portable @@ portable
Sourceval int32_log_uniform_inclusive : Base.int32 -> Base.int32 -> Base.int32 Base_quickcheck.Generator.t @ portable @@ portable
Sourceval int63_log_uniform_inclusive : Base.Int63.t -> Base.Int63.t -> Base.Int63.t Base_quickcheck.Generator.t @ portable @@ portable
Sourceval int64_log_uniform_inclusive : Base.int64 -> Base.int64 -> Base.int64 Base_quickcheck.Generator.t @ portable @@ portable
Sourceval nativeint_log_uniform_inclusive : Base.nativeint -> Base.nativeint -> Base.nativeint Base_quickcheck.Generator.t @ portable @@ portable
Log Space Distributions

Like the *_log_uniform_inclusive bindings above, but giving additional weight to corner cases, e.g. the given bounds.

Sourceval int_log_inclusive : Base.int -> Base.int -> Base.int Base_quickcheck.Generator.t @ portable @@ portable
Sourceval int32_log_inclusive : Base.int32 -> Base.int32 -> Base.int32 Base_quickcheck.Generator.t @ portable @@ portable
Sourceval int63_log_inclusive : Base.Int63.t -> Base.Int63.t -> Base.Int63.t Base_quickcheck.Generator.t @ portable @@ portable
Sourceval int64_log_inclusive : Base.int64 -> Base.int64 -> Base.int64 Base_quickcheck.Generator.t @ portable @@ portable
Sourceval nativeint_log_inclusive : Base.nativeint -> Base.nativeint -> Base.nativeint Base_quickcheck.Generator.t @ portable @@ portable
Geometric Distributions

These generators produce a geometric distribution with a given minimum and probabilty p. In other words, with probability p, the minimum is produced. Otherwise, a value is effectively produced from a geometric distribution with the same p and a minimum one higher, although the implementation can be more efficent than this. If the result overflows, the function returns max_value for the integer type.

Raises if p <. 0. || 1. <. p..

Sourceval int_geometric : Base.int -> p:Base.float -> Base.int Base_quickcheck.Generator.t @ portable @@ portable
Sourceval int32_geometric : Base.int32 -> p:Base.float -> Base.int32 Base_quickcheck.Generator.t @ portable @@ portable
Sourceval int63_geometric : Base.Int63.t -> p:Base.float -> Base.Int63.t Base_quickcheck.Generator.t @ portable @@ portable
Sourceval int64_geometric : Base.int64 -> p:Base.float -> Base.int64 Base_quickcheck.Generator.t @ portable @@ portable
Sourceval nativeint_geometric : Base.nativeint -> p:Base.float -> Base.nativeint Base_quickcheck.Generator.t @ portable @@ portable

Floating Point Distributions

Sourceval float_inclusive : Base.float -> Base.float -> Base.float Base_quickcheck.Generator.t @ portable @@ portable

Generates values between the given bounds, inclusive, which must be finite and in nondecreasing order. Weighted toward boundary values.

Sourceval float_uniform_exclusive : Base.float -> Base.float -> Base.float Base_quickcheck.Generator.t @ portable @@ portable

Generates values between the given bounds, exclusive, which must be finite and in increasing order, with at least one float value between them. Weighted approximately uniformly across the resulting range, rounding error notwithstanding.

Sourceval float_without_nan : Base.float Base_quickcheck.Generator.t @@ portable
Sourceval float_finite : Base.float Base_quickcheck.Generator.t @@ portable
Sourceval float_strictly_positive : Base.float Base_quickcheck.Generator.t @@ portable
Sourceval float_strictly_negative : Base.float Base_quickcheck.Generator.t @@ portable
Sourceval float_positive_or_zero : Base.float Base_quickcheck.Generator.t @@ portable
Sourceval float_negative_or_zero : Base.float Base_quickcheck.Generator.t @@ portable
Sourceval float_of_class : Base.Float.Class.t -> Base.float Base_quickcheck.Generator.t @ portable @@ portable

Character Distributions

Sourceval char_lowercase : Base.char Base_quickcheck.Generator.t @@ portable
Sourceval char_uppercase : Base.char Base_quickcheck.Generator.t @@ portable
Sourceval char_digit : Base.char Base_quickcheck.Generator.t @@ portable
Sourceval char_alpha : Base.char Base_quickcheck.Generator.t @@ portable
Sourceval char_alphanum : Base.char Base_quickcheck.Generator.t @@ portable
Sourceval char_whitespace : Base.char Base_quickcheck.Generator.t @@ portable
Sourceval char_print : Base.char Base_quickcheck.Generator.t @@ portable
Sourceval char_uniform_inclusive : Base.char -> Base.char -> Base.char Base_quickcheck.Generator.t @ portable @@ portable

String Distributions

Sourceval string_non_empty : Base.string Base_quickcheck.Generator.t @@ portable
Sourceval string_with_length : length:Base.int -> Base.string Base_quickcheck.Generator.t @ portable @@ portable
Sourceval string_like : Base.string -> Base.string Base_quickcheck.Generator.t @ portable @@ portable

Produces strings similar to the input, with some number of edits.

Sexp Distributions

Produces s-expressions whose atoms are chosen from the given string distribution.

List Distributions

Sourceval list_non_empty : ('a : value_or_null). 'a Base_quickcheck.Generator.t -> 'a Base.list Base_quickcheck.Generator.t @@ portable
Sourceval list_with_length : ('a : value_or_null). 'a Base_quickcheck.Generator.t -> length:Base.int -> 'a Base.list Base_quickcheck.Generator.t @@ portable
Sourceval list_filtered : 'a Base.list -> 'a Base.list Base_quickcheck.Generator.t @@ portable

Randomly drops elements from a list. The length of each result is chosen uniformly between 0 and the length of the input, inclusive.

Sourceval list_permutations : 'a Base.list -> 'a Base.list Base_quickcheck.Generator.t @@ portable

Produces permutations of the given list, weighted uniformly.

Sourceval fold_until : ?min_length:Base.int -> ?max_length:Base.int -> init:'acc -> f: ('acc -> ('acc, 'final) Base.Continue_or_stop.t Base_quickcheck.Generator.t) -> finish:('acc -> 'final) -> Base.unit -> 'final Base_quickcheck.Generator.t @@ portable

Bigarray Distributions

Low-Level Interface

These functions provide direct access to the pseudo-random state threaded through Base_quickcheck generators. Most users should not need these functions.

Sourceval perturb : ('a : value_or_null). 'a Base_quickcheck.Generator.t -> Base.int -> 'a Base_quickcheck.Generator.t @@ portable

Passes in additional "salt" used to perturb the pseudo-random state used to generate random values. Generators' output is intended to be deterministic for any initial pseudorandom state, so perturb can be used to generate a new generator with the same distribution that nonetheless produces different values from the original for any given pseudo-random state.

Sourceval create : ('a : value_or_null). (size:Base.int -> random:Splittable_random.t -> 'a) -> 'a Base_quickcheck.Generator.t @@ portable

Creates a generator that calls the given function with the current size parameter and pseudorandom state.

Sourceval generate : ('a : value_or_null). 'a Base_quickcheck.Generator.t -> size:Base.int -> random:Splittable_random.t -> 'a @@ portable

Generates a random value using the given size and pseudorandom state. Useful when using create and dispatching to other existing generators.

Sourcemodule Via_thunk : sig ... end
Sourcemodule Debug : sig ... end