Amogh Sarpotdar
Amogh Sarpotdar

Reputation: 617

Unit test for ensuring conditionally compiled code in c++

This is a standard C++ ASSERT macro defined in my code -

#ifndef DEBUG
#define ASSERT(n)
#else
#define ASSERT(n) \
if (!(n)){  \
    printf("%s - Failed ", #n); \
    printf("On %s ", __DATE__); \
    printf("At %s ", __TIME__); \
    printf("In File %s ", __FILE__); \
    printf("At Line %d\n", __LINE__); \
    exit(1);}
#endif

I want to ensure that my build always contains this code, by binding a unit test around it. The test should check that if #DEBUG preprocessor is not supplied (i.e. it is release mode), a conditional check applied in unit test should fail with ASSERT macro failing and containing the message given above.

Is there an established way to achieve this? I am using google test framework to achieve this, but unable to achieve the result. Test fails with standard assertion message, not the custom assertion I am trying it to fail with. My code is as below -

TEST(VerifyNormalInitialization, VerifyAssert)
{
    static int index = 0;
    static int num = 4;
    ASSERT(index == num);
    EXPECT_FATAL_FAILURE(ASSERT(index == num),"Failed");
}

Upvotes: 0

Views: 956

Answers (2)

Lundin
Lundin

Reputation: 213266

Consider

EXPECT_FATAL_FAILURE(if (!(index == num)){ ... },"Failed");

Does that look like valid C++? It is not.

Consider writing a macro which passes along #n, __FILE__ etc to a proper function. If you insist on using a macro alone, then it needs to be a single expression and not a statement, something along the lines of:

#define STR2(x) #x
#define STR(x) STR2(x)

#define ASSERT(n)                                          \
(                                                          \
  fprintf(stderr,                                          \
          #n " - Failed on " __DATE__ " at " __TIME__      \
          " in file " __FILE__ " at line " STR(__LINE__)   \
         ),                                                \
  exit(EXIT_FAILURE)                                       \
)

This is using compile-time string concatenation to prepare the whole string. Everything in this expression is string literals, and two string literals such as "hello" and "world" get concatenated by the pre-processor as "helloworld".

The "stringification" macros are just there to convert the integer __LINE__ into a string literal. Stringification - how does it work?

Note that the ), is the comma operator, which is used to allow two function calls in the same expression.

Upvotes: 0

Joop Eggen
Joop Eggen

Reputation: 109532

First the obvious the following raises only an error when DEBUG is defined.

ASSERT(index == num);
ASSERT(index != num);

For unit tests for both cases: production and development, you need to compile both ways.

You might effect that by your own #define/#undef DEBUG.

Good practice? I do not know; I was not aware that this was something worthwile testing. Maybe just a verification that ASSERTs are active during development. And that is something for an installation check.

Upvotes: 1

Related Questions