aiken/fuzz
Functions
Constructing
Primitives
Generate a random Bool
value from a
uniform distribution.
test prop_bool(is_true via fuzz.bool()) {
is_true || !is_true
}
Create a constant Fuzzer from an arbitrary value.
Generate a random ByteArray
of 32 bytes.
Generate a random ByteArray
of
size within a lower and upper bounds.
Generate a random ByteArray
of len
bytes.
Generate a random integer value. It favors small values near zero, but
generate across the range [-255; 16383]
with the following distribution:
25.0% [-255; 0[ ████████████
2.5% 0 █
50.0% ]0; 255] █████████████████████████
22.5% [256; 16383] ██████████
The distribution is uniform within those buckets. If you need larger values, use int_between
.
Generate integers values uniformly between a lower and upper bounds (both inclusive).
Data-structures
Generate a random list of elements from a given fuzzer. The list contains
at most 20
elements, and has a higher probability of generating smaller lists.
For lists of a specific length, use list_between
.
Generate a random list of elements with length within specified bounds. The
resulting list contains at least min
elements and at most max
elements, with a higher probability of generating smaller lists.
More specifically, there’s approximately 1/n chance of generating n
elements within the range. For example, the distribution when generating a
list between 0 and 10 elements resemble the following:
22.7% 0 elements ████████
19.7% 1 element ███████
13.5% 2 elements █████
9.5% 3 elements ███
6.3% 4 elements ██
5.6% 5 elements ██
5.6% 6 elements ██
4.0% 7 elements █
3.1% 8 elements █
2.0% 9 elements █
8.0% 10 elements ███
Generate a random list of elements from a given fuzzer, with at least min
elements.
Generate a random list of elements from a given fuzzer, with at most max
elements.
Generate a random list and pick an element from that list. Return both.
Generate a random list of unique elements (a.k.a. a set) from a given fuzzer.
The list contains at most 20
elements, and has a higher probability of
generating smaller lists.
Important: The specified fuzzer must have a high enough entropy to
yield enough unique values to fill the set with the required size!
For sets of a specific length, use set_between
.
Generate a random list of unique elements (a.k.a a set) with length
within specified bounds. The resulting set contains at least min
elements and at most max
elements, with a higher probability of
generating smaller sets.
More specifically, there’s approximately 1/n chance of generating n
elements within the range. For example, the distribution when generating a
set between 0 and 10 elements resemble the following:
Important: The specified fuzzer must have a high enough entropy to
yield enough unique values to fill the set with the required size!
22.7% 0 elements ████████
19.7% 1 element ███████
13.5% 2 elements █████
9.5% 3 elements ███
6.3% 4 elements ██
5.6% 5 elements ██
5.6% 6 elements ██
4.0% 7 elements █
3.1% 8 elements █
2.0% 9 elements █
8.0% 10 elements ███
Generate a random set of elements from a given fuzzer, with at least min
elements.
Generate a random set of elements from a given fuzzer, with at most max
elements.
Generate a random set and pick an element from that set. Return both.
Combining
Combine a Fuzzer with the result of a another one.
This function works great with backpassing.
pub fn either(left: Fuzzer<a>, right: Fuzzer<a>) -> Fuzzer<a> {
let pick_left <- fuzz.and_then(fuzz.bool())
if pick_left {
left
} else {
right
}
}
Choose either of two fuzzers with an equal probability.
Choose either of three fuzzers with an equal probability.
either4(
a: Fuzzer<result>,
b: Fuzzer<result>,
c: Fuzzer<result>,
d: Fuzzer<result>,
) -> Fuzzer<result>
Choose either of four fuzzers with an equal probability.
either5(
a: Fuzzer<result>,
b: Fuzzer<result>,
c: Fuzzer<result>,
d: Fuzzer<result>,
e: Fuzzer<result>,
) -> Fuzzer<result>
Choose either of five fuzzers with an equal probability.
either6(
a: Fuzzer<result>,
b: Fuzzer<result>,
c: Fuzzer<result>,
d: Fuzzer<result>,
e: Fuzzer<result>,
f: Fuzzer<result>,
) -> Fuzzer<result>
Choose either of six fuzzers with an equal probability.
either7(
a: Fuzzer<result>,
b: Fuzzer<result>,
c: Fuzzer<result>,
d: Fuzzer<result>,
e: Fuzzer<result>,
f: Fuzzer<result>,
g: Fuzzer<result>,
) -> Fuzzer<result>
Choose either of seven fuzzers with an equal probability.
either8(
a: Fuzzer<result>,
b: Fuzzer<result>,
c: Fuzzer<result>,
d: Fuzzer<result>,
e: Fuzzer<result>,
f: Fuzzer<result>,
g: Fuzzer<result>,
h: Fuzzer<result>,
) -> Fuzzer<result>
Choose either of height fuzzers with an equal probability.
either9(
a: Fuzzer<result>,
b: Fuzzer<result>,
c: Fuzzer<result>,
d: Fuzzer<result>,
e: Fuzzer<result>,
f: Fuzzer<result>,
g: Fuzzer<result>,
h: Fuzzer<result>,
i: Fuzzer<result>,
) -> Fuzzer<result>
Choose either of nine fuzzers with an equal probability.
Transform the result of a Fuzzer using a function.
This function works great with backpassing.
fn bool() -> Fuzzer<Bool> {
let n <- map(int_between(1, 100))
n % 2
}
Combine the results of two Fuzzers.
map3(
fuzz_0: Fuzzer<t0>,
fuzz_1: Fuzzer<t1>,
fuzz_2: Fuzzer<t2>,
f: fn(t0, t1, t2) -> result,
) -> Fuzzer<result>
Combine the results of three Fuzzers.
map4(
fuzz_0: Fuzzer<t0>,
fuzz_1: Fuzzer<t1>,
fuzz_2: Fuzzer<t2>,
fuzz_3: Fuzzer<t3>,
f: fn(t0, t1, t2, t3) -> result,
) -> Fuzzer<result>
Combine the results of four Fuzzers.
map5(
fuzz_0: Fuzzer<t0>,
fuzz_1: Fuzzer<t1>,
fuzz_2: Fuzzer<t2>,
fuzz_3: Fuzzer<t3>,
fuzz_4: Fuzzer<t4>,
f: fn(t0, t1, t2, t3, t4) -> result,
) -> Fuzzer<result>
Combine the results of five Fuzzers.
map6(
fuzz_0: Fuzzer<t0>,
fuzz_1: Fuzzer<t1>,
fuzz_2: Fuzzer<t2>,
fuzz_3: Fuzzer<t3>,
fuzz_4: Fuzzer<t4>,
fuzz_5: Fuzzer<t5>,
f: fn(t0, t1, t2, t3, t4, t5) -> result,
) -> Fuzzer<result>
Combine the results of six Fuzzers.
map7(
fuzz_0: Fuzzer<t0>,
fuzz_1: Fuzzer<t1>,
fuzz_2: Fuzzer<t2>,
fuzz_3: Fuzzer<t3>,
fuzz_4: Fuzzer<t4>,
fuzz_5: Fuzzer<t5>,
fuzz_6: Fuzzer<t6>,
f: fn(t0, t1, t2, t3, t4, t5, t6) -> result,
) -> Fuzzer<result>
Combine the results of seven Fuzzers.
map8(
fuzz_0: Fuzzer<t0>,
fuzz_1: Fuzzer<t1>,
fuzz_2: Fuzzer<t2>,
fuzz_3: Fuzzer<t3>,
fuzz_4: Fuzzer<t4>,
fuzz_5: Fuzzer<t5>,
fuzz_6: Fuzzer<t6>,
fuzz_7: Fuzzer<t7>,
f: fn(t0, t1, t2, t3, t4, t5, t6, t7) -> result,
) -> Fuzzer<result>
Combine the results of eight Fuzzers.
map9(
fuzz_0: Fuzzer<t0>,
fuzz_1: Fuzzer<t1>,
fuzz_2: Fuzzer<t2>,
fuzz_3: Fuzzer<t3>,
fuzz_4: Fuzzer<t4>,
fuzz_5: Fuzzer<t5>,
fuzz_6: Fuzzer<t6>,
fuzz_7: Fuzzer<t7>,
fuzz_8: Fuzzer<t8>,
f: fn(t0, t1, t2, t3, t4, t5, t6, t7, t8) -> result,
) -> Fuzzer<result>
Combine the results of nine Fuzzers.
Pick a value from a (non-empty!) list with equal probability.
let any_bool = fuzz.one_of([True, False])
Choose between None
or Some
value with an equal probability.
Generate a value that satisfies a given predicate. Beware that this
function may heavily impact the performances of your fuzzers. In general, you
should prefer constraining the fuzzers beforehand than trying to discard
values after the fact!
Use with caution.
Inspecting
Label a test case. Labels are collected at the end of a property run and a
distribution amongst all labels is computed and shown. This is particularly
useful to assert that specific scenarios are met or to test your fuzzers.
test prop_bool_distribution(is_true via bool()) {
label(
if is_true {
@"True"
} else {
@"False"
},
)
True
}
Apply a label when a predicate is true, or fallback to a default label.
Useful for labelling dichotomies while ensuring that the final label
distribution reflects all cases.
test prop_u16(operands via fuzz.both(byte(), byte())) {
let (msb, lsb) = operands
fuzz.label_when(msb == 0, @"msb = 0", @"default")
fuzz.label_when(lsb == 0, @"lsb = 0", @"default")
builtin.bytearray_to_integer(
False,
""
|> builtin.cons_bytearray(msb, _)
|> builtin.cons_bytearray(lsb, _),
) == msb * 256 + lsb
}
Apply a label when a predicate is true, or do nothing. Useful for
conditionally labelling scenarios in a single line.
test post_conditions(steps via any_scenario()) {
let (is_register, is_reregister, is_unregister, is_forward) =
classify_steps(steps)
@"contains solo registration" |> label_if(is_register)
@"contains re-registration" |> label_if(is_reregister)
@"contains solo unregistration" |> label_if(is_unregister)
@"contains forward-only" |> label_if(is_forward)
}
Generate a random Bool
value from a
uniform distribution.
test prop_bool(is_true via fuzz.bool()) {
is_true || !is_true
}
Create a constant Fuzzer from an arbitrary value.
Generate a random ByteArray
of 32 bytes.
Generate a random ByteArray
of
size within a lower and upper bounds.
Generate a random ByteArray
of len
bytes.
Generate a random integer value. It favors small values near zero, but
generate across the range [-255; 16383]
with the following distribution:
25.0% [-255; 0[ ████████████
2.5% 0 █
50.0% ]0; 255] █████████████████████████
22.5% [256; 16383] ██████████
The distribution is uniform within those buckets. If you need larger values, use int_between
.
Generate integers values uniformly between a lower and upper bounds (both inclusive).
Data-structures
Generate a random list of elements from a given fuzzer. The list contains
at most 20
elements, and has a higher probability of generating smaller lists.
For lists of a specific length, use list_between
.
Generate a random list of elements with length within specified bounds. The
resulting list contains at least min
elements and at most max
elements, with a higher probability of generating smaller lists.
More specifically, there’s approximately 1/n chance of generating n
elements within the range. For example, the distribution when generating a
list between 0 and 10 elements resemble the following:
22.7% 0 elements ████████
19.7% 1 element ███████
13.5% 2 elements █████
9.5% 3 elements ███
6.3% 4 elements ██
5.6% 5 elements ██
5.6% 6 elements ██
4.0% 7 elements █
3.1% 8 elements █
2.0% 9 elements █
8.0% 10 elements ███
Generate a random list of elements from a given fuzzer, with at least min
elements.
Generate a random list of elements from a given fuzzer, with at most max
elements.
Generate a random list and pick an element from that list. Return both.
Generate a random list of unique elements (a.k.a. a set) from a given fuzzer.
The list contains at most 20
elements, and has a higher probability of
generating smaller lists.
Important: The specified fuzzer must have a high enough entropy to
yield enough unique values to fill the set with the required size!
For sets of a specific length, use set_between
.
Generate a random list of unique elements (a.k.a a set) with length
within specified bounds. The resulting set contains at least min
elements and at most max
elements, with a higher probability of
generating smaller sets.
More specifically, there’s approximately 1/n chance of generating n
elements within the range. For example, the distribution when generating a
set between 0 and 10 elements resemble the following:
Important: The specified fuzzer must have a high enough entropy to
yield enough unique values to fill the set with the required size!
22.7% 0 elements ████████
19.7% 1 element ███████
13.5% 2 elements █████
9.5% 3 elements ███
6.3% 4 elements ██
5.6% 5 elements ██
5.6% 6 elements ██
4.0% 7 elements █
3.1% 8 elements █
2.0% 9 elements █
8.0% 10 elements ███
Generate a random set of elements from a given fuzzer, with at least min
elements.
Generate a random set of elements from a given fuzzer, with at most max
elements.
Generate a random set and pick an element from that set. Return both.
Combining
Generate a random list of elements from a given fuzzer. The list contains
at most 20
elements, and has a higher probability of generating smaller lists.
For lists of a specific length, use list_between
.
Generate a random list of elements with length within specified bounds. The
resulting list contains at least min
elements and at most max
elements, with a higher probability of generating smaller lists.
More specifically, there’s approximately 1/n chance of generating n elements within the range. For example, the distribution when generating a list between 0 and 10 elements resemble the following:
22.7% 0 elements ████████
19.7% 1 element ███████
13.5% 2 elements █████
9.5% 3 elements ███
6.3% 4 elements ██
5.6% 5 elements ██
5.6% 6 elements ██
4.0% 7 elements █
3.1% 8 elements █
2.0% 9 elements █
8.0% 10 elements ███
Generate a random list of elements from a given fuzzer, with at least min
elements.
Generate a random list of elements from a given fuzzer, with at most max
elements.
Generate a random list and pick an element from that list. Return both.
Generate a random list of unique elements (a.k.a. a set) from a given fuzzer.
The list contains at most 20
elements, and has a higher probability of
generating smaller lists.
Important: The specified fuzzer must have a high enough entropy to yield enough unique values to fill the set with the required size!
For sets of a specific length, use set_between
.
Generate a random list of unique elements (a.k.a a set) with length
within specified bounds. The resulting set contains at least min
elements and at most max
elements, with a higher probability of
generating smaller sets.
More specifically, there’s approximately 1/n chance of generating n elements within the range. For example, the distribution when generating a set between 0 and 10 elements resemble the following:
Important: The specified fuzzer must have a high enough entropy to yield enough unique values to fill the set with the required size!
22.7% 0 elements ████████
19.7% 1 element ███████
13.5% 2 elements █████
9.5% 3 elements ███
6.3% 4 elements ██
5.6% 5 elements ██
5.6% 6 elements ██
4.0% 7 elements █
3.1% 8 elements █
2.0% 9 elements █
8.0% 10 elements ███
Generate a random set of elements from a given fuzzer, with at least min
elements.
Generate a random set of elements from a given fuzzer, with at most max
elements.
Generate a random set and pick an element from that set. Return both.
Combine a Fuzzer with the result of a another one. This function works great with backpassing.
pub fn either(left: Fuzzer<a>, right: Fuzzer<a>) -> Fuzzer<a> {
let pick_left <- fuzz.and_then(fuzz.bool())
if pick_left {
left
} else {
right
}
}
Choose either of two fuzzers with an equal probability.
Choose either of three fuzzers with an equal probability.
either4(
a: Fuzzer<result>,
b: Fuzzer<result>,
c: Fuzzer<result>,
d: Fuzzer<result>,
) -> Fuzzer<result>
Choose either of four fuzzers with an equal probability.
either5(
a: Fuzzer<result>,
b: Fuzzer<result>,
c: Fuzzer<result>,
d: Fuzzer<result>,
e: Fuzzer<result>,
) -> Fuzzer<result>
Choose either of five fuzzers with an equal probability.
either6(
a: Fuzzer<result>,
b: Fuzzer<result>,
c: Fuzzer<result>,
d: Fuzzer<result>,
e: Fuzzer<result>,
f: Fuzzer<result>,
) -> Fuzzer<result>
Choose either of six fuzzers with an equal probability.
either7(
a: Fuzzer<result>,
b: Fuzzer<result>,
c: Fuzzer<result>,
d: Fuzzer<result>,
e: Fuzzer<result>,
f: Fuzzer<result>,
g: Fuzzer<result>,
) -> Fuzzer<result>
Choose either of seven fuzzers with an equal probability.
either8(
a: Fuzzer<result>,
b: Fuzzer<result>,
c: Fuzzer<result>,
d: Fuzzer<result>,
e: Fuzzer<result>,
f: Fuzzer<result>,
g: Fuzzer<result>,
h: Fuzzer<result>,
) -> Fuzzer<result>
Choose either of height fuzzers with an equal probability.
either9(
a: Fuzzer<result>,
b: Fuzzer<result>,
c: Fuzzer<result>,
d: Fuzzer<result>,
e: Fuzzer<result>,
f: Fuzzer<result>,
g: Fuzzer<result>,
h: Fuzzer<result>,
i: Fuzzer<result>,
) -> Fuzzer<result>
Choose either of nine fuzzers with an equal probability.
Transform the result of a Fuzzer using a function. This function works great with backpassing.
fn bool() -> Fuzzer<Bool> {
let n <- map(int_between(1, 100))
n % 2
}
Combine the results of two Fuzzers.
map3(
fuzz_0: Fuzzer<t0>,
fuzz_1: Fuzzer<t1>,
fuzz_2: Fuzzer<t2>,
f: fn(t0, t1, t2) -> result,
) -> Fuzzer<result>
Combine the results of three Fuzzers.
map4(
fuzz_0: Fuzzer<t0>,
fuzz_1: Fuzzer<t1>,
fuzz_2: Fuzzer<t2>,
fuzz_3: Fuzzer<t3>,
f: fn(t0, t1, t2, t3) -> result,
) -> Fuzzer<result>
Combine the results of four Fuzzers.
map5(
fuzz_0: Fuzzer<t0>,
fuzz_1: Fuzzer<t1>,
fuzz_2: Fuzzer<t2>,
fuzz_3: Fuzzer<t3>,
fuzz_4: Fuzzer<t4>,
f: fn(t0, t1, t2, t3, t4) -> result,
) -> Fuzzer<result>
Combine the results of five Fuzzers.
map6(
fuzz_0: Fuzzer<t0>,
fuzz_1: Fuzzer<t1>,
fuzz_2: Fuzzer<t2>,
fuzz_3: Fuzzer<t3>,
fuzz_4: Fuzzer<t4>,
fuzz_5: Fuzzer<t5>,
f: fn(t0, t1, t2, t3, t4, t5) -> result,
) -> Fuzzer<result>
Combine the results of six Fuzzers.
map7(
fuzz_0: Fuzzer<t0>,
fuzz_1: Fuzzer<t1>,
fuzz_2: Fuzzer<t2>,
fuzz_3: Fuzzer<t3>,
fuzz_4: Fuzzer<t4>,
fuzz_5: Fuzzer<t5>,
fuzz_6: Fuzzer<t6>,
f: fn(t0, t1, t2, t3, t4, t5, t6) -> result,
) -> Fuzzer<result>
Combine the results of seven Fuzzers.
map8(
fuzz_0: Fuzzer<t0>,
fuzz_1: Fuzzer<t1>,
fuzz_2: Fuzzer<t2>,
fuzz_3: Fuzzer<t3>,
fuzz_4: Fuzzer<t4>,
fuzz_5: Fuzzer<t5>,
fuzz_6: Fuzzer<t6>,
fuzz_7: Fuzzer<t7>,
f: fn(t0, t1, t2, t3, t4, t5, t6, t7) -> result,
) -> Fuzzer<result>
Combine the results of eight Fuzzers.
map9(
fuzz_0: Fuzzer<t0>,
fuzz_1: Fuzzer<t1>,
fuzz_2: Fuzzer<t2>,
fuzz_3: Fuzzer<t3>,
fuzz_4: Fuzzer<t4>,
fuzz_5: Fuzzer<t5>,
fuzz_6: Fuzzer<t6>,
fuzz_7: Fuzzer<t7>,
fuzz_8: Fuzzer<t8>,
f: fn(t0, t1, t2, t3, t4, t5, t6, t7, t8) -> result,
) -> Fuzzer<result>
Combine the results of nine Fuzzers.
Pick a value from a (non-empty!) list with equal probability.
let any_bool = fuzz.one_of([True, False])
Choose between None
or Some
value with an equal probability.
Generate a value that satisfies a given predicate. Beware that this function may heavily impact the performances of your fuzzers. In general, you should prefer constraining the fuzzers beforehand than trying to discard values after the fact!
Use with caution.
Inspecting
Label a test case. Labels are collected at the end of a property run and a distribution amongst all labels is computed and shown. This is particularly useful to assert that specific scenarios are met or to test your fuzzers.
test prop_bool_distribution(is_true via bool()) {
label(
if is_true {
@"True"
} else {
@"False"
},
)
True
}
Apply a label when a predicate is true, or fallback to a default label. Useful for labelling dichotomies while ensuring that the final label distribution reflects all cases.
test prop_u16(operands via fuzz.both(byte(), byte())) {
let (msb, lsb) = operands
fuzz.label_when(msb == 0, @"msb = 0", @"default")
fuzz.label_when(lsb == 0, @"lsb = 0", @"default")
builtin.bytearray_to_integer(
False,
""
|> builtin.cons_bytearray(msb, _)
|> builtin.cons_bytearray(lsb, _),
) == msb * 256 + lsb
}
Apply a label when a predicate is true, or do nothing. Useful for conditionally labelling scenarios in a single line.
test post_conditions(steps via any_scenario()) {
let (is_register, is_reregister, is_unregister, is_forward) =
classify_steps(steps)
@"contains solo registration" |> label_if(is_register)
@"contains re-registration" |> label_if(is_reregister)
@"contains solo unregistration" |> label_if(is_unregister)
@"contains forward-only" |> label_if(is_forward)
}