37 releases (20 stable)
1.4.1 | Nov 5, 2024 |
---|---|
1.3.2 | Oct 30, 2023 |
1.3.0 | Mar 13, 2023 |
1.2.0 | Oct 20, 2022 |
0.1.0 | May 8, 2017 |
#8 in Testing
2,107,765 downloads per month
Used in 1,683 crates
(469 directly)
110KB
2K
SLoC
Arbitrary
The trait for generating structured data from arbitrary, unstructured input.
About
The Arbitrary
crate lets you construct arbitrary instances of a type.
This crate is primarily intended to be combined with a fuzzer like libFuzzer
and cargo-fuzz
or
AFL, and to help you turn the raw,
untyped byte buffers that they produce into well-typed, valid, structured
values. This allows you to combine structure-aware test case generation with
coverage-guided, mutation-based fuzzers.
Documentation
Read the API documentation on docs.rs
!
Example
Say you're writing a color conversion library, and you have an Rgb
struct to
represent RGB colors. You might want to implement Arbitrary
for Rgb
so that
you could take arbitrary Rgb
instances in a test function that asserts some
property (for example, asserting that RGB converted to HSL and converted back to
RGB always ends up exactly where we started).
Automatically Deriving Arbitrary
Automatically deriving the Arbitrary
trait is the recommended way to implement
Arbitrary
for your types.
Automatically deriving Arbitrary
requires you to enable the "derive"
cargo
feature:
# Cargo.toml
[dependencies]
arbitrary = { version = "1", features = ["derive"] }
And then you can simply add #[derive(Arbitrary)]
annotations to your types:
// rgb.rs
use arbitrary::Arbitrary;
#[derive(Arbitrary)]
pub struct Rgb {
pub r: u8,
pub g: u8,
pub b: u8,
}
Customizing single fields
This can be particular handy if your structure uses a type that does not implement Arbitrary
or you want to have more customization for particular fields.
#[derive(Arbitrary)]
pub struct Rgba {
// set `r` to Default::default()
#[arbitrary(default)]
pub r: u8,
// set `g` to 255
#[arbitrary(value = 255)]
pub g: u8,
// Generate `b` with a custom function of type
//
// fn(&mut Unstructured) -> arbitrary::Result<T>
//
// where `T` is the field's type.
#[arbitrary(with = arbitrary_b)]
pub b: u8,
// Generate `a` with a custom closure (shortuct to avoid a custom function)
#[arbitrary(with = |u: &mut Unstructured| u.int_in_range(0..=64))]
pub a: u8,
}
fn arbitrary_b(u: &mut Unstructured) -> arbitrary::Result<u8> {
u.int_in_range(64..=128)
}
Implementing Arbitrary
By Hand
Alternatively, you can write an Arbitrary
implementation by hand:
// rgb.rs
use arbitrary::{Arbitrary, Result, Unstructured};
#[derive(Copy, Clone, Debug)]
pub struct Rgb {
pub r: u8,
pub g: u8,
pub b: u8,
}
impl<'a> Arbitrary<'a> for Rgb {
fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {
let r = u8::arbitrary(u)?;
let g = u8::arbitrary(u)?;
let b = u8::arbitrary(u)?;
Ok(Rgb { r, g, b })
}
}
License
Licensed under dual MIT or Apache-2.0 at your choice.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
Dependencies
~105KB