Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

fungible conformance tests: Inspect and Mutate #13852

Merged
merged 47 commits into from
May 4, 2023

Conversation

liamaharon
Copy link
Contributor

@liamaharon liamaharon commented Apr 7, 2023

Partial: paritytech/polkadot-sdk#225

Implements conformance tests for fungible traits Inspect and Mutate.

  • Pattern for creating a function that accepts something implementing Inspect + Mutate

    •   pub fn something<T, AccountId, Balance>()
        where
            T: Mutate<AccountId> + Inspect<AccountId, Balance = Balance>,
            AccountId: AtLeast8BitUnsigned,
            Balance: AtLeast8BitUnsigned + Debug,
        {}
  • Implement inspect and mutate conformance tests (frame/support/src/traits/tokens/fungible/conformance_tests/inspect_mutate.rs)

  • Test conformance tests against balances (frame/balances/src/tests/fungible_conformance_tests.rs)

    •  cargo test --package pallet-balances -- tests::fungible_conformance_tests:: --nocapture
      
  • Create a macro to generate test cases wrapped with some logic

@liamaharon liamaharon added A3-in_progress Pull request is in progress. No review needed at this stage. C1-low PR touches the given topic and has a low impact on builders. labels Apr 7, 2023
@liamaharon liamaharon added D3-trivial 🧸 PR contains trivial changes in a runtime directory that do not require an audit B1-note_worthy Changes should be noted in the release notes T1-runtime This PR/Issue is related to the topic “runtime”. labels Apr 7, 2023
@sam0x17
Copy link
Contributor

sam0x17 commented Apr 7, 2023

This should lend itself well to a simple macro. Based on your description I think you should be able to write a regular proc macro that accepts those args (I generally recommend making a MyUseCaseArgs struct and using derive_syn_parse to get an automatic Parse implementation for it, it can even do things like optional fields etc). The proc macro would then expand to a test case like the one you are writing.

you mention that Balance and AccountId need to be passed. Are these always just <Test as frame_system::Config>::AccountId and <Test as pallet_balances::Config>::Balance or is there some variation there necessitating them being part of the input. I'm assuming based on your examples that these are always the same? Anyway, here is a contrived example

If the inputs are just a few idents or paths (or any syn type separated by commas with some optional args at the end), you could have something like:

#[derive(derive_syn_parse::Parse)]
struct InspectMutateConformanceTestArgs {
    some_ident: syn::Ident,
    _comma1: syn::token::Comma,
    some_path: syn::Path,
    _comma2: Option<syn::token::Comma>,
    #[parse_if(_comma2.is_some())]
    optional_path: Option<syn::Path>,
}

#[proc_macro]
pub fn inspect_mutate_conformance_tests(tokens: TokenStream) -> TokenStream {
    let args = parse_macro_input!(tokens as InspectMutateConformanceTestArgs);
    let test_ident = quote::format_ident!("mint_into_{}", args.some_ident);
    // other stuff with args ...
    quote::quote! {
        #[test]
        fn #test_ident() {
            ExtBuilder::default().build_and_execute_with(|| {
                conformance_tests::inspect_mutate::#test_ident::<
                    Balances,
                    <Test as frame_system::Config>::AccountId,
                    <Test as pallet_balances::Config>::Balance,
                >();
            });
        }
    }
}

Something vaguely like that, I'm just not 100% clear on what the args would be, but the above would let you parse args like this:

inspect_mutate_conformance_tests!(an_ident, some::cool_path);

And optionally have a third field like:

inspect_mutate_conformance_tests!(another_ident, different::path, an::optional::path);

Hope this helps. If you can give me exact desired usage of the proc macro I can give you something tighter

@KiChjang
Copy link
Contributor

KiChjang commented Apr 7, 2023

I think something as simple as this doesn't require a proc macro, and can still be easily done using a declarative macro using macro_rules!:

macro_rules! inspect_mutate_conformance_tests {
    ($name:ident, $some_path:path $(, $optional_path:path)?) => /* macro code goes here */
}

And with the clever usage of paste::paste!, we can create custom names for the tests as well using declarative macros.

@sam0x17
Copy link
Contributor

sam0x17 commented Apr 7, 2023

Yes I agree a macro_rules would be fine here unless you want to be very strict about what you are passing in which looks like it is not necessary if it's idents and paths. A proc macro would be nice if you want to assert that one of the inputs is a very specific syn type, for example

edit: although concating idents is a hell of a lot easier in proc macros...

@liamaharon
Copy link
Contributor Author

liamaharon commented Apr 7, 2023

Ahh thanks all, really appreciate the examples.

Originally I had been thinking about the macro living with the generalised tests, but I see now it would be much more simple if it was with the implementation, allowing the implementation to customise the environment the tests are run in without anything too complicated.

It also would allow the implementor to run the same sets of test with different environment parameters, e.g. balances could easily run the tests with different values for existential_deposit (perhaps opportunity for more fuzzing). 👌

@liamaharon
Copy link
Contributor Author

@xlc if you have time it would be nice to get your eyes on this given you're likely to use it with orml-tokens.

and @gavofyork also curious to get your eyes on this if you have time, given it's your issue I'd like to check that this satisfies the requirements you had in mind.

@liamaharon liamaharon requested review from gavofyork, ggwpez and kianenigma and removed request for kianenigma and ggwpez April 18, 2023 14:45
@liamaharon liamaharon changed the title fungible Inspect and Mutate conformance tests fungible conformance tests: Inspect and Mutate Apr 28, 2023
Copy link
Member

@gavofyork gavofyork left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good.

@liamaharon liamaharon merged commit 6be90cf into master May 4, 2023
@liamaharon liamaharon deleted the liam-fungibles-conformance-tests branch May 4, 2023 16:21
nathanwhit pushed a commit to nathanwhit/substrate that referenced this pull request Jul 19, 2023
* typo

* - create test files for each fungile trait
- begin implementing tests for the Inspect trait

* wrap inspect tests in a macro

* first run of mutate tests

* move test implementation out of ballances

* make tests more generic

* transfer tests

* combine inspect and mutate tests

* set balance failing tests

* can_deposit tests

* can_withdraw tests

* test reducible_balance

* remove balanced stub

* revert set_balance return val fix

* typo

* macro and dust trap tests

* disable test when it doesn't make sense

* remove debug comment

* reduce macro boilerplate

* improved var naming

* improve variable naming

* remove redundant comment

* remove placeholder tests

* remove placeholder tests

* simplify macro

* Update frame/balances/src/tests/fungible_conformance_tests.rs

Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>

* use Balance from T

* fix copyright

* add test doc comments

* improve test naming

* clippy

* fix rustdoc errors

* fix rustdoc

* improve macro

* improve variable naming

* remove redundant comment

* use path

---------

Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
A0-please_review Pull request needs code review. B1-note_worthy Changes should be noted in the release notes C1-low PR touches the given topic and has a low impact on builders. D3-trivial 🧸 PR contains trivial changes in a runtime directory that do not require an audit T1-runtime This PR/Issue is related to the topic “runtime”.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants