reth_db/tables/codecs/fuzz/mod.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
//! Implements fuzzing targets to be used by test-fuzz
mod inputs;
/// Fuzzer generates a random instance of the object and proceeds to encode and decode it. It then
/// makes sure that it matches the original object.
///
/// Some types like [`IntegerList`] might have some restrictions on how they're fuzzed. For example,
/// the list is assumed to be sorted before creating the object.
macro_rules! impl_fuzzer_with_input {
($(($name:tt, $input_type:tt, $encode:tt, $encode_method:tt, $decode:tt, $decode_method:tt)),+) => {
$(
/// Macro generated module to be used by test-fuzz and `bench` if it applies.
#[allow(non_snake_case)]
#[cfg(any(test, feature = "bench"))]
pub mod $name {
use reth_db_api::table;
#[allow(unused_imports)]
use reth_primitives_traits::*;
#[allow(unused_imports)]
use super::inputs::*;
#[allow(unused_imports)]
use reth_db_api::models::*;
/// Encodes and decodes table types returning its encoded size and the decoded object.
/// This method is used for benchmarking, so its parameter should be the actual type that is being tested.
pub fn encode_and_decode(obj: $name) -> (usize, $name) {
let data = table::$encode::$encode_method(obj);
let size = data.len();
// Some `data` might be a fixed array.
(size, table::$decode::$decode_method(&data).expect("failed to decode"))
}
#[cfg(test)]
#[allow(dead_code)]
#[allow(missing_docs)]
#[test_fuzz::test_fuzz]
pub fn fuzz(obj: $input_type) {
let obj: $name = obj.into();
assert!(encode_and_decode(obj.clone()).1 == obj );
}
#[test]
#[allow(missing_docs)]
pub fn test() {
fuzz($input_type::default())
}
}
)+
};
}
/// Fuzzer generates a random instance of the object and proceeds to encode and decode it. It then
/// makes sure that it matches the original object.
macro_rules! impl_fuzzer_key {
($($name:tt),+) => {
$(
impl_fuzzer_with_input!(($name, $name, Encode, encode, Decode, decode));
)+
};
}
/// Fuzzer generates a random instance of the object and proceeds to compress and decompress it. It
/// then makes sure that it matches the original object.
#[allow(unused_macros)]
macro_rules! impl_fuzzer_value {
($($name:tt),+) => {
$(
impl_fuzzer_value_with_input!($name, $name);
)+
};
}
/// Fuzzer generates a random instance of the object and proceeds to compress and decompress it. It
/// then makes sure that it matches the original object. It supports being fed a different kind of
/// input, as long as it supports `Into<T>`.
macro_rules! impl_fuzzer_value_with_input {
($(($name:tt, $input:tt)),+) => {
$(
impl_fuzzer_with_input!(($name, $input, Compress, compress, Decompress, decompress));
)+
};
}
impl_fuzzer_key!(BlockNumberAddress);
impl_fuzzer_value_with_input!((IntegerList, IntegerListInput));