Skip to content

Commit

Permalink
Fix START_TEST to look like valid C code.
Browse files Browse the repository at this point in the history
Instead of exporting the defined name as a bare function, export a
struct that has a pointer to the function, but also its name, file and
line number where it is defined.

Store that information into a new `struct TTest`.

After this commit, START_TEST(<testname>) will create three definitions:
- <testname>_fn: The actual function;
- <testname>_ttest: A `struct TTest` with the information about it;
- <testname>: A pointer to <testname>_ttest.

Functions `tcase_add_test()` and friends are updated to take a `TTest *`
argument rather than a `TFun` and separate name. The runners are updated
to find that information inside the linked `tc->ttest`. The call to
`tcase_fn_start()` is moved from the defined functions to the runners
(both the "fork" and the "nofork" one) which call it just before
invoking the test function.

A nice side-effect is that END_TEST is now optional, though the empty
`#define` is kept for backwards compability.

v2: Initialize the struct TTest by position to be compatible with older
compilers that do not recognize named fields (e.g. VS 2010, VS 2012.)

Tested:
- `make check` still passes.
- Removing END_TEST from test cases still produces valid code that
  builds and passes tests.
  • Loading branch information
filbranden committed Jun 14, 2018
1 parent 65e8c5e commit 4a75af2
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 30 deletions.
10 changes: 5 additions & 5 deletions src/check.c
Original file line number Diff line number Diff line change
Expand Up @@ -247,21 +247,21 @@ void suite_add_tcase(Suite * s, TCase * tc)
check_list_add_end(s->tclst, tc);
}

void _tcase_add_test(TCase * tc, TFun fn, const char *name, int _signal,
int allowed_exit_value, int start, int end)
void _tcase_add_test(TCase * tc, const TTest * ttest,
int _signal, int allowed_exit_value,
int start, int end)
{
TF *tf;

if(tc == NULL || fn == NULL || name == NULL)
if(tc == NULL || ttest == NULL)
return;
tf = (TF *)emalloc(sizeof(TF)); /* freed in tcase_free */
tf->fn = fn;
tf->ttest = ttest;
tf->loop_start = start;
tf->loop_end = end;
tf->signal = _signal; /* 0 means no signal expected */
tf->allowed_exit_value =
(WEXITSTATUS_MASK & allowed_exit_value); /* 0 is default successful exit */
tf->name = name;
check_list_add_end(tc->tflst, tf);
}

Expand Down
51 changes: 33 additions & 18 deletions src/check.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,16 @@ typedef void (*SFun) (void);
*/
typedef struct Suite Suite;

/**
* Type for a test, which wraps a test function
*/
typedef struct TTest {
const char *name;
TFun fn;
const char *file;
int line;
} TTest;

