mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat(eth-wire): enforce test-fuzz traits pre-fuzz (#545)
* directs types we generate fuzz tests for to a method that is more restrictive in the traits each input type should implement, so if any type does not implement the test-fuzz required traits it will fail to compile instead of fail to autogenerate a fuzz test at runtime.
This commit is contained in:
@ -9,7 +9,7 @@ use std::fmt::Debug;
|
||||
/// The test will create a random instance of the type, encode it, and then decode it.
|
||||
fn roundtrip_encoding<T>(thing: T)
|
||||
where
|
||||
T: Encodable + Decodable + Clone + Serialize + Debug + PartialEq + Eq,
|
||||
T: Encodable + Decodable + Debug + PartialEq + Eq,
|
||||
{
|
||||
let mut encoded = Vec::new();
|
||||
thing.encode(&mut encoded);
|
||||
@ -17,6 +17,21 @@ where
|
||||
assert_eq!(thing, decoded, "expected: {thing:?}, got: {decoded:?}");
|
||||
}
|
||||
|
||||
/// This method delegates to roundtrip_encoding, but is used to enforce that each type input to the
|
||||
/// macro has a proper Default, Clone, and Serialize impl. These trait implementations are
|
||||
/// necessary for test-fuzz to autogenerate a corpus.
|
||||
///
|
||||
/// If it makes sense to remove a Default impl from a type that we fuzz, this should prevent the
|
||||
/// fuzz test from compiling, rather than failing at runtime.
|
||||
/// In this case, we should implement a wrapper for the type that should no longer implement
|
||||
/// Default, Clone, or Serialize, and fuzz the wrapper type instead.
|
||||
fn roundtrip_fuzz<T>(thing: T)
|
||||
where
|
||||
T: Encodable + Decodable + Clone + Serialize + Debug + PartialEq + Eq + Default,
|
||||
{
|
||||
roundtrip_encoding::<T>(thing)
|
||||
}
|
||||
|
||||
/// Creates a fuzz test for a rlp encodable and decodable type.
|
||||
macro_rules! fuzz_type_and_name {
|
||||
( $x:ty, $fuzzname:ident ) => {
|
||||
@ -24,7 +39,7 @@ macro_rules! fuzz_type_and_name {
|
||||
#[test_fuzz]
|
||||
#[allow(non_snake_case)]
|
||||
fn $fuzzname(thing: $x) {
|
||||
roundtrip_encoding::<$x>(thing)
|
||||
crate::roundtrip_fuzz::<$x>(thing)
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -46,7 +61,34 @@ pub mod fuzz_rlp {
|
||||
use crate::roundtrip_encoding;
|
||||
|
||||
// p2p subprotocol messages
|
||||
fuzz_type_and_name!(HelloMessage, fuzz_HelloMessage);
|
||||
|
||||
// see message below for why wrapper types are necessary for fuzzing types that do not have a
|
||||
// Default impl
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
RlpEncodableWrapper,
|
||||
RlpDecodableWrapper,
|
||||
)]
|
||||
struct HelloMessageWrapper(HelloMessage);
|
||||
|
||||
impl Default for HelloMessageWrapper {
|
||||
fn default() -> Self {
|
||||
HelloMessageWrapper(HelloMessage {
|
||||
client_version: Default::default(),
|
||||
capabilities: Default::default(),
|
||||
protocol_version: Default::default(),
|
||||
id: Default::default(),
|
||||
port: Default::default(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fuzz_type_and_name!(HelloMessageWrapper, fuzz_HelloMessage);
|
||||
fuzz_type_and_name!(DisconnectReason, fuzz_DisconnectReason);
|
||||
|
||||
// eth subprotocol messages
|
||||
|
||||
Reference in New Issue
Block a user