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));