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