0

I want to write a macro to support parameterized tests, and got the following code from AI, but got errors on one line:

#[macro_export]
macro_rules! parameterize {
    ($name:ident, $params:pat, {$($test_name:ident : ($($args:expr),*)),*}, $test_body:block) => {
        $(
            fn $name_\$test_name() {   //<========= this line
                let $params = ($($args),*);
                $test_body
            }
        )*
     };
}

parameterize! {
     should_be_added,
     (expected, a, b),
     {
         positive: (3, 1, 2),
         zero: (0, 0, 0),
         negative: (-5, -2, -3),
         large_numbers: (999999, 444444, 555555)
     },
     {
         println!("a={}, b={}, expected={}", a, b, expected);
     }
}

fn main() {
   positive();
   negative();
}

If I change fn $name_\$test_name() to fn $test_name() , it works well.

So I want to know how to concatenate the two variables $name $test_name to output one string. For example, if $name is foo and $test_name is bar, how to output foo_bar?

Peter Hall
  • 53,120
  • 14
  • 139
  • 204
Zach
  • 5,715
  • 12
  • 47
  • 62
  • 1
    I think you'll need a separate package for this, like [`paste!`](https://docs.rs/paste/latest/paste/). – tadman Feb 19 '23 at 02:22
  • For what it's worth, you can write tests like this using `for (expected, inputs) in vec![ (...,...), ... ] { assert_eq!(f(inputs), expected) }` – tadman Feb 19 '23 at 02:23

1 Answers1

1

There is a crate called paste, that provides a macro for concatenating tokens inside declarative macros.

To use it, wrap your entire result in the paste! macro, and then you can concatenate tokens by placing them between [< and >] with spaces to separate.

use paste::paste;

#[macro_export]
macro_rules! parameterize {
    ($name:ident, $params:pat, {$($test_name:ident : ($($args:expr),*)),*}, $test_body:block) => {
        paste! {
            $(
                fn [<$name _ $test_name>]() { // <- special syntax used by paste!
                    let $params = ($($args),*);
                    $test_body
                }
            )*
        }
     };
}

Using the remainder of the code you've provided, this would generate functions should_be_added_positive and should_be_added_negative.

Peter Hall
  • 53,120
  • 14
  • 139
  • 204