How to test if your ASSERT macro is compiled out
I am often interested in how specific code works in different build configurations. In the case of a custom ASSERT macro, I want to make sure that it does not evaluate any expression in builds where it is disabled (i.e. it is 'compiled out'). The technique I use is the following:
Let's assume CHECK_EQUALS is a macro in your test framework that checks if it's two inputs are equal. ASSERT behaves as usual. Let's also assume, your build system somewhere defines ASSERTS_ENABLED in those builds where this is so desired. Here is some code:
C++:
- TEST(AssertBehavesCorrectlyAcrossBuildConfigs)
- {
- int a = 0;
- ASSERT(a = 100);
- #ifdef ASSERTS_ENABLED
- CHECK_EQUALS(a, 100);
- #else
- CHECK_EQUALS(a, 0);
- #endif
- }
What's happening here? The expression inside ASSERT contains code with a side effect. If the ASSERT macro is defined to do anything, the side effect is that a is being set to 100. The expression evaluates to true, and no harm is done. Otherwise a will stay at 0, in which case we can safely say that ASSERT does not evaluate the expression.
April 23rd, 2006 at 2:34
Can you test that such code compiles out completely in certain builds? For example in the case of logging. If you use a macro, there’ll be no code generated… But macros aren’t so great for arbitrary numbers of parameters that you want to pass in sprintf-style.
April 23rd, 2006 at 3:00
So you mean how I would test if something is compiled out without using macros?
Well in such a case, like logging, I would probably have a class that forwards all logged messages to obsevers. In a final build I would want to attach a test observer that just checks if it was called or not, failing the test if it was called. So my logging class would not be really “compiled out” but it would just do nothing in certain builds, like the final build. If you can’t use macros, you will have to have some code being called in all builds, and hope that the compiler optimises out empty function calls and such.