Copyright © 2010-2021 Manolis Papadakis, Eirini Arvaniti, and Kostis Sagonas
Version: May 18 2021 22:41:22
Authors: Manolis Papadakis.
Type manipulation functions and predefined types.
This module defines all the basic types of the PropEr type system as functions. See the function index for an overview.
Types can be combined in tuples or lists to produce other types. Exact
values (such as exact numbers, atoms, binaries and strings) can be combined
with types inside such structures, like in this example of the type of a
tagged tuple: {'result', integer()}
.
When including the PropEr header file, all
API functions of this module are automatically
imported, unless PROPER_NO_IMPORTS
is defined.
The following operators can be applied to basic types in order to produce new ones:
?LET(<Xs>, <Xs_type>, <In>)
<Xs>
are replaced inside <In>
by their corresponding values in a
randomly generated instance of <Xs_type>
. It's OK for the <In>
part to
evaluate to a type - in that case, an instance of the inner type is
generated recursively.?SUCHTHAT(<X>, <Type>, <Condition>)
<Type>
, which only includes those
members of <Type>
that satisfy the constraint <Condition>
- that is,
those members for which the function fun(<X>) -> <Condition> end
returns
true
. If the constraint is very strict - that is, only a small
percentage of instances of <Type>
pass the test - it will take a lot of
tries for the instance generation subsystem to randomly produce a valid
instance. This will result in slower testing, and testing may even be
stopped short, in case the constraint_tries
limit is reached (see the
"Options" section in the documentation of the proper
module). If
this is the case, it would be more appropriate to generate valid instances
of the specialized type using the ?LET
macro. Also make sure that even
small instances can satisfy the constraint, since PropEr will only try
small instances at the start of testing. If this is not possible, you can
instruct PropEr to start at a larger size, by supplying a suitable value
for the start_size
option (see the "Options" section in the
documentation of the proper
module).?SUCHTHATMAYBE(<X>, <Type>, <Condition>)
?SUCHTHAT
macro, but the constraint <Condition>
is considered non-strict: if the constraint_tries
limit is reached, the
generator will just return an instance of <Type>
instead of failing,
even if that instance doesn't satisfy the constraint.?SHRINK(<Generator>, <List_of_alt_gens>)
<Generator>
(this may evaluate to a type, which will
then be generated recursively). If an instance of such a type is to be
shrunk, the generators in <List_of_alt_gens>
are first run to produce
hopefully simpler instances of the type. Thus, the generators in the
second argument should be simpler than the default. The simplest ones
should be at the front of the list, since those are the generators
preferred by the shrinking subsystem. Like the main <Generator>
, the
alternatives may also evaluate to a type, which is generated recursively.
?LETSHRINK(<List_of_variables>, <List_of_types>, <Generator>)
?LET
and a ?SHRINK
macro. Instances
are generated by applying a randomly generated list of values inside
<Generator>
(just like a ?LET
, with the added constraint that the
variables and types must be provided in a list - alternatively,
<List_of_types>
may be a list or vector type). When shrinking instances
of such a type, the sub-instances that were combined to produce it are
first tried in place of the failing instance.?LAZY(<Generator>)
<Generator>
(<Generator>
can return a type, which will
be generated recursively). Using this, you can simulate the lazy
generation of instances:
stream() -> ?LAZY(frequency([ {1,[]}, {3,[0|stream()]} ])).The above type produces lists of zeroes with an average length of 3. Note that, had we not enclosed the generator with a
?LAZY
macro, the
evaluation would continue indefinitely, due to the eager evaluation of
the Erlang language.non_empty(<List_or_binary_type>)
non_empty/1
.noshrink(<Type>)
noshrink/1
.default(<Default_value>, <Type>)
default/2
.with_parameter(<Parameter>, <Value>, <Type>)
with_parameter/3
.with_parameters(<Param_value_pairs>, <Type>)
with_parameters/2
.
The following operators are related to the size
parameter, which controls
the maximum size of produced instances. The actual size of a produced
instance is chosen randomly, but can never exceed the value of the size
parameter at the moment of generation. A more accurate definition is the
following: the maximum instance of size S
can never be smaller than the
maximum instance of size S-1
. The actual size of an instance is measured
differently for each type: the actual size of a list is its length, while
the actual size of a tree may be the number of its internal nodes. Some
types, e.g. unions, have no notion of size, thus their generation is not
influenced by the value of size
. The size
parameter starts at 1 and
grows automatically during testing.
?SIZED(<S>, <Generator>)
<S>
parameter inside the statement block
<Generator>
with the value of the size
parameter. It's OK for the
<Generator>
to return a type - in that case, an instance of the inner
type is generated recursively.resize(<New_size>, <Type>)
resize/2
.extint() = integer() | inf
extnum() = number() | inf
frequency() = non_neg_integer()
length() = non_neg_integer()
loose_tuple(T) = {} | {T} | {T, T} | {T, T, T} | {T, T, T, T} | {T, T, T, T, T} | {T, T, T, T, T, T} | {T, T, T, T, T, T, T} | {T, T, T, T, T, T, T, T} | {T, T, T, T, T, T, T, T, T} | {T, T, T, T, T, T, T, T, T, T} | tuple()
Internal types
raw_type() = type() | [raw_type()] | loose_tuple(raw_type()) | term()
You can consider this as an equivalent of type()
.
abstract datatype: type()
A type of the PropEr type system
type_prop_name() = kind | generator | reverse_gen | parts_type | combine | alt_gens | shrink_to_parts | size_transform | is_instance | shrinkers | noshrink | internal_type | internal_types | get_length | split | join | get_indices | remove | retrieve | update | constraints | parameters | env | subenv | user_nf | is_user_nf | matcher
type_prop_value() = term()
value() = term()
add_prop/3 | |
any/0 | All Erlang terms (that PropEr can produce). |
arity/0 | Equivalent to integer(0, 255). |
atom/0 | All atoms. |
binary/0 | All binaries. |
binary/1 | All binaries with a byte size of Len . |
bitstring/0 | All bitstrings. |
bitstring/1 | All bitstrings with a bit size of Len . |
bool/0 | Equivalent to boolean(). |
boolean/0 | The atoms true and false . |
byte/0 | Equivalent to integer(0, 255). |
char/0 | Equivalent to integer(0, 1114111). |
choose/2 | Equivalent to integer(Low, High). |
default/2 | Adds a default value, Default , to Type . |
elements/1 | Equivalent to union(Choices). |
exactly/1 | Singleton type consisting only of E . |
fixed_list/1 | All lists whose i-th element is an instance of the type at index i of
ListOfTypes . |
float/0 | Equivalent to float(inf, inf). |
float/2 | All floats between Low and High , bounds included. |
frequency/1 | Equivalent to weighted_union(Choices). |
function/2 | All pure functions that map instances of ArgTypes to instances of
RetType . |
function0/1 | Equivalent to function(0, RetType). |
function1/1 | Equivalent to function(1, RetType). |
function2/1 | Equivalent to function(2, RetType). |
function3/1 | Equivalent to function(3, RetType). |
function4/1 | Equivalent to function(4, RetType). |
int/0 | Small integers (bound by the current value of the size parameter). |
integer/0 | Equivalent to integer(inf, inf). |
integer/2 | All integers between Low and High , bounds included. |
largeint/0 | Equivalent to integer(). |
list/0 | Equivalent to list(any()). |
list/1 | All lists containing elements of type ElemType . |
loose_tuple/1 | Tuples whose elements are all of type ElemType . |
map/0 | A map associating keys and values of unspecified types (of any term()). |
map/2 | A map whose keys are defined by the generator K and values
by the generator V . |
nat/0 | Small non-negative integers (bound by the current value of the size
parameter). |
neg_integer/0 | Equivalent to integer(inf, -1). |
nil/0 | Equivalent to exactly([]). |
non_empty/1 | This is a predefined constraint that can be applied to random-length list and binary types to ensure that the produced values are never empty. |
non_neg_float/0 | Equivalent to float(0.0, inf). |
non_neg_integer/0 | Equivalent to integer(0, inf). |
noshrink/1 | Creates a new type which is equivalent to Type , but whose instances
are never shrunk by the shrinking subsystem. |
number/0 | Equivalent to union([integer(), float()]). |
oneof/1 | Equivalent to union(Choices). |
orderedlist/1 | All sorted lists containing elements of type ElemType . |
parameter/1 | Equivalent to parameter(Parameter, undefined). |
parameter/2 | Returns the value associated with Parameter , or Default in case
Parameter is not associated with any value. |
pos_integer/0 | Equivalent to integer(1, inf). |
range/2 | Equivalent to integer(Low, High). |
real/0 | Equivalent to float(). |
resize/2 | Overrides the size parameter used when generating instances of
Type with NewSize . |
return/1 | Equivalent to exactly(E). |
shrink_list/1 | A type that generates exactly the list List . |
string/0 | Equivalent to list(char()). |
term/0 | Equivalent to any(). |
timeout/0 | Equivalent to union([non_neg_integer() | infinity]). |
tuple/0 | Equivalent to loose_tuple(any()). |
tuple/1 | All tuples whose i-th element is an instance of the type at index i of
ListOfTypes . |
union/1 | The union of all types in ListOfTypes . |
vector/2 | All lists of length Len containing elements of type ElemType . |
weighted_default/2 | A specialization of default/2 , where Default and Type are
assigned weights to be considered by the random instance generator. |
weighted_union/1 | A specialization of union/1 , where each type in ListOfTypes is
assigned a frequency. |
with_parameter/3 | Associates the atom key Parameter with the value Value while
generating instances of Type . |
with_parameters/2 | Similar to with_parameter/3 , but accepts a list of
{Parameter, Value} pairs. |
wunion/1 | Equivalent to weighted_union(FreqChoices). |
add_prop(PropName :: type_prop_name(), Value :: type_prop_value(), X3 :: proper_types:type()) -> proper_types:type()
any() -> proper_types:type()
All Erlang terms (that PropEr can produce). For reasons of efficiency,
functions are never produced as instances of this type.
CAUTION: Instances of this type are expensive to produce, shrink and instance-
check, both in terms of processing time and consumed memory. Only use this
type if you are certain that you need it.
arity() -> proper_types:type()
Equivalent to integer(0, 255).
atom() -> proper_types:type()
All atoms. All atoms used internally by PropEr start with a '$
', so
such atoms will never be produced as instances of this type. You should also
refrain from using such atoms in your code, to avoid a potential clash.
Instances shrink towards the empty atom, ''.
binary() -> proper_types:type()
All binaries. Instances shrink towards the empty binary, <<>>
.
binary(Len :: length()) -> proper_types:type()
All binaries with a byte size of Len
.
Len
must be an Erlang expression that evaluates to a non-negative integer.
Instances shrink towards binaries of zeroes.
bitstring() -> proper_types:type()
All bitstrings. Instances shrink towards the empty bitstring, <<>>
.
bitstring(Len :: length()) -> proper_types:type()
All bitstrings with a bit size of Len
.
Len
must be an Erlang expression that evaluates to a non-negative integer.
Instances shrink towards bitstrings of zeroes
bool() -> proper_types:type()
Equivalent to boolean().
boolean() -> proper_types:type()
The atoms true
and false
. Instances shrink towards false
.
byte() -> proper_types:type()
Equivalent to integer(0, 255).
char() -> proper_types:type()
Equivalent to integer(0, 1114111).
choose(Low :: extint(), High :: extint()) -> proper_types:type()
Equivalent to integer(Low, High).
default(Default :: raw_type(), Type :: raw_type()) -> proper_types:type()
Adds a default value, Default
, to Type
.
The default serves as a primary shrinking target for instances, while it
is also chosen by the random instance generation subsystem half the time.
elements(Choices :: [raw_type(), ...]) -> proper_types:type()
Equivalent to union(Choices).
exactly(E :: term()) -> proper_types:type()
Singleton type consisting only of E
. E
must be an evaluated term.
Also written simply as E
.
fixed_list(ListOfTypes :: maybe_improper_list(raw_type(), raw_type() | [])) -> proper_types:type()
All lists whose i-th element is an instance of the type at index i of
ListOfTypes
. Also written simply as a list of types.
float() -> proper_types:type()
Equivalent to float(inf, inf).
float(Low :: extnum(), High :: extnum()) -> proper_types:type()
All floats between Low
and High
, bounds included.
Low
and High
must be Erlang expressions that evaluate to floats, with
Low =< High
. Additionally, Low
and High
may have the value inf
, in
which case they represent minus infinity and plus infinity respectively.
Instances shrink towards 0.0 if Low =< 0.0 =< High
, or towards the bound
with the smallest absolute value otherwise.
frequency(FreqChoices :: [{frequency(), raw_type()}, ...]) -> proper_types:type()
Equivalent to weighted_union(Choices).
function(ArgTypes :: [raw_type()] | arity(), RetType :: raw_type()) -> proper_types:type()
All pure functions that map instances of ArgTypes
to instances of
RetType
. The syntax function(Arity, RetType)
is also acceptable.
function0(RetType :: raw_type()) -> proper_types:type()
Equivalent to function(0, RetType).
function1(RetType :: raw_type()) -> proper_types:type()
Equivalent to function(1, RetType).
function2(RetType :: raw_type()) -> proper_types:type()
Equivalent to function(2, RetType).
function3(RetType :: raw_type()) -> proper_types:type()
Equivalent to function(3, RetType).
function4(RetType :: raw_type()) -> proper_types:type()
Equivalent to function(4, RetType).
int() -> proper_types:type()
Small integers (bound by the current value of the size
parameter).
Instances shrink towards 0
.
integer() -> proper_types:type()
Equivalent to integer(inf, inf).
integer(Low :: extint(), High :: extint()) -> proper_types:type()
All integers between Low
and High
, bounds included.
Low
and High
must be Erlang expressions that evaluate to integers, with
Low =< High
. Additionally, Low
and High
may have the value inf
, in
which case they represent minus infinity and plus infinity respectively.
Instances shrink towards 0 if Low =< 0 =< High
, or towards the bound with
the smallest absolute value otherwise.
largeint() -> proper_types:type()
Equivalent to integer().
list() -> proper_types:type()
Equivalent to list(any()).
list(ElemType :: raw_type()) -> proper_types:type()
All lists containing elements of type ElemType
.
Instances shrink towards the empty list, []
.
loose_tuple(ElemType :: raw_type()) -> proper_types:type()
Tuples whose elements are all of type ElemType
.
Instances shrink towards the 0-size tuple, {}
.
map() -> proper_types:type()
A map associating keys and values of unspecified types (of any term()).
map(K :: raw_type(), V :: raw_type()) -> proper_types:type()
A map whose keys are defined by the generator K
and values
by the generator V
.
nat() -> proper_types:type()
Small non-negative integers (bound by the current value of the size
parameter). Instances shrink towards 0
.
neg_integer() -> proper_types:type()
Equivalent to integer(inf, -1).
nil() -> proper_types:type()
Equivalent to exactly([]).
non_empty(ListType :: raw_type()) -> proper_types:type()
This is a predefined constraint that can be applied to random-length list and binary types to ensure that the produced values are never empty.
e.g.list/0
, string/0
, binary/0
)
non_neg_float() -> proper_types:type()
Equivalent to float(0.0, inf).
non_neg_integer() -> proper_types:type()
Equivalent to integer(0, inf).
noshrink(Type :: raw_type()) -> proper_types:type()
Creates a new type which is equivalent to Type
, but whose instances
are never shrunk by the shrinking subsystem.
number() -> proper_types:type()
Equivalent to union([integer(), float()]).
oneof(Choices :: [raw_type(), ...]) -> proper_types:type()
Equivalent to union(Choices).
orderedlist(ElemType :: raw_type()) -> proper_types:type()
All sorted lists containing elements of type ElemType
.
Instances shrink towards the empty list, []
.
parameter(Parameter :: atom()) -> value()
Equivalent to parameter(Parameter, undefined).
Returns the value associated with Parameter
, or Default
in case
Parameter
is not associated with any value.
pos_integer() -> proper_types:type()
Equivalent to integer(1, inf).
range(Low :: extint(), High :: extint()) -> proper_types:type()
Equivalent to integer(Low, High).
real() -> proper_types:type()
Equivalent to float().
resize(NewSize :: proper_gen:size(), Type :: raw_type()) -> proper_types:type()
Overrides the size
parameter used when generating instances of
Type
with NewSize
. Has no effect on size-less types, such as unions.
Also, this will not affect the generation of any internal types contained in
Type
, such as the elements of a list - those will still be generated
using the test-wide value of size
. One use of this function is to modify
types to produce instances that grow faster or slower, like so:
?SIZED(Size, resize(Size * 2, list(integer()))The above specifies a list type that grows twice as fast as normal lists.
return(E :: term()) -> proper_types:type()
Equivalent to exactly(E).
shrink_list(List :: [term()]) -> proper_types:type()
A type that generates exactly the list List
. Instances shrink towards
shorter sublists of the original list.
string() -> proper_types:type()
Equivalent to list(char()).
term() -> proper_types:type()
Equivalent to any().
timeout() -> proper_types:type()
Equivalent to union([non_neg_integer() | infinity]).
tuple() -> proper_types:type()
Equivalent to loose_tuple(any()).
tuple(ListOfTypes :: [raw_type()]) -> proper_types:type()
All tuples whose i-th element is an instance of the type at index i of
ListOfTypes
. Also written simply as a tuple of types.
union(ListOfTypes :: [raw_type(), ...]) -> proper_types:type()
The union of all types in ListOfTypes
. ListOfTypes
can't be empty.
The random instance generator is equally likely to choose any one of the
types in ListOfTypes
. The shrinking subsystem will always try to shrink an
instance of a type union to an instance of the first type in ListOfTypes
,
thus you should write the simplest case first.
vector(Len :: length(), ElemType :: raw_type()) -> proper_types:type()
All lists of length Len
containing elements of type ElemType
.
Len
must be an Erlang expression that evaluates to a non-negative integer.
weighted_default(Default :: {frequency(), raw_type()}, Type :: {frequency(), raw_type()}) -> proper_types:type()
A specialization of default/2
, where Default
and Type
are
assigned weights to be considered by the random instance generator. The
shrinking subsystem will ignore the weights and try to shrink using the
default value.
weighted_union(ListOfTypes :: [{frequency(), raw_type()}, ...]) -> proper_types:type()
A specialization of union/1
, where each type in ListOfTypes
is
assigned a frequency. Frequencies must be Erlang expressions that evaluate to
non-negative integers. Types with larger frequencies are more likely to be
chosen by the random instance generator. The shrinking subsystem will ignore
the frequencies and try to shrink towards the first type in the list with a
non-zero frequency.
with_parameter(Parameter :: atom(), Value :: value(), Type :: raw_type()) -> proper_types:type()
Associates the atom key Parameter
with the value Value
while
generating instances of Type
.
with_parameters(PVlist :: [{atom(), value()}], Type :: raw_type()) -> proper_types:type()
Similar to with_parameter/3
, but accepts a list of
{Parameter, Value}
pairs.
wunion(FreqChoices :: [{frequency(), raw_type()}, ...]) -> proper_types:type()
Equivalent to weighted_union(FreqChoices).
Generated by EDoc