Module eqc_gen

This module implements QuickCheck generators.

Copyright © Quviq AB, 2004-2023

Version: 1.46.3

Description

This module implements QuickCheck generators. QuickCheck generators are used to generate random test data for QuickCheck properties. A generator specifies three things at the same time: QuickCheck permits constants to be used as generators for their own value, and also permits tuples, records, and lists containing generators to be used as generators for values of the same form. For example,
 {int(), bool()} 
is a generator that generates random pairs of integers and booleans.

Many of the functions in this module are usually used via macros, defined in eqc.hrl. These macros are listed here.

?LET(Pat, G1, G2)

Generates a value from G1, binds it to Pat, then generates a value from G2 (which may refer to the variables bound in Pat).

The result is shrunk by first shrinking the value generated by G1 while the test still fails, then shrinking the value generated by G2. It is thus better to write ?LET({X, Y}, {G1, G2}, G3) than ?LET(X, G1, ?LET(Y, G2, G3)) (provided G2 does not depend on X), since in the first case shrinking can shrink G1 a bit, shrink G2, then shrink G1 some more, while in the second case G1 cannot be shrunk further once shrinking G2 has begun.

?SIZED(Size, G)

Binds the variable Size to the current size parameter for generation. G may use Size in any way to control the size of generated data. However, as Size increases, the set of possible values that G can generate should also increase. Size is always a natural number, and increases during QuickCheck testing from a small value up to about 40. See also resize/2.

?SUCHTHAT(X, G, P)

Generates values X from G such that the condition P is true. Should only be used if the probability that P holds is reasonably high for values generated by G--otherwise generation may be slow, and the distribution of generated values may be skewed. For example,
?SUCHTHAT(Xs, list(int()), lists:sort(Xs)==Xs)
generates predominantly very short lists, since the probability that a random longer list will just happen to be sorted is very low. If no value is found within 100 attempts, then ?SUCHTHAT exits.

?SUCHTHATMAYBE(X, G, P)

Generates either {value, X}, where X is generated by G and satisfies P, or false if no such X is found in a reasonable time.

?SHRINK(G, Gs)

Generates a value from G, which can be shrunk to a value generated by any generator in the list Gs.

?LETSHRINK(Pat, G1, G2)

This behaves in the same way as ?LET(Pat, G1, G2), except that G1 must generate a list of values, and each one of these values is added as a possible shrinking of the result. This is intended for use in generating tree - like structures. For example,
 ?LETSHRINK([L, R], [tree(), tree()], {branch, L, R})
generates a tree node {branch, L, R}, which can shrink to either L or R.

?LAZY(G)

A generator equivalent to its argument, but which is always cheap to construct. To be used, for example, in recursive generators to avoid building a huge generator, only a small part of which will be used.

Data Types

box()

abstract datatype: box(A)

gen()

abstract datatype: gen(A)

suspension()

abstract datatype: suspension(A)

Function Index

