Module eqc_gen

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:

A set of values that can be generated,

A probability distribution on that set,

A way of shrinking generated values to similar,
smaller values---used after a test fails, to enable
QuickCheck to search for a similar, but simpler failing case.

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.

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.

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.

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.

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.

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.

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.

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.

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.

{chunks, NrChunks} - The number of chunks to split the binary into, each
chunk is considered while shrinking (default: 32 - Note: Chunks should be a
power of 2.)

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).

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.

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.

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.

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.

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.

"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.

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.

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.

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.