diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/libbb.h | 135 | ||||
-rw-r--r-- | include/platform.h | 3 |
2 files changed, 138 insertions, 0 deletions
diff --git a/include/libbb.h b/include/libbb.h index 7a3610bb9..cede50cc2 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1941,6 +1941,141 @@ static ALWAYS_INLINE unsigned char bb_ascii_tolower(unsigned char a) #define isprint_asciionly(a) ((unsigned)((a) - 0x20) <= 0x7e - 0x20) +/* Simple unit-testing framework */ + +typedef void (*bbunit_testfunc)(void); + +struct bbunit_listelem { + struct bbunit_listelem* next; + const char* name; + bbunit_testfunc testfunc; +}; + +void bbunit_registertest(struct bbunit_listelem* test); +void bbunit_settestfailed(void); + +#define BBUNIT_DEFINE_TEST(NAME) \ + static void bbunit_##NAME##_test(void); \ + static struct bbunit_listelem bbunit_##NAME##_elem = { \ + .name = #NAME, \ + .testfunc = bbunit_##NAME##_test, \ + }; \ + static void INIT_LAST bbunit_##NAME##_register(void) \ + { \ + bbunit_registertest(&bbunit_##NAME##_elem); \ + } \ + static void bbunit_##NAME##_test(void) + +/* + * Both 'goto bbunit_end' and 'break' are here only to get rid + * of compiler warnings. + */ +#define BBUNIT_ENDTEST \ + do { \ + goto bbunit_end; \ + bbunit_end: \ + break; \ + } while (0) + +#define BBUNIT_PRINTASSERTFAIL \ + do { \ + bb_error_msg( \ + "[ERROR] Assertion failed in file %s, line %d", \ + __FILE__, __LINE__); \ + } while (0) + +#define BBUNIT_ASSERTION_FAILED \ + do { \ + bbunit_settestfailed(); \ + goto bbunit_end; \ + } while (0) + +/* + * Assertions. + * For now we only offer assertions which cause tests to fail + * immediately. In the future 'expects' might be added too - + * similar to those offered by the gtest framework. + */ +#define BBUNIT_ASSERT_EQ(EXPECTED, ACTUAL) \ + do { \ + if ((EXPECTED) != (ACTUAL)) { \ + BBUNIT_PRINTASSERTFAIL; \ + bb_error_msg("[ERROR] '%s' isn't equal to '%s'", \ + #EXPECTED, #ACTUAL); \ + BBUNIT_ASSERTION_FAILED; \ + } \ + } while (0) + +#define BBUNIT_ASSERT_NOTEQ(EXPECTED, ACTUAL) \ + do { \ + if ((EXPECTED) == (ACTUAL)) { \ + BBUNIT_PRINTASSERTFAIL; \ + bb_error_msg("[ERROR] '%s' is equal to '%s'", \ + #EXPECTED, #ACTUAL); \ + BBUNIT_ASSERTION_FAILED; \ + } \ + } while (0) + +#define BBUNIT_ASSERT_NOTNULL(PTR) \ + do { \ + if ((PTR) == NULL) { \ + BBUNIT_PRINTASSERTFAIL; \ + bb_error_msg("[ERROR] '%s' is NULL!", #PTR); \ + BBUNIT_ASSERTION_FAILED; \ + } \ + } while (0) + +#define BBUNIT_ASSERT_NULL(PTR) \ + do { \ + if ((PTR) != NULL) { \ + BBUNIT_PRINTASSERTFAIL; \ + bb_error_msg("[ERROR] '%s' is not NULL!", #PTR); \ + BBUNIT_ASSERTION_FAILED; \ + } \ + } while (0) + +#define BBUNIT_ASSERT_FALSE(STATEMENT) \ + do { \ + if ((STATEMENT)) { \ + BBUNIT_PRINTASSERTFAIL; \ + bb_error_msg("[ERROR] Statement '%s' evaluated to true!", \ + #STATEMENT); \ + BBUNIT_ASSERTION_FAILED; \ + } \ + } while (0) + +#define BBUNIT_ASSERT_TRUE(STATEMENT) \ + do { \ + if (!(STATEMENT)) { \ + BBUNIT_PRINTASSERTFAIL; \ + bb_error_msg("[ERROR] Statement '%s' evaluated to false!", \ + #STATEMENT); \ + BBUNIT_ASSERTION_FAILED; \ + } \ + } while (0) + +#define BBUNIT_ASSERT_STREQ(STR1, STR2) \ + do { \ + if (strcmp(STR1, STR2) != 0) { \ + BBUNIT_PRINTASSERTFAIL; \ + bb_error_msg("[ERROR] Strings '%s' and '%s' " \ + "are not the same", STR1, STR2); \ + BBUNIT_ASSERTION_FAILED; \ + } \ + } while (0) + +#define BBUNIT_ASSERT_STRNOTEQ(STR1, STR2) \ + do { \ + if (strcmp(STR1, STR2) == 0) { \ + BBUNIT_PRINTASSERTFAIL; \ + bb_error_msg("[ERROR] Strings '%s' and '%s' " \ + "are the same, but were " \ + "expected to differ", STR1, STR2); \ + BBUNIT_ASSERTION_FAILED; \ + } \ + } while (0) + + POP_SAVED_FUNCTION_VISIBILITY #endif diff --git a/include/platform.h b/include/platform.h index 92f775551..413c2224c 100644 --- a/include/platform.h +++ b/include/platform.h @@ -76,6 +76,9 @@ # define UNUSED_PARAM_RESULT #endif +/* used by unit test machinery to run registration functions */ +#define INIT_LAST __attribute__ ((constructor(2000))) + /* -fwhole-program makes all symbols local. The attribute externally_visible * forces a symbol global. */ #if __GNUC_PREREQ(4,1) |