23 releases (12 breaking)

new 0.13.1 Mar 20, 2025
0.12.0 Nov 27, 2024
0.11.1 Jun 20, 2024
0.10.2 Mar 4, 2024
0.2.0 Oct 16, 2019

#517 in Testing

Download history 9601/week @ 2024-11-30 8234/week @ 2024-12-07 6203/week @ 2024-12-14 1569/week @ 2024-12-21 3268/week @ 2024-12-28 4773/week @ 2025-01-04 7204/week @ 2025-01-11 5927/week @ 2025-01-18 5964/week @ 2025-01-25 10328/week @ 2025-02-01 7621/week @ 2025-02-08 8808/week @ 2025-02-15 10556/week @ 2025-02-22 9420/week @ 2025-03-01 17363/week @ 2025-03-08 10274/week @ 2025-03-15

48,689 downloads per month
Used in 36 crates (7 directly)

MIT license

195KB
5.5K SLoC

bolero-generator

value generator for testing and fuzzing

Installation

bolero-generator is on crates.io and can be added to a project like so:

$ cargo add --dev bolero-generator

Usage

Simple type generator

use bolero_generator::{gen, driver::FuzzDriver, ValueGenerator};
let input = &[1, 2, 3, 4, 5];
let driver = FuzzDriver::new(&input);

let value = gen::<u8>().generate(&mut driver).unwrap();

Parameterized value generator

use bolero_generator::{gen, driver::FuzzDriver, ValueGenerator};
let input = &[1, 2, 3, 4, 5];
let driver = FuzzDriver::new(&input);

let value = gen::<u8>().with().bounds(5..=42).generate(&mut driver).unwrap();

Nested parameterized value generator

use bolero_generator::{gen, driver::FuzzDriver, ValueGenerator};
let input = &[1, 2, 3, 4, 5];
let driver = FuzzDriver::new(&input);

let value = (
    gen::<u8>(),
    gen::<u8>()
        .with()
        .bounds(5..=42), // between 5 and including 42
    gen::<Vec<u32>>()
        .with()
        .len(6usize) // always have 6 values
        .values(7..500), // between 7 and 500
).generate(&mut driver).unwrap();

Value modifications with map and and_then

use bolero_generator::{gen, driver::FuzzDriver, ValueGenerator};
let input = &[1, 2, 3, 4, 5];
let driver = FuzzDriver::new(&input);

let value = gen::<u8>()
    .map(|value| value / 2)
    .and_then(|value| gen::<Vec<u8>>().with().len(value as usize))
    .generate(&mut driver)
    .unwrap()

Prior work

arbitrary

While bolero draws a lot of inspiration from the rust_arbitrary crate, several improvements were added:

Parameterized generation

Arbitrary supports basic value generation, given a type:

let driver = RingBuffer::new(input, 20).unwrap();
let value: u8 = Arbitrary::arbitrary(&mut driver).unwrap();

This can be limiting when constraints need to be applied to the type:

let driver = RingBuffer::new(input, 20).unwrap();
let value: u8 = Arbitrary::arbitrary(&mut driver).unwrap();
// make sure `value` in between 8 and 20
let value = (value % (20 - 8)) + 8;

The same issue arises from container sizes being limited to 0-255:

let driver = RingBuffer::new(input, 20).unwrap();
let mut value: Vec<u8> = Arbitrary::arbitrary(&mut driver).unwrap();
// make sure `value` has at least 3 items
while value.len() < 3 {
    value.push(Arbitrary::arbitrary(&mut driver).unwrap());
}
// make sure `value` has no more than 42 items
while value.len() > 42 {
    value.pop();
}

bolero supports value generation, given a type:

let driver = FuzzDriver::new(&[1, 2, 3, 4, 5]);
let value = gen::<u8>().generate(&mut driver).unwrap();

Parameterized generators can be created by calling with()

let driver = FuzzDriver::new(&[1, 2, 3, 4, 5]);
let value = gen::<u8>().with().bounds(8..=20).generate(&mut driver).unwrap();

Container sizes can be specified as well:

let driver = FuzzDriver::new(&[1, 2, 3, 4, 5]);
let value = gen::<Vec<u8>>().with().len(3usize..=42).generate(&mut driver).unwrap();

#![no_std] compatibility

bolero supports environments that require #![no_std].

Dependencies

~4MB
~95K SLoC