#define TESTFAILED 0 #define TESTGOOD 1 #define TESTSKIPPED -1 #include #define TESTDATA "./tests/data/" // very helpfull: https://mgalgs.io/2013/05/10/hacking-your-ELF-for-fun-and-profit.html #define TESTNAME(NAME) test_##NAME #define TESTFUNC(NAME) int TESTNAME(NAME)() #define REGISTERTEST(NAME) static const testdef __test_ ## NAME \ __attribute((__section__("testlist"))) \ __attribute((__used__)) = { \ TESTNAME(NAME), \ #NAME, \ } #define TEST(NAME) static TESTFUNC(NAME); \ REGISTERTEST(NAME); \ TESTFUNC(NAME) { #define TESTEND return TESTGOOD; } \ #define ASSERT(BED, ERR) if(!(BED)) { std::cout << __FILE__ << ":" << __LINE__ << " " << ERR << ' ' << std::flush; return TESTFAILED; } #define CMPASSERTE(IS, SHOULD, ERR) if( !((IS) == (SHOULD))) { std::cout << __FILE__ << ":" << __LINE__ << " is: \"" << (IS) << "\" should: \"" << (SHOULD) << "\" "<< std::flush; return TESTFAILED; } #define CMPASSERT(IS, SHOULD) CMPASSERTE(IS, SHOULD, "") #define SKIPTEST return TESTSKIPPED typedef int (*test_t)(); struct testdef { test_t testf; const char* name; }; // linker generates this <3 extern struct testdef __start_testlist; extern struct testdef __stop_testlist;