Arbitrary
用于从任意、非结构化输入生成结构化数据的特征。
关于
Arbitrary
crate 允许你构造类型的任意实例。
这个 crate 主要用于与模糊测试工具(如 libFuzzer 和 cargo-fuzz
或 AFL)结合使用,帮助你将它们生成的原始、无类型字节缓冲区转换为类型良好、有效的结构化值。这使你能够将结构感知的测试用例生成与基于覆盖率引导、变异的模糊测试工具结合起来。
文档
示例
假设你正在编写一个颜色转换库,并且有一个 Rgb
结构体来表示 RGB 颜色。你可能想为 Rgb
实现 Arbitrary
,这样你就可以在测试函数中使用任意的 Rgb
实例来断言某些属性(例如,断言 RGB 转换为 HSL 再转换回 RGB 总是能得到我们开始的确切结果)。
自动派生 Arbitrary
自动派生 Arbitrary
特征是为你的类型实现 Arbitrary
的推荐方式。
自动派生 Arbitrary
需要你启用 "derive" cargo 特性:
# Cargo.toml
[dependencies]
arbitrary = { version = "1", features = ["derive"] }
然后你可以简单地为你的类型添加 #[derive(Arbitrary)]
注解:
// rgb.rs
use arbitrary::Arbitrary;
#[derive(Arbitrary)]
pub struct Rgb {
pub r: u8,
pub g: u8,
pub b: u8,
}
自定义单个字段
如果你的结构体使用了一个没有实现 Arbitrary
的类型,或者你想为特定字段进行更多自定义,这特别有用。
#[derive(Arbitrary)]
pub struct Rgba {
// 将 `r` 设置为 Default::default()
#[arbitrary(default)]
pub r: u8,
// 将 `g` 设置为 255
#[arbitrary(value = 255)]
pub g: u8,
// 使用自定义函数生成 `b`,函数类型为
//
// fn(&mut Unstructured) -> arbitrary::Result<T>
//
// 其中 `T` 是字段的类型。
#[arbitrary(with = arbitrary_b)]
pub b: u8,
// 使用自定义闭包生成 `a`(避免自定义函数的快捷方式)
#[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)
}
手动实现 Arbitrary
或者,你可以手动编写 Arbitrary
实现:
// 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 })
}
}
许可证
根据你的选择,采用 MIT 或 Apache-2.0 双重许可。
除非你明确声明,否则你有意提交以包含在本项目中的任何贡献,按照 Apache-2.0 许可证中的定义,都将按上述方式双重许可,无任何附加条款或条件。