reth_db/tables/codecs/fuzz/
mod.rs

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