Macro plugin_test

Source
macro_rules! plugin_test {
    (@output_ty $InputType:ty) => { ... };
    (@output_ty $InputType:ty, $OutputType:ty) => { ... };
    (
        model: $ModelName:ty,
        input: $InputTy:ty,
        output: $OutputTy:ty,
        context: $ContextTy:ty,
        value: $ContextExpr:expr,
        cases: { $(($test_name:ident, $input_expr:expr, $expected:expr)),* $(,)? }
    ) => { ... };
    (
        model: $ModelName:ty,
        input: $InputTy:ty,
        context: $ContextTy:ty,
        value: $ContextExpr:expr,
        cases: { $(($test_name:ident, $input_expr:expr, $expected:expr)),* $(,)? }
    ) => { ... };
    (
        model: $ModelName:ty,
        input: $InputTy:ty,
        output: $OutputTy:ty,
        cases: { $(($test_name:ident, $input_expr:expr, $expected:expr)),* $(,)? }
    ) => { ... };
    (
        model: $ModelName:ty,
        input: $InputTy:ty,
        cases: { $(($test_name:ident, $input_expr:expr, $expected:expr)),* $(,)? }
    ) => { ... };
    (
        model: $ModelName:ty,
        input: mut $InputTy:ty,
        output: $OutputTy:ty,
        context: $ContextTy:ty,
        value: $ContextExpr:expr,
        cases: { $(($test_name:ident, $input_expr:expr, $expected:expr $(, $expected_input:expr)?)),* $(,)? }
    ) => { ... };
    (
        model: $ModelName:ty,
        input: mut $InputTy:ty,
        context: $ContextTy:ty,
        value: $ContextExpr:expr,
        cases: { $(($test_name:ident, $input_expr:expr, $expected:expr $(, $expected_input:expr)?)),* $(,)? }
    ) => { ... };
    (
        model: $ModelName:ty,
        input: mut $InputTy:ty,
        output: $OutputTy:ty,
        cases: { $(($test_name:ident, $input_expr:expr, $expected:expr $(, $expected_input:expr)?)),* $(,)? }
    ) => { ... };
    (
        model: $ModelName:ty,
        input: mut $InputTy:ty,
        cases: { $(($test_name:ident, $input_expr:expr, $expected:expr $(, $expected_input:expr)?)),* $(,)? }
    ) => { ... };
}
Expand description

Generates table-driven unit tests for plugin models.

It supports both immutable and mutable models, with or without context, and with either explicit or inferred output types.

For each test case, the macro:

  • Instantiates the plugin model using Default
  • Constructs the required context (if any)
  • Executes the model’s computation (compute for immutable models, compute_mut for mutable models)
  • Asserts that the computed output matches the expected value
  • Optionally asserts the final mutated input state for mutable models

Each test case expands into an independent #[test] function, ensuring clear isolation and accurate failure reporting.

§Features

  • Supports immutable (PurePluginModel) and mutable (MutablePluginModel) models
  • Supports context-aware and context-free plugin models
  • Supports explicit output types or implicit output = input
  • Optional assertion of the mutated input value for mutable models
  • Generates one #[test] function per case
  • Avoids boilerplate while preserving full type safety
  • Mirrors the exact runtime execution contract of plugin models

§Supported Forms

The macro supports the same four combinations for both immutable and mutable models:

| Context | Output | +—––+——+ | Yes | Explicit | | Yes | Inferred (output = input) | | No | Explicit | | No | Inferred (output = input) |

Mutable models are declared by using input: mut Type, which indicates that the model will receive &mut Type and may transform the input in-place.

§Syntax

plugin_test! {
    model: ModelType,              // Plugin model type to test
    input: InputType | mut InputType, // `mut` enables mutable model testing
    output: OutputType,            // Optional: defaults to `InputType` if omitted
    context: ContextType,          // Optional: required if model uses context
    value: context_expr,           // Optional: expression constructing the context
    cases: {
        (test_name, input_expr, expected_output),
        (test_name_2, input_expr_2, expected_output_2, expected_mutated_input), // mutable only
    }
}
  • model: Plugin model type implementing PurePluginModel or MutablePluginModel
  • input: Input type consumed by the model (mut indicates in-place mutation)
  • output: Output type produced by the model (defaults to input type if omitted)
  • context: Context type required by the model (omit for ())
  • value: Expression that constructs the context instance
  • cases: List of test tuples

Each case tuple has the form:

  • (name, input, expected_output) for immutable models
  • (name, input, expected_output) for mutable models when only output is asserted
  • (name, input, expected_output, expected_mutated_input) to also verify the final mutated state of the input

When the fourth element is provided, the macro additionally checks that the input was correctly transformed in-place.

§Notes

  • Each test case expands into a separate #[test] function
  • Context and input types must match the model’s trait implementation
  • Output inference (output = input) follows the same rule as plugin_model!
  • Compilation fails if input, context, or output types are incompatible

This macro is intended for testing plugin model logic in isolation and should not be used for testing pallet storage, dispatchables, or runtime configuration.