Skip to content

Commit

Permalink
Support arbitrary tagging and selection of testcases.
Browse files Browse the repository at this point in the history
A testcase can optionally have a list of tags associated with it.
Srunner can be run with an optional include list of tags and an optional
exclude list of tags. These will have the effect of filtering testcases
that would otherwise be run.
  • Loading branch information
Crispin Dent-Young committed Jun 8, 2016
1 parent 6cadd63 commit 8694d33
Show file tree
Hide file tree
Showing 10 changed files with 841 additions and 3 deletions.
136 changes: 135 additions & 1 deletion src/check.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ static void suite_free(Suite * s)
free(s);
}


TCase *tcase_create(const char *name)
{
char *env;
Expand Down Expand Up @@ -149,10 +150,113 @@ TCase *tcase_create(const char *name)
tc->ch_sflst = check_list_create();
tc->unch_tflst = check_list_create();
tc->ch_tflst = check_list_create();
tc->tags = NULL;
tc->num_tags = 0;

return tc;
}

void tcase_set_tags(TCase * tc, const char *tags_orig)
{
unsigned int count;
char *tags;
char *tag;

/* free any existing tags */
if (NULL != tc->tags)
{
unsigned int i;

for (i = 0; i < tc->num_tags; i++)
{
free(tc->tags[i]);
}
free(tc->tags);
tc->tags = NULL;
}
tc->num_tags = 0;

if (NULL == tags_orig)
{
return;
}

/* first pass to count the number of tags to be added */
tags = strdup(tags_orig);
tag = strtok(tags, " ");
while (tag)
{
if (strlen(tag))
{
count++;
}
tag = strtok(NULL, " ");
}
free(tags);

if (0 == count)
{
return;
}

tc->tags = calloc(count, sizeof(const char *));

/* second pass to copy new tags */
tags = strdup(tags_orig);
tag = strtok(tags, " ");
while (tag)
{
if (strlen(tag))
{
tc->tags[tc->num_tags++] = strdup(tag);
}
tag = strtok(NULL, " ");
}
free(tags);
}

int tcase_get_tags(TCase *tc, char *tags, unsigned int max_sz)
{
unsigned int desired_len = 0;
unsigned int consumed_len = 0;
unsigned int i;

if (NULL != tc->tags)
{
for (i = 0; i < tc->num_tags; i++)
{
consumed_len = (max_sz >= desired_len) ?
desired_len : max_sz;

desired_len += snprintf(tags + consumed_len,
max_sz - consumed_len,
"%s ", tc->tags[i]);
}

}

if (max_sz > 0)
{
if (desired_len > 0)
{
/* if we wrote to tags then remove any trailing space */
consumed_len = (max_sz >= desired_len) ? desired_len : max_sz;
tags[consumed_len - 1] = '\0';
}
else
{
/* otherwise just make sure it is null terminated */
tags[0] = '\0';
}
}

/* desired_len should not include trailing space */
if (desired_len > 0)
{
desired_len--;
}
return desired_len;
}

static void tcase_free(TCase * tc)
{
Expand All @@ -166,10 +270,40 @@ static void tcase_free(TCase * tc)
check_list_free(tc->ch_sflst);
check_list_free(tc->unch_tflst);
check_list_free(tc->ch_tflst);

tcase_set_tags(tc, NULL);
free(tc);
}

unsigned int tcase_matching_tag(TCase *tc, const char *check_for)
{
char *tags;
char *tag;

if ((NULL == tc->tags) || (NULL == check_for))
{
return 0;
}

tags = strdup(check_for);

tag = strtok(tags, " ");
while (NULL != tag)
{
unsigned int i;
for (i = 0; i < tc->num_tags; i++)
{
if (0 == strcmp(tc->tags[i], tag))
{
return 1;
}
}
tag = strtok(NULL, " ");
}
free(tags);

return 0;
}

void suite_add_tcase(Suite * s, TCase * tc)
{
if(s == NULL || tc == NULL)
Expand Down
36 changes: 36 additions & 0 deletions src/check.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,41 @@ CK_DLL_EXP void CK_EXPORT suite_add_tcase(Suite * s, TCase * tc);
* */
CK_DLL_EXP TCase *CK_EXPORT tcase_create(const char *name);

/**
* Associate a test case with certain tags.
* Replaces any existing tags with the new set.
*
* @param tc the test case
*
* @param tags string containing arbitrary tags separated by spaces
* This will be copied. Passing NULL clears all tags.
*
* @since 0.11.0
* */
CK_DLL_EXP void CK_EXPORT tcase_set_tags(TCase * tc,
const char *tags);
/**
* Get tags currently associated with a test case.
*
* @param tc the test case
*
* @param tags pointer to array in which to return space separated tag
* string.
*
* @param max_sz maximum size of tags array including null terminator.
* If max_sz is passed as 0 then nothing will be written to tags and it
* may not be terminated.
*
* @return length it would like to have written excluding the
* terminating null. NOTE: this may be equal or longer to max_sz, in
* which case you know that the returned string truncated. (See
* snprintf).
*
* @since 0.11.0
* */
CK_DLL_EXP int CK_EXPORT tcase_get_tags(TCase * tc,
char *tags,
unsigned int max_sz);
/**
* Add a test function to a test case
*
Expand Down Expand Up @@ -980,6 +1015,7 @@ CK_DLL_EXP void CK_EXPORT srunner_run_all(SRunner * sr,
*/
CK_DLL_EXP void CK_EXPORT srunner_run(SRunner * sr, const char *sname,
const char *tcname,
const char *inc_tags, const char *exc_tags,
enum print_output print_mode);


Expand Down
4 changes: 4 additions & 0 deletions src/check_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ struct TCase
List *unch_tflst;
List *ch_sflst;
List *ch_tflst;
unsigned int num_tags;
char **tags;
};