/**
* Creates a test suite with the given name.
*
Expand Down Expand Up @@ -214,8 +224,8 @@ CK_DLL_EXP void CK_EXPORT tcase_set_tags(TCase * tc,
*
* @since 0.9.2
* */
#define tcase_add_test_raise_signal(tc,tf,signal) \
_tcase_add_test((tc),(tf),"" # tf "",(signal), 0, 0, 1)
#define tcase_add_test_raise_signal(tc,ttest,signal) \
_tcase_add_test((tc),(ttest),(signal), 0, 0, 1)

/**
* Add a test function with an expected exit value to a test case
Expand All @@ -229,8 +239,8 @@ CK_DLL_EXP void CK_EXPORT tcase_set_tags(TCase * tc,
*
* @since 0.9.7
*/
#define tcase_add_exit_test(tc, tf, expected_exit_value) \
_tcase_add_test((tc),(tf),"" # tf "",0,(expected_exit_value),0,1)
#define tcase_add_exit_test(tc, ttest, expected_exit_value) \
_tcase_add_test((tc),(ttest),0,(expected_exit_value),0,1)

/**
* Add a looping test function to a test case
Expand All @@ -246,8 +256,8 @@ CK_DLL_EXP void CK_EXPORT tcase_set_tags(TCase * tc,
*
* @since 0.9.4
*/
#define tcase_add_loop_test(tc,tf,s,e) \
_tcase_add_test((tc),(tf),"" # tf "",0,0,(s),(e))
#define tcase_add_loop_test(tc,ttest,s,e) \
_tcase_add_test((tc),(ttest),0,0,(s),(e))

/**
* Add a looping test function with signal handling to a test case
Expand All @@ -267,8 +277,8 @@ CK_DLL_EXP void CK_EXPORT tcase_set_tags(TCase * tc,
*
* @since 0.9.5
*/
#define tcase_add_loop_test_raise_signal(tc,tf,signal,s,e) \
_tcase_add_test((tc),(tf),"" # tf "",(signal),0,(s),(e))
#define tcase_add_loop_test_raise_signal(tc,ttest,signal,s,e) \
_tcase_add_test((tc),(ttest),(signal),0,(s),(e))

/**
* Add a looping test function with an expected exit value to a test case
Expand All @@ -288,16 +298,15 @@ CK_DLL_EXP void CK_EXPORT tcase_set_tags(TCase * tc,
*
* @since 0.9.7
*/
#define tcase_add_loop_exit_test(tc,tf,expected_exit_value,s,e) \
_tcase_add_test((tc),(tf),"" # tf "",0,(expected_exit_value),(s),(e))
#define tcase_add_loop_exit_test(tc,ttest,expected_exit_value,s,e) \
_tcase_add_test((tc),(ttest),0,(expected_exit_value),(s),(e))

/* Add a test function to a test case
(function version -- use this when the macro won't work
*/
CK_DLL_EXP void CK_EXPORT _tcase_add_test(TCase * tc, TFun tf,
const char *fname, int _signal,
int allowed_exit_value, int start,
int end);
CK_DLL_EXP void CK_EXPORT _tcase_add_test(TCase * tc, const TTest * ttest,
int _signal, int allowed_exit_value,
int start, int end);

/**
* Add unchecked fixture setup/teardown functions to a test case
Expand Down Expand Up @@ -400,16 +409,22 @@ CK_DLL_EXP const char* CK_EXPORT tcase_name(void);
* @since 0.6.0
*/
#define START_TEST(__testname)\
static void __testname (int _i CK_ATTRIBUTE_UNUSED)\
{\
tcase_fn_start (""# __testname, __FILE__, __LINE__);
static void __testname ## _fn (int _i CK_ATTRIBUTE_UNUSED);\
static const TTest __testname ## _ttest = {\
.name = ""# __testname,\
.fn = __testname ## _fn,\
.file = __FILE__,\
.line = __LINE__,\
};\
static const TTest * __testname = & __testname ## _ttest;\
static void __testname ## _fn (int _i CK_ATTRIBUTE_UNUSED)

/**
* End a unit test
*
* @since 0.6.0
*/
#define END_TEST }
#define END_TEST

/*
* Fail the test case unless expr is false
Expand Down
3 changes: 1 addition & 2 deletions src/check_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,9 @@

typedef struct TF
{
TFun fn;
const TTest * ttest;
int loop_start;
int loop_end;
const char *name;
int signal;
signed char allowed_exit_value;
} TF;
Expand Down
2 changes: 1 addition & 1 deletion src/check_log.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ void log_test_start(SRunner * sr, TCase * tc, TF * tfun)
{
char buffer[100];

snprintf(buffer, 99, "%s:%s", tc->name, tfun->name);
snprintf(buffer, 99, "%s:%s", tc->name, tfun->ttest->name);
srunner_send_evt(sr, buffer, CLSTART_T);
}

Expand Down
10 changes: 6 additions & 4 deletions src/check_run.c
Original file line number Diff line number Diff line change
Expand Up @@ -415,11 +415,12 @@ static TestResult *tcase_run_tfun_nofork(SRunner * sr, TCase * tc, TF * tfun,
clock_gettime(check_get_clockid(), &ts_start);
if(0 == setjmp(error_jmp_buffer))
{
tfun->fn(i);
tcase_fn_start(tfun->ttest->name, tfun->ttest->file, tfun->ttest->line);
tfun->ttest->fn(i);
}
clock_gettime(check_get_clockid(), &ts_end);
tcase_run_checked_teardown(tc);
return receive_result_info_nofork(tc->name, tfun->name, i,
return receive_result_info_nofork(tc->name, tfun->ttest->name, i,
DIFF_IN_USEC(ts_start, ts_end));
}

Expand Down Expand Up @@ -491,7 +492,8 @@ static TestResult *tcase_run_tfun_fork(SRunner * sr, TCase * tc, TF * tfun,
tr = tcase_run_checked_setup(sr, tc);
free(tr);
clock_gettime(check_get_clockid(), &ts_start);
tfun->fn(i);
tcase_fn_start(tfun->ttest->name, tfun->ttest->file, tfun->ttest->line);
tfun->ttest->fn(i);
clock_gettime(check_get_clockid(), &ts_end);
tcase_run_checked_teardown(tc);
send_duration_info(DIFF_IN_USEC(ts_start, ts_end));
Expand Down Expand Up @@ -535,7 +537,7 @@ static TestResult *tcase_run_tfun_fork(SRunner * sr, TCase * tc, TF * tfun,

killpg(pid, SIGKILL); /* Kill remaining processes. */

return receive_result_info_fork(tc->name, tfun->name, i, status,
return receive_result_info_fork(tc->name, tfun->ttest->name, i, status,
tfun->signal, tfun->allowed_exit_value);
}

Expand Down

0 comments on commit 4a75af2

Please sign in to comment.