binary/0Generates a binary of random size.
binary/1Generates a binary of a given size in bytes.
bitstring/0Generates a list of bits in a bitstring.
bitstring/1Generates a bitstring of a given size in bits.
bool/0Generates a random boolean.
char/0Generates a random character.
choose/2Generates a number in the range M to N.
constrain_shrinking/2Constrain the shrinking behaviour of a generator to only consider shrinking step satisfying the given relation.
default/2Adds a default value to a generator, to be chosen half the time.
elements/1Generates an element of the list argument.
fault/2Adds a fault - generation alternative to a generator.
fault_rate/3Specifies that faulty data should be generated by any uses of fault/2 within G on M out of N occasions.
frequency/1Makes a weighted choice between the generators in its argument, such that the probability of choosing each generator is proportional to the weight paired with it.
function0/1Generates a function of no arguments with result generated by G.
function1/1Generates a function of one argument with result generated by G.
function2/1Generates a function of two arguments with result generated by G.
function3/1Generates a function of three arguments with result generated by G.
function4/1Generates a function of four arguments with result generated by G.
growingelements/1Generates an element of the list argument.
int/0Generates a small integer (with absolute value bounded by the generation size).
largebinary/0Equivalent to largebinary({limit, 255, 65535}).
largebinary/1largebinary(X) is equivalent to largebinary({fixed, X}, []),.
largebinary/2A generator for large binaries.
largeint/0Generates an integer from a large range.
less_faulty/2Decreases the fault rate within G by a factor M.
list/1Generates a list of elements generated by its argument.
list/2Generates a list of elements generated by its argument, of length at most MaxLen.
map/2Generates a map with keys generated by K and values generated by V.
more_faulty/2Increases the fault rate within G by a factor M.
nat/0Generates a small natural number (bounded by the generation size).
no_faults/1Sets the fault rate to zero within its argument, disabling fault generation.
non_empty/1Make sure that the generated value is not empty.
noshrink/1Generates the same values as G, but these values are never shrunk.
oneof/1Generates a value using a randomly chosen element of the list of generators.
open/1Opens a box created by seal/1.
orderedlist/1Generates an ordered list of elements generated by G.
parameter/1Generates the value of generator parameter P, or fails if P is unbound.
parameter/2Generates the value of generator parameter P, or Default if P is unbound.
peek/1Returns the value contained in a sealed box, before any shrinking.
prop_shrinks_without_duplicates/1This property holds if the generator G never produces duplicate values during shrinking (except perhaps in the last failing test).
real/0Generates a real number.
resize/2Binds the generation size parameter to Size within G.
return/1Constructs a generator that always generates the value X.
sample/1Prints 11 values randomly generated by G, for sizes ranging from 10 to 20.
sampleshrink/1Prints a value generated by G, followed by one way of shrinking it.
seal/1"Seals" G, by generating a sealed box that, every time it is opened, generates the same value, chosen from those generated by G.
shrink_genlist/1Given a list of generators Gs, builds a generator that shrinks to a sublist of elements generated from Gs.
shrink_int/3Generates the value X, and shrinks it within the range M to N.
shrink_list/1Generates L, and shrinks to any sublist of L.
shrink_without_duplicates/1Removes duplicate values from the shrinking search.
shuffle/1Shuffles a list and shrinks to the unshuffled list.
sublist/1Generate a random sublist of the given list.
suspend/1Creates a suspended generator.
timeout/2timeout(T, G) generates using G, but with a timeout of T (in milliseconds).
utf8/0Generates a random utf8 binary.
utf8/1Generates a random utf8 binary with N unicode characters.
vector/2Generates a list of the given length, with elements generated by G.
weighted_default/2Adds a default value to a generator, where both the default and the generator carry weights.
with_parameter/3Binds the parameter P to the value V within generator G.
with_parameters/2Binds all the parameters to the values given within the generator G.

Function Details

binary/0

binary() -> gen(binary())

Generates a binary of random size. The binary shrinks both in size as well as in content. If you consider the binary as a representation of a number, then each shrinking step will result in a smaller - or - equal number.

binary/1

binary(NrBytes::int()) -> gen(binary())

Generates a binary of a given size in bytes. When shrinking, the size is unchanged, but content shrinks like binary/0.

bitstring/0

bitstring() -> gen(bitstring())

Generates a list of bits in a bitstring. For Erlang release R12B and later. The bitstring shrinks both in size as well as in content. If you consider the bitstring as a representation of a number, then each shrinking step will result in a smaller - or - equal number.

bitstring/1

bitstring(NrBits::int()) -> gen(bitstring())

Generates a bitstring of a given size in bits. For Erlang release R12B and later. When shrinking, the size is unchanged, but content shrinks like bitstring/0.

bool/0

bool() -> gen(bool())

Generates a random boolean. Shrinks to false.

char/0

char() -> gen(char())

Generates a random character. Shrinks to a, b or c.

choose/2

choose(M, N::integer()) -> gen(integer())

Generates a number in the range M to N. The result shrinks towards smaller absolute values.

constrain_shrinking/2

constrain_shrinking(Valid::fun((New::A, Old::A) -> boolean()), Gen::gen(A)) -> gen(A)

Constrain the shrinking behaviour of a generator to only consider shrinking step satisfying the given relation. For instance, constrain_shrinking(fun erlang:'<'/2, G) constrains the shrinking of G to strictly decreasing values.

default/2

default(Default::A, G::gen(A)) -> gen(A)

Adds a default value to a generator, to be chosen half the time. Any other value shrinks to the default.

elements/1

elements(Xs::[A]) -> gen(A)

Generates an element of the list argument. Shrinking chooses an earlier element.

fault/2

fault(Fault::gen(A), G::gen(A)) -> gen(A)

Adds a fault - generation alternative to a generator. The probability of using the faulty alternative is controlled by fault_rate/3, more_faulty/2, and less_faulty/2. If no fault rate is specified, then the faulty alternative is never used. Shrinking attempts to replace a faulty value by a freshly generated non - faulty one.

fault_rate/3

fault_rate(M::int(), N::int(), G::gen(A)) -> gen(A)

Specifies that faulty data should be generated by any uses of fault/2 within G on M out of N occasions. M must be between zero and N.

frequency/1

frequency(FGs0::[{number(), gen(A)}]) -> gen(A)

Makes a weighted choice between the generators in its argument, such that the probability of choosing each generator is proportional to the weight paired with it. The weights should be non-negative numbers and sum to a positive value. A generator with a weight of zero will not be chosen.

function0/1

function0(G::gen(A)) -> gen(fun(() -> A))

Generates a function of no arguments with result generated by G.

function1/1

function1(G::gen(A)) -> gen(fun((term()) -> A))

