4
\$\begingroup\$

I like from the C++ unit test framework Catch2 its sections -- much more than the xUnit test fixtures. Therefore I wrote me some macros which mimic the Catch2 sections.

This is the first macro heavy code I wrote, so I am mostly interested whether the macros do what they should do, or not.

#include <utility>
#define TOKENPASTE_HELPER(x, y) x ## y
#define TOKENPASTE(x, y) TOKENPASTE_HELPER(x, y)
#define CASE( name ) \
 if ( int executed_section = 0, first_run = 0; true ) \
 while ( std::exchange(executed_section, 0) || first_run++ == 0 )
#define SECTION( name ) \
 static int TOKENPASTE(counter_done_, __LINE__) = 0; \
 goto TOKENPASTE(section_start_, __LINE__); \
 TOKENPASTE(section_end_, __LINE__): \
 continue; \
 TOKENPASTE(section_start_, __LINE__): \
 while ( true ) \
 if ( TOKENPASTE(counter_done_, __LINE__) == 2 ) { \
 break; \
 } else if( TOKENPASTE(counter_done_, __LINE__) == 1 ) { \
 TOKENPASTE(counter_done_, __LINE__) = 2; \
 goto TOKENPASTE(section_end_, __LINE__); \
 } else if ( TOKENPASTE(counter_done_, __LINE__) = 1, executed_section=1; true )

They are used like this:

#include <cassert>
int main() {
 CASE( i_test ) {
 int i = 0;
 SECTION( i==1 ) {
 ++i;
 assert( i == 1 );
 }
 SECTION( i == 0 ) {
 assert( i == 0 );
 }
 }
 CASE( ii_test ) {
 int i = 10;
 SECTION() {
 assert( i==10 );
 }
 }
}
asked Aug 4 at 20:53
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Just... sigh. Don't use macros. But since you are using macros, please show the output of gcc -E or equivalent. \$\endgroup\$ Commented Aug 5 at 1:01

1 Answer 1

3
\$\begingroup\$

The output of gcc -E is

int main() {
 if ( int executed_section = 0, first_run = 0; true ) while ( std::exchange(executed_section, 0) || first_run++ == 0 ) {
 int i = 0;
 static int counter_done_27 = 0; goto section_start_27; section_end_27: continue; section_start_27: while ( true ) if ( counter_done_27 == 2 ) { break; } else if( counter_done_27 == 1 ) { counter_done_27 = 2; goto section_end_27; } else if ( counter_done_27 = 1, executed_section=1; true ) {
 ++i;
 assert( i == 1 );
 }
 static int counter_done_32 = 0; goto section_start_32; section_end_32: continue; section_start_32: while ( true ) if ( counter_done_32 == 2 ) { break; } else if( counter_done_32 == 1 ) { counter_done_32 = 2; goto section_end_32; } else if ( counter_done_32 = 1, executed_section=1; true ) {
 assert( i == 0 );
 }
 }
 if ( int executed_section = 0, first_run = 0; true ) while ( std::exchange(executed_section, 0) || first_run++ == 0 ) {
 int i = 10;
 static int counter_done_39 = 0; goto section_start_39; section_end_39: continue; section_start_39: while ( true ) if ( counter_done_39 == 2 ) { break; } else if( counter_done_39 == 1 ) { counter_done_39 = 2; goto section_end_39; } else if ( counter_done_39 = 1, executed_section=1; true ) {
 assert( i==10 );
 }
 }
}

I do recommend that you check output like this for macro-heavy code. And... what does it even do. It feels like it's written to be a puzzle, and test frameworks shouldn't be a puzzle. The goto, exchange, non-re-entrant statics... None of this should see the light of day, and it should all be deleted. I strongly recommend that you retry this project and pretend that the precompiler does not exist. The same features can be implemented with contemporary C++, especially lambdas.

answered Aug 5 at 1:34
\$\endgroup\$
2
  • \$\begingroup\$ Well, the output of gcc -E is exactly what it should be. \$\endgroup\$ Commented Aug 5 at 7:27
  • \$\begingroup\$ While I agree it would be better to write a test framework that doesn't require macros, if the goal is to make a drop-in replacement for Catch2, I don't see how you could do that. \$\endgroup\$ Commented Aug 7 at 8:28

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.