How to wrap a macro

I'm trying to do a simple wrap in the info! and error! macros from log so I can use them in tests.

This is what I did. I created wrap functions to be imported just in the case we're testing, like this:

#[cfg(not(test))] 
use log::{info, error}; // Use log crate when building application
#[cfg(test)]
use crate::{info, error}; // Workaround to use prinltn! for logs.

Here it is:

#[macro_export]
macro_rules! info {
    (target: $target:expr, $($arg:tt)*) => { println!("target: {}, info: {}", $target, $($arg),*) };
    ($($arg:tt)*) => { println!("info: {}", $($arg),*) };
}

#[macro_export]
macro_rules! error {
    (target: $target:expr, $($arg:tt)*) => { printn!("target: {}, info: {}", $target, $($arg),*) };
    ($($arg:tt)*) => { println!("error: {}", $($arg),*) };
}

Then I call like this:

       error!("Unauthorized message has authentication header but WwwAuthenticate fails to parse. RTSP Message: {:?}", message);

but I get:

error: expected expression, found `,`
   --> src/rtsp_machine.rs:440:96
    |
440 |                     "Unauthorized message has no AuthenticationInfo header. RTSP Message: {:?}",
    |                                                                                                ^ expected expression

Something is wrong with the repetition in the macro argument but I don't know what exactly

The macro takes $($arg:tt)* parameters (which is any amount of any token), and expands to $($arg),*, which puts commas between all the tokens. What you want is to expand to $($arg)*.

#[macro_export]
macro_rules! info {
    (target: $target:expr, $($arg:tt)*) => { println!("target: {}, info: {}", $target, $($arg)*) };
    ($($arg:tt)*) => { println!("info: {}", $($arg)*) };
}

#[macro_export]
macro_rules! error {
    (target: $target:expr, $($arg:tt)*) => { printn!("target: {}, info: {}", $target, $($arg)*) };
    ($($arg:tt)*) => { println!("error: {}", $($arg)*) };
}

I now get

error: argument never used
   --> src/rtsp_machine.rs:433:137
    |
433 | ...WwwAuthenticate fails to parse. RTSP Message: {:?}", message);
    |                                                         ^^^^^^^ argument never used
    | 
   ::: src/log_test.rs:16:33
    |
16  |     ($($arg:tt)*) => { println!("error: {}", $($arg)*) };
    |                                 ----------- formatting specifier missing

Somehow the third argument is not being used. Do you have an idea?

This is what I'm trying now:

#[macro_export]
macro_rules! info {
    (target: $target:expr, $fmt:expr, $($arg:tt)*) => {
        println!("target: {}, info: {}", $target, format!("{}", $($arg)*)); 
    };
    ($fmt:expr, $($arg:tt)*) => { 
        println!("info: {}", $($arg)*);
    };
}

info!(
    "Unauthorized message has no AuthenticationInfo header. RTSP Message: {:?}",
    "message"
);

info!(
    "i",
    "filling basic challenge for realm: {}", "realm"
);

with

   Compiling playground v0.0.1 (/playground)
error: macro expansion ignores token `{` and any following
    | 
   ::: src/lib.rs:8:9
    |
8   |           println!("info: {}", $($arg)*);
    |           ------------------------------- caused by the macro expansion here
    |
    = note: the usage of `println!` is likely invalid in item context

error: macro expansion ignores token `{` and any following
    | 
   ::: src/lib.rs:8:9
    |
8   |           println!("info: {}", $($arg)*);
    |           ------------------------------- caused by the macro expansion here
    |
    = note: the usage of `println!` is likely invalid in item context

Now that you have another example for how you want to use it, I can write something that works:
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=5b75dbd45edb451b9c62003d63d639b4

#[macro_export]
macro_rules! info {
    (target: $target:expr, $fmt:expr $(, $($arg:tt)*)?) => {
        println!(concat!("target: {}, info: ", $fmt), $target, $($($arg)*)?);
    };
    ($fmt:expr $(, $($arg:tt)*)?) => {
        println!(concat!("info: ", $fmt), $($($arg)*)?);
    };
}

fn main() {
    info!(
        "Unauthorized message has no AuthenticationInfo header. RTSP Message: {:?}",
        "message"
    );

    info!(
        target: "i",
        "filling basic challenge for realm: {}",
        "realm"
    );
}

This prints

info: Unauthorized message has no AuthenticationInfo header. RTSP Message: "message"
target: i, info: filling basic challenge for realm: realm

The first post makes it sound like you wanted to use log::{info, error} in tests but hit some issue when trying to do so. Just in case that's the case: you should be able to use them without any workaround as long as you make sure initialise a logger in the test function.