From 1f5eedfa8b28c3a95603b74a0efbd58c93e3f39c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Enrique=20Mu=C3=B1oz=20Mart=C3=ADn?= Date: Wed, 13 Dec 2023 18:39:37 +0100 Subject: [PATCH] MockBuilder: extend trait generic support when the generics are themself generic (#16) * improve testing * fix issue --- mock-builder/src/location.rs | 124 +++++++++++++++++++++-------------- mock-builder/tests/pallet.rs | 26 +++++++- 2 files changed, 99 insertions(+), 51 deletions(-) diff --git a/mock-builder/src/location.rs b/mock-builder/src/location.rs index fbe9c7a..ef0bb05 100644 --- a/mock-builder/src/location.rs +++ b/mock-builder/src/location.rs @@ -60,23 +60,17 @@ impl FunctionLocation { let (path, name) = self.location.rsplit_once("::").expect("always '::'"); let (path, trait_info) = match path.strip_prefix('<') { Some(struct_as_trait_path) => { - let struct_path = struct_as_trait_path + let (struct_path, trait_path) = struct_as_trait_path .split_once(" as") - .expect("always ' as'") - .0; + .expect("always ' as'"); - let trait_name = struct_as_trait_path - .rsplit_once("::") - .expect("always '::'") - .1 - .strip_suffix('>') - .unwrap(); - - // Remove generic from trait name - let trait_name = trait_name + let trait_name = trait_path .split_once('<') - .map(|(fst, _)| fst) - .unwrap_or(trait_name); + .map(|(name, _generics)| name) + .unwrap_or(trait_path.strip_suffix('>').unwrap()) + .rsplit_once("::") + .expect("Always '::'") + .1; (struct_path, Some(trait_name.to_owned())) } @@ -156,12 +150,16 @@ mod tests { } trait TraitExampleGen { - fn foo() -> FunctionLocation; + fn generic() -> FunctionLocation; } - struct Example; + trait Config { + type Assoc; + } - impl Example { + struct Example(core::marker::PhantomData); + + impl Example { fn mock_method() -> FunctionLocation { FunctionLocation::from(|| ()) } @@ -171,12 +169,17 @@ mod tests { FunctionLocation::from(|| ()) } + #[allow(non_snake_case)] + fn mock_TraitExampleGen_generic() -> FunctionLocation { + FunctionLocation::from(|| ()) + } + fn mock_generic_method>(_: impl Into) -> FunctionLocation { FunctionLocation::from(|| ()) } } - impl TraitExample for Example { + impl TraitExample for Example { fn method() -> FunctionLocation { FunctionLocation::from(|| ()) } @@ -186,59 +189,68 @@ mod tests { } } - impl TraitExampleGen for Example { - fn foo() -> FunctionLocation { + impl TraitExampleGen for Example { + fn generic() -> FunctionLocation { FunctionLocation::from(|| ()) } } + struct TestConfig; + impl Config for TestConfig { + type Assoc = u32; + } + #[test] fn function_location() { assert_eq!( - Example::mock_method(), + Example::::mock_method(), FunctionLocation { - location: format!("{PREFIX}::Example::mock_method"), + location: format!("{PREFIX}::Example<{PREFIX}::TestConfig>::mock_method"), trait_info: None, } ); assert_eq!( - Example::mock_TraitExample_method(), + Example::::mock_TraitExample_method(), FunctionLocation { - location: format!("{PREFIX}::Example::mock_TraitExample_method"), + location: format!( + "{PREFIX}::Example<{PREFIX}::TestConfig>::mock_TraitExample_method" + ), trait_info: None, } ); assert_eq!( - Example::mock_generic_method::(0u8), + Example::::mock_generic_method::(0u8), FunctionLocation { - location: format!("{PREFIX}::Example::mock_generic_method"), + location: format!("{PREFIX}::Example<{PREFIX}::TestConfig>::mock_generic_method"), trait_info: None, } ); assert_eq!( - Example::method(), + Example::::method(), FunctionLocation { - location: format!("<{PREFIX}::Example as {PREFIX}::TraitExample>::method"), + location: format!( + "<{PREFIX}::Example<{PREFIX}::TestConfig> as {PREFIX}::TraitExample>::method" + ), trait_info: None, } ); assert_eq!( - Example::generic_method::(0u8), + Example::::generic_method::(0u8), FunctionLocation { - location: format!("<{PREFIX}::Example as {PREFIX}::TraitExample>::generic_method"), + location: format!("<{PREFIX}::Example<{PREFIX}::TestConfig> as {PREFIX}::TraitExample>::generic_method"), trait_info: None, } ); assert_eq!( - Example::foo(), + Example::::generic(), FunctionLocation { location: format!( - "<{PREFIX}::Example as {PREFIX}::TraitExampleGen>::foo" + "<{PREFIX}::Example<{PREFIX}::TestConfig> as {PREFIX}::TraitExampleGen<<{PREFIX}::TestConfig as {PREFIX}::Config>::Assoc, bool>>::generic" ), trait_info: None, } @@ -248,33 +260,35 @@ mod tests { #[test] fn normalized() { assert_eq!( - Example::mock_method().normalize(), + Example::::mock_method().normalize(), FunctionLocation { - location: format!("{PREFIX}::Example::mock_method"), + location: format!("{PREFIX}::Example<{PREFIX}::TestConfig>::mock_method"), trait_info: None, } ); assert_eq!( - Example::mock_TraitExample_method().normalize(), + Example::::mock_TraitExample_method().normalize(), FunctionLocation { - location: format!("{PREFIX}::Example::mock_TraitExample_method"), + location: format!( + "{PREFIX}::Example<{PREFIX}::TestConfig>::mock_TraitExample_method" + ), trait_info: None, } ); assert_eq!( - Example::method().normalize(), + Example::::method().normalize(), FunctionLocation { - location: format!("{PREFIX}::Example::method"), + location: format!("{PREFIX}::Example<{PREFIX}::TestConfig>::method"), trait_info: Some("TraitExample".into()), } ); assert_eq!( - Example::foo().normalize(), + Example::::generic().normalize(), FunctionLocation { - location: format!("{PREFIX}::Example::foo"), + location: format!("{PREFIX}::Example<{PREFIX}::TestConfig>::generic"), trait_info: Some("TraitExampleGen".into()), } ); @@ -283,10 +297,10 @@ mod tests { #[test] fn striped_name_prefix() { assert_eq!( - Example::mock_method().strip_name_prefix("mock_"), + Example::::mock_method().strip_name_prefix("mock_"), FunctionLocation { - location: format!("{PREFIX}::Example::method"), - trait_info: None + location: format!("{PREFIX}::Example<{PREFIX}::TestConfig>::method"), + trait_info: None, } ); } @@ -294,32 +308,42 @@ mod tests { #[test] fn assimilated_trait_prefix() { assert_eq!( - Example::mock_method() + Example::::mock_method() .strip_name_prefix("mock_") .assimilate_trait_prefix(), FunctionLocation { - location: format!("{PREFIX}::Example::method"), - trait_info: None + location: format!("{PREFIX}::Example<{PREFIX}::TestConfig>::method"), + trait_info: None, } ); assert_eq!( - Example::mock_TraitExample_method() + Example::::mock_TraitExample_method() .strip_name_prefix("mock_") .assimilate_trait_prefix(), FunctionLocation { - location: format!("{PREFIX}::Example::method"), + location: format!("{PREFIX}::Example<{PREFIX}::TestConfig>::method"), trait_info: Some("TraitExample".into()), } ); + + assert_eq!( + Example::::mock_TraitExampleGen_generic() + .strip_name_prefix("mock_") + .assimilate_trait_prefix(), + FunctionLocation { + location: format!("{PREFIX}::Example<{PREFIX}::TestConfig>::generic"), + trait_info: Some("TraitExampleGen".into()), + } + ); } #[test] fn appended_type_signature() { assert_eq!( - Example::mock_method().append_type_signature::(), + Example::::mock_method().append_type_signature::(), FunctionLocation { - location: format!("{PREFIX}::Example::mock_method:i8->u8"), + location: format!("{PREFIX}::Example<{PREFIX}::TestConfig>::mock_method:i8->u8"), trait_info: None, } ); diff --git a/mock-builder/tests/pallet.rs b/mock-builder/tests/pallet.rs index 1a7ea51..407b283 100644 --- a/mock-builder/tests/pallet.rs +++ b/mock-builder/tests/pallet.rs @@ -12,6 +12,10 @@ pub trait TraitB { fn same_name(p1: i32) -> bool; } +pub trait TraitGen { + fn generic() -> u32; +} + pub trait Storage { fn set(value: i32); fn get() -> i32; @@ -73,6 +77,11 @@ pub mod pallet_mock_test { pub fn mock_TraitB_same_name(f: impl Fn(i32) -> bool + 'static) { register_call!(f); } + + #[allow(non_snake_case)] + pub fn mock_TraitGen_generic(f: impl Fn() -> u32 + 'static) { + register_call!(move |()| f()); + } } impl super::TraitA for Pallet { @@ -111,6 +120,12 @@ pub mod pallet_mock_test { } } + impl super::TraitGen for Pallet { + fn generic() -> u32 { + execute_call!(()) + } + } + impl super::Storage for Pallet { fn set(a: i32) { execute_call!(a) @@ -198,7 +213,7 @@ mod mock { mod test { use frame_support::assert_ok; - use super::{mock::*, Storage, TraitA, TraitB}; + use super::{mock::*, Storage, TraitA, TraitB, TraitGen}; #[test] fn basic() { @@ -332,4 +347,13 @@ mod test { assert_eq!(::same_name(23), true); }); } + + #[test] + fn method_from_generic_trait_long_path() { + new_test_ext().execute_with(|| { + MockTest::mock_TraitGen_generic(|| 23); + + assert_eq!(MockTest::generic(), 23); + }); + } }