blob: a55e6d6e7d72aa6bf0cb71b5e227a2379fdd7fd3 [file] [log] [blame]
#![cfg(feature = "derive")]
use arbitrary::*;
fn arbitrary_from<T: Arbitrary>(input: &[u8]) -> T {
let mut buf = Unstructured::new(input);
T::arbitrary(&mut buf).expect("can create arbitrary instance OK")
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Arbitrary)]
pub struct Rgb {
pub r: u8,
pub g: u8,
pub b: u8,
}
#[test]
fn struct_with_named_fields() {
let rgb: Rgb = arbitrary_from(&[4, 5, 6]);
assert_eq!(rgb.r, 4);
assert_eq!(rgb.g, 5);
assert_eq!(rgb.b, 6);
assert_eq!(
rgb.shrink().collect::<Vec<_>>(),
vec![
Rgb { r: 0, g: 0, b: 0 },
Rgb { r: 2, g: 2, b: 3 },
Rgb { r: 1, g: 1, b: 1 }
]
);
assert_eq!((3, Some(3)), <Rgb as Arbitrary>::size_hint(0));
}
#[derive(Copy, Clone, Debug, Arbitrary)]
struct MyTupleStruct(u8, bool);
#[test]
fn tuple_struct() {
let s: MyTupleStruct = arbitrary_from(&[43, 42]);
assert_eq!(s.0, 43);
assert_eq!(s.1, false);
let s: MyTupleStruct = arbitrary_from(&[42, 43]);
assert_eq!(s.0, 42);
assert_eq!(s.1, true);
for ((a, b), s) in 42.shrink().zip(true.shrink()).zip(s.shrink()) {
assert_eq!(a, s.0);
assert_eq!(b, s.1);
}
assert_eq!((2, Some(2)), <MyTupleStruct as Arbitrary>::size_hint(0));
}
#[derive(Clone, Debug, Arbitrary)]
struct EndingInVec(u8, bool, u32, Vec<u16>);
#[derive(Clone, Debug, Arbitrary)]
struct EndingInString(u8, bool, u32, String);
#[test]
fn test_take_rest() {
let bytes = [1, 1, 1, 2, 3, 4, 5, 6, 7, 8];
let s1 = EndingInVec::arbitrary_take_rest(Unstructured::new(&bytes)).unwrap();
let s2 = EndingInString::arbitrary_take_rest(Unstructured::new(&bytes)).unwrap();
assert_eq!(s1.0, 1);
assert_eq!(s2.0, 1);
assert_eq!(s1.1, true);
assert_eq!(s2.1, true);
assert_eq!(s1.2, 0x4030201);
assert_eq!(s2.2, 0x4030201);
assert_eq!(s1.3, vec![0x605, 0x807]);
assert_eq!(s2.3, "\x05\x06\x07\x08");
}
#[derive(Copy, Clone, Debug, Arbitrary)]
enum MyEnum {
Unit,
Tuple(u8, u16),
Struct { a: u32, b: (bool, u64) },
}
#[test]
fn derive_enum() {
let mut raw = vec![
// The choice of which enum variant takes 4 bytes.
1, 2, 3, 4,
// And then we need up to 13 bytes for creating `MyEnum::Struct`, the
// largest variant.
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
];
let mut saw_unit = false;
let mut saw_tuple = false;
let mut saw_struct = false;
for i in 0..=255 {
// Choose different variants each iteration.
for el in &mut raw[..4] {
*el = i;
}
let e: MyEnum = arbitrary_from(&raw);
match e {
MyEnum::Unit => {
saw_unit = true;
assert_eq!(e.shrink().count(), 0);
}
MyEnum::Tuple(a, b) => {
saw_tuple = true;
assert_eq!(a, arbitrary_from(&raw[4..5]));
assert_eq!(b, arbitrary_from(&raw[5..]));
for ((a, b), e) in a.shrink().zip(b.shrink()).zip(e.shrink()) {
match e {
MyEnum::Tuple(c, d) => {
assert_eq!(a, c);
assert_eq!(b, d);
}
_ => panic!("should never shrink to a different variant"),
}
}
}
MyEnum::Struct { a, b } => {
saw_struct = true;
assert_eq!(a, arbitrary_from(&raw[4..8]));
assert_eq!(b, arbitrary_from(&raw[8..]));
for ((a, b), e) in a.shrink().zip(b.shrink()).zip(e.shrink()) {
match e {
MyEnum::Struct { a: c, b: d } => {
assert_eq!(a, c);
assert_eq!(b, d);
}
_ => panic!("should never shrink to a different variant"),
}
}
}
}
}
assert!(saw_unit);
assert!(saw_tuple);
assert!(saw_struct);
assert_eq!((4, Some(17)), <MyEnum as Arbitrary>::size_hint(0));
}
#[derive(Arbitrary, Debug)]
enum RecursiveTree {
Leaf,
Node {
left: Box<RecursiveTree>,
right: Box<RecursiveTree>,
},
}
#[test]
fn recursive() {
let raw = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
let _rec: RecursiveTree = arbitrary_from(&raw);
let (lower, upper) = <RecursiveTree as Arbitrary>::size_hint(0);
assert_eq!(lower, 4, "need a u32 for the discriminant at minimum");
assert!(
upper.is_none(),
"potentially infinitely recursive, so no upper bound"
);
}