1
votes

I'm writing unit tests for some function macros, which are just wrappers around some function calls, with a little housekeeping thrown in.

I've been writing tests all morning and I'm starting to get tedium of the brainpan, so this might just be a case of tunnel vision, but:

Is there a valid case to be made for unit testing for macro expansion? By that I mean checking that the correct function behavior is produced for the various source code forms of the function macro's arguments. For example, function arguments can take the form, in source code of a:

  • literal
  • variable
  • operator expression
  • struct member access
  • pointer-to-struct member access
  • pointer dereference
  • array index
  • function call
  • macro expansion
  • (feel free to point out any that I've missed)

If the macro doesn't expand properly, then the code usually won't even compile. So then, is there even any sensible point in a different unit test if the argument was a float literal or a float variable, or the result of a function call?

Should the expansion be part of the unit test?

2
Definitely, if you forgot to put parentheses around each and every instance of the macro arguments. Otherwise, not so much. But really, this is mostly a matter of opinion, or at least a case-by-case decision. - user3386109
Using expressions such as value & 1 could reveal that the macros are careless, but code inspections can do that too. I think going through the full panoply of tests is overkill; the tedium is giving you a relevant warning. - Jonathan Leffler
@JonathanLeffler: Yeah, I have to watch myself sometimes. I get way into the groove covering edge cases and ticking all the boxes that if I'm not careful, I'll wind up writing tests to cover solar eclipses and invasions from Mars. - Mark Benningfield

2 Answers

1
votes

As I noted in a comment:

Using expressions such as value & 1 could reveal that the macros are careless, but code inspections can do that too.

I think going through the full panoply of tests is overkill; the tedium is giving you a relevant warning.

There is an additional mode of checking that might be relevant, namely side-effects such as: x++ + ++y as an argument. If the argument to the macro is evaluated more than once, the side-effects will probably be scrambled, or at least repeated. An I/O function (getchar(), or printf("Hello World\n")) as the argument might also reveal mismanagement of arguments.

It also depends in part on the rules you want to apply to the macros. However, if they're supposed to look like and behave like function calls, they should only evaluate arguments once (but they should evaluate each argument — if the macro doesn't evaluate an argument at all, then the side-effects won't occur that should occur (that would occur if the macro was really a function).

Also, don't underestimate the value of inline functions.

0
votes

Based on the comments and some of the points made in @Jonathan Leffler's answer, I've come to the conclusion that this is something that is better tested in functional testing, preferably with a fuzz tester.

That way, using a couple of automation scripts, the fuzzer can throw a jillion arguments at the function macro and log those that either don't compile, produce compiler warnings, or compile and run, but produce the incorrect result.

Since fuzz tests aren't supposed to run quickly (like unit tests), there's no problem just adding it to the fuzz suite and letting it run over the weekend.