typedef struct TestStats
Expand Down Expand Up @@ -134,4 +136,6 @@ enum fork_status cur_fork_status(void);

clockid_t check_get_clockid(void);

unsigned int tcase_matching_tag(TCase *tc, const char *check_for);

#endif /* CHECK_IMPL_H */
27 changes: 25 additions & 2 deletions src/check_run.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ static void srunner_run_init(SRunner * sr, enum print_output print_mode);
static void srunner_run_end(SRunner * sr, enum print_output print_mode);
static void srunner_iterate_suites(SRunner * sr,
const char *sname, const char *tcname,
const char *inc_tags, const char *exc_tags,
enum print_output print_mode);
static void srunner_iterate_tcase_tfuns(SRunner * sr, TCase * tc);
static void srunner_add_failure(SRunner * sr, TestResult * tf);
Expand Down Expand Up @@ -160,6 +161,7 @@ static void srunner_run_end(SRunner * sr,

static void srunner_iterate_suites(SRunner * sr,
const char *sname, const char *tcname,
const char *inc_tags, const char *exc_tags,
enum print_output CK_ATTRIBUTE_UNUSED
print_mode)
{
Expand Down Expand Up @@ -191,6 +193,20 @@ static void srunner_iterate_suites(SRunner * sr,
{
continue;
}
if (inc_tags != NULL)
{
if (!tcase_matching_tag(tc, inc_tags))
{
continue;
}
}
if (exc_tags != NULL)
{
if (tcase_matching_tag(tc, exc_tags))
{
continue;
}
}

srunner_run_tcase(sr, tc);
}
Expand Down Expand Up @@ -738,10 +754,13 @@ void srunner_run_all(SRunner * sr, enum print_output print_mode)
{
srunner_run(sr, NULL, /* All test suites. */
NULL, /* All test cases. */
NULL, /* Include all tags */
NULL, /* Exclude no tags */
print_mode);
}

void srunner_run(SRunner * sr, const char *sname, const char *tcname,
const char *inc_tags, const char *exc_tags,
enum print_output print_mode)
{
#if defined(HAVE_SIGACTION) && defined(HAVE_FORK)
Expand All @@ -756,7 +775,11 @@ void srunner_run(SRunner * sr, const char *sname, const char *tcname,
if(!tcname)
tcname = getenv("CK_RUN_CASE");
if(!sname)
sname = getenv("CK_RUN_SUITE");
sname = getenv("CK_RUN_SUITE");
if(!inc_tags)
inc_tags = getenv("CK_INC_TAGS");
if(!exc_tags)
exc_tags = getenv("CK_EXC_TAGS");

if(sr == NULL)
return;
Expand All @@ -779,7 +802,7 @@ void srunner_run(SRunner * sr, const char *sname, const char *tcname,
sigaction(SIGTERM, &sigterm_new_action, &sigterm_old_action);
#endif /* HAVE_SIGACTION && HAVE_FORK */
srunner_run_init(sr, print_mode);
srunner_iterate_suites(sr, sname, tcname, print_mode);
srunner_iterate_suites(sr, sname, tcname, inc_tags, exc_tags, print_mode);
srunner_run_end(sr, print_mode);
#if defined(HAVE_SIGACTION) && defined(HAVE_FORK)
sigaction(SIGALRM, &sigalarm_old_action, NULL);
Expand Down
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ set(CHECK_CHECK_SOURCES
check_check_pack.c
check_check_selective.c
check_check_sub.c
check_check_tags.c
check_list.c)
set(CHECK_CHECK_HEADERS check_check.h)
add_executable(check_check ${CHECK_CHECK_HEADERS} ${CHECK_CHECK_SOURCES})
Expand Down
3 changes: 3 additions & 0 deletions tests/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ check_check_export_SOURCES = \
check_check_master.c \
check_check_log.c \
check_check_fork.c \
check_check_tags.c \
check_check_export_main.c
check_check_export_LDADD = $(top_builddir)/src/libcheck.la $(top_builddir)/lib/libcompat.la

Expand All @@ -58,6 +59,7 @@ check_check_SOURCES = \
check_check_pack.c \
check_check_exit.c \
check_check_selective.c \
check_check_tags.c \
check_check_main.c
check_check_LDADD = $(top_builddir)/src/libcheckinternal.la $(top_builddir)/lib/libcompat.la

Expand All @@ -67,6 +69,7 @@ check_mem_leaks_SOURCES = \
check_check_fork.c \
check_check_exit.c \
check_check_selective.c \
check_check_tags.c \
check_check_sub.c \
check_check_master.c
check_mem_leaks_LDADD = $(top_builddir)/src/libcheck.la $(top_builddir)/lib/libcompat.la
Expand Down
1 change: 1 addition & 0 deletions tests/check_check.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ Suite *make_fixture_suite(void);
Suite *make_pack_suite(void);
Suite *make_exit_suite(void);
Suite *make_selective_suite(void);
Suite *make_tag_suite(void);

extern int master_tests_lineno[];
void init_master_tests_lineno(int num_master_tests);
Expand Down
1 change: 1 addition & 0 deletions tests/check_check_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ int main (void)
srunner_add_suite(sr, make_fork_suite());
srunner_add_suite(sr, make_fixture_suite());
srunner_add_suite(sr, make_pack_suite());
srunner_add_suite(sr, make_tag_suite());

#if defined(HAVE_FORK) && HAVE_FORK==1
srunner_add_suite(sr, make_exit_suite());
Expand Down
Loading

0 comments on commit 8694d33

Please sign in to comment.