Generates a function of one argument with result generated by G. The generated function is pure--will always return the same result for the same argument-- and the result depends randomly on the argument.

function2/1

function2(G::gen(A)) -> gen(fun((term(), term()) -> A))

Generates a function of two arguments with result generated by G. See function1/1.

function3/1

function3(G::gen(A)) -> gen(fun((term(), term(), term()) -> A))

Generates a function of three arguments with result generated by G. See function1/1.

function4/1

function4(G::gen(A)) -> gen(fun((term(), term(), term(), term()) -> A))

Generates a function of four arguments with result generated by G. See function1/1.

growingelements/1

growingelements(Xs::[A]) -> gen(A)

Generates an element of the list argument. In the early tests, when the size parameter is small, then only early elements of the list are chosen. For larger test sizes, all of the elements become candidates for generation. Thus, if several elements are chosen, then there is a high probability of choosing the same element twice during the early tests.

int/0

int() -> gen(integer())

Generates a small integer (with absolute value bounded by the generation size).

largebinary/0

largebinary() -> gen(binary())

Equivalent to largebinary({limit, 255, 65535}).

largebinary/1

largebinary(X::NrBytes | {fixed, NrBytes} | {limit, Lower, Upper}) -> gen(binary())

largebinary(X) is equivalent to largebinary({fixed, X}, []),
largebinary({fixed, X}) is equivalent to largebinary({fixed, X}, []), and
largebinary({limit, X, Y}) is equivalent to largebinary({limit, X, Y}).

largebinary/2

largebinary(Size, Options) -> gen(binary())

A generator for large binaries. As a rule of thumb, large means > 128 bytes. The problem with the standard generator (binary/0/binary/1) is twofold, the number of shrinking alternatives quickly grow unfeasably large, and the generation is memory consuming.

This generator sacrifices precision for performance. Generation is more efficient, and it shrinks faster although less precisely.

The generator can generate either: Shrinking is configurable with the following options: During shrinking the binary is split into N chunks and then shrinking is only applied to the whole chunk; i.e. either the whole chunk is taken away (size shrinking) or the whole chunk is zeroed (value shrinking).

largeint/0

largeint() -> any()

Generates an integer from a large range.

less_faulty/2

less_faulty(M::int(), G::gen(A)) -> gen(A)

Decreases the fault rate within G by a factor M.

list/1

list(G::gen(A)) -> gen([A])

Generates a list of elements generated by its argument. Shrinking drops elements from the list. The length of the list varies up to one third of the generation size parameter.

list/2

list(MaxLen::integer(), G::gen(A)) -> gen([A])

Generates a list of elements generated by its argument, of length at most MaxLen. Shrinking drops elements from the list.

map/2

map(K::gen(K), V::gen(V)) -> gen(#{K => V})

Generates a map with keys generated by K and values generated by V.

more_faulty/2

more_faulty(M::int(), G::gen(A)) -> gen(A)

Increases the fault rate within G by a factor M.

nat/0

nat() -> gen(integer())

Generates a small natural number (bounded by the generation size).

no_faults/1

no_faults(G::gen(A)) -> gen(A)

Sets the fault rate to zero within its argument, disabling fault generation. Note that a nested call of fault_rate/3 within the argument of no_faults/1 can set the fault rate to be locally non - zero again, so that faults may still be generated. It is best to avoid calling fault_rate/3 within an argument to no_fault/1 or another call of fault_rate/3.

non_empty/1

non_empty(G::gen(A)) -> gen(A)

Make sure that the generated value is not empty. For example when creating a list of integers, but the list should always contain at least one element non_empty(list(int())).

noshrink/1

noshrink(G::gen(A) | property()) -> gen(A) | property()

Generates the same values as G, but these values are never shrunk. Can also be applied to properties.

oneof/1

oneof(Gs::[gen(A)]) -> gen(A)

Generates a value using a randomly chosen element of the list of generators.

open/1

open(B::box(A) | suspension(A)) -> gen(A)

Opens a box created by seal/1. Open can also be applied to any structure containing boxes, when it opens them all. Boxes inside boxes are not opened, however, and neither are boxes "inside generators". Thus

open(seal(Gen))
is not equivalent to Gen, because seal returns a gen(box(A)), which open does not look inside. On the other hand,
?LET(Box, seal(Gen), open(Box))
is equivalent to Gen, since here Box is bound to the box(A) that seal generates, not to the generator itself.

orderedlist/1

orderedlist(G::gen(A)) -> gen([A])

Generates an ordered list of elements generated by G.

parameter/1

parameter(P::atom()) -> gen(term())

Generates the value of generator parameter P, or fails if P is unbound.

parameter/2

parameter(P::atom(), Default::term()) -> gen(term())

Generates the value of generator parameter P, or Default if P is unbound.

peek/1

peek(B::box(A)) -> A

Returns the value contained in a sealed box, before any shrinking. Can also be applied to a structure containing sealed boxes.

prop_shrinks_without_duplicates/1

prop_shrinks_without_duplicates(G::gen(A)) -> property()

This property holds if the generator G never produces duplicate values during shrinking (except perhaps in the last failing test). Such generators lead to faster shrinking when tests fail, because no duplicate tests are run. This property can be used to test user - defined shrinking strategies.

real/0

real() -> gen(float())

Generates a real number.

resize/2

resize(Size::integer(), G::gen(A)) -> gen(A)

Binds the generation size parameter to Size within G. Size should never be negative.

return/1

return(X::A) -> gen(A)

Constructs a generator that always generates the value X. Most values can also be used as generators for themselves, making return unnecessary, but return(X) may be more efficient than using X as a generator, since when return(X) is used then QuickCheck does not traverse X searching for values to be intepreted specially.

sample/1

sample(G::gen(A)) -> ok

Prints 11 values randomly generated by G, for sizes ranging from 10 to 20.

sampleshrink/1

sampleshrink(G::gen(A)) -> ok

Prints a value generated by G, followed by one way of shrinking it. Each following line displays a list of values that the first value on the previous line can be shrunk to in one step. Thus the output traces the leftmost path through the shrinking tree.

seal/1

seal(G::gen(A)) -> gen(box(A))

"Seals" G, by generating a sealed box that, every time it is opened, generates the same value, chosen from those generated by G. The box contains not only the value, but all the possible ways of shrinking it. Each time the box is opened, its value can be shrunk independently--thus there is no reason to expect that, after shrinking, all openings of a box will result in the same value.

The purpose of seal is to control the search order during shrinking, since the alternative values are explored at the point the box is opened, not at the point it is created.

shrink_genlist/1

shrink_genlist(Gs::[gen(A)]) -> gen([A])

Given a list of generators Gs, builds a generator that shrinks to a sublist of elements generated from Gs. The shrinking will alternate between dropping elements from the list and shrinking the elements.

shrink_int/3

shrink_int(M::int(), N::int(), X::int()) -> gen(int())

Generates the value X, and shrinks it within the range M to N. The shrinking strategy used is the same one used by built - in QuickCheck generators.

shrink_list/1

shrink_list(L::[A]) -> gen([A])

Generates L, and shrinks to any sublist of L.

shrink_without_duplicates/1

shrink_without_duplicates(G::gen(A)) -> gen(A)

Removes duplicate values from the shrinking search. The result is a generator equivalent to G, in that it generates the same values, and explores the same possibilities during shrinking, leading to the same final result. However, shrink_without_duplicates(G) generates each value at most once during the shrinking search, except possibly for the last failing value, which is repeated if necessary to ensure that shrinking stops at the same value. To do so, it shrinks in the same way as G, but collects a set of all values encountered, testing each new value for membership. This is quite expensive, so shrink_without_duplicates should only be used when it is difficult to avoid duplicates by other means. See prop_shrinks_without_duplicates/1.

shuffle/1

shuffle(Xs::[A]) -> gen([A])

Shuffles a list and shrinks to the unshuffled list.

sublist/1

sublist(Xs::[A]) -> gen([A])

Generate a random sublist of the given list. Generates short sublists when the size parameter is small, and ramps up to an even distribution of sublist lengths as the size parameter increases. Shrinks to shorter sublists containing elements from earlier in the list.

suspend/1

suspend(G::gen(A)) -> gen(suspension(A))

Creates a suspended generator. A suspension works just like a box created by seal/1, except you cannot peek/1 at the value. The advantage is that the generator is not evaluated until the suspension is opened.

timeout/2

timeout(T::int(), G::gen(A)) -> gen(A | timeout)

timeout(T, G) generates using G, but with a timeout of T (in milliseconds). Values generated in this way do not shrink on a test failure.

utf8/0

utf8() -> any()

Generates a random utf8 binary.

utf8/1

utf8(N) -> any()

Generates a random utf8 binary with N unicode characters.

vector/2

vector(K::integer(), G::gen(A)) -> gen([A])

Generates a list of the given length, with elements generated by G.

weighted_default/2

weighted_default(Default::{number(), A}, X2::{number(), gen(A)}) -> gen(A)

Adds a default value to a generator, where both the default and the generator carry weights. Any other value shrinks to the default.

with_parameter/3

with_parameter(P::atom(), V::term(), G::gen(A)) -> gen(A)

Binds the parameter P to the value V within generator G.

with_parameters/2

with_parameters(Ps::[{atom(), term()}], G::gen(A)) -> gen(A)

Binds all the parameters to the values given within the generator G. For example, with_parameters([{id, 247}], G) is equivalent to with_parameter(id, 247, G).


Generated by EDoc