unit-tests: implement the unit-testing framework
This set of patches adds a simple unit-testing framework to Busybox unit-tests: add some helper macros for unit-test framework implementation unit-tests: implement the unit-testing framework unit-tests: add basic documentation on writing the unit test cases unit-tests: modify the Makefile 'test' target to run unit-tests too unit-tests: add two example test cases unit-tests: modify the existing strrstr test code to use the unit-test framework Signed-off-by: Bartosz Golaszewski <bartekgola@gmail.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
committed by
Denys Vlasenko
parent
5d2e409ef8
commit
3ed81cf052
135
include/libbb.h
135
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
|
||||
|
@@ -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)
|
||||
|
Reference in New Issue
Block a user