tags:

views:

26

answers:

1

In a project of mine (which for technical reasons must not depend on any external libraries or third-party sources) I have set up the following test.h:

static int rc = 0;
#define TESTCASE( x ) if ( x ) {} \
                      else \
                      { \
                          rc += 1; \
                          printf( "FAILED: " __FILE__ ", line %d - " #x "\n", __LINE__ ); \
                      }

This works fine most of the time - if the testcase evaluates to true, nothing happens. If the testcase evaluates to false, the testcase is printed including file name and line number.

However, when the testcase contains a string literal, the printf() in the TESTCASE macro insists on interpreting the string literal as part of the format string (which proved fatal for a certain testcase).

Now I am pondering various approaches to get the printf() to print whatever is in x (the testcase) verbatim, but I've come up empty. The closest thing was to use %c to print a fixed numbers of characters, and pass the textcase (#x) as parameter to printf() - but I couldn't figure out how to determine the size of #x, especially if it contains zero bytes (which rules out any use of strlen()).

Confused, and at a loss. Help?

+3  A: 

what about using %s as a format then passing the stringified test case as a parameter, like you did for the line number ?

printf( "FAILED: %s, line %d - %s\n", __FILE__, __LINE__, #x );

the # convert the argument to a properly double-quote delimited string, so nothing prevents you from passing this string as an argument to printf...

(you should never use any value that is not hardcoded as a format string for printf: that's raising hell most of the time)

Adrien Plisson
A good first appriach, but what if the string literal in #x contains zero bytes?
DevSolar
I don't think this is possible: a zero byte has no representation, it is not valid in a C source file and thus cannot appear in your test case. (or the definition of the `TEST_CASE` macro in your question is wrong) remember that the `#` preprocessor operator is a stringizer, it converts `abc` appearing literally in the macro argument by `"abc"`.
Adrien Plisson
And here I was halfway through typing 'hey, I could write "\0" into a string literal anytime' when I realized that '\0' is the *representation* of a zero byte, not the thing itself. AAaaargh... half my brain must have been asleep. You are absolutely right, of course.
DevSolar