diff options
Diffstat (limited to 'tests/clar')
-rw-r--r-- | tests/clar/clar.c | 70 | ||||
-rw-r--r-- | tests/clar/clar.h | 6 | ||||
-rw-r--r-- | tests/clar/clar/print.h | 41 | ||||
-rw-r--r-- | tests/clar/clar/summary.h | 29 | ||||
-rw-r--r-- | tests/clar/clar_libgit2.c | 108 | ||||
-rw-r--r-- | tests/clar/clar_libgit2.h | 24 | ||||
-rw-r--r-- | tests/clar/main.c | 1 |
7 files changed, 223 insertions, 56 deletions
diff --git a/tests/clar/clar.c b/tests/clar/clar.c index ca508d073..c9c3fde38 100644 --- a/tests/clar/clar.c +++ b/tests/clar/clar.c @@ -12,6 +12,7 @@ #include <math.h> #include <stdarg.h> #include <wchar.h> +#include <time.h> /* required for sandboxing */ #include <sys/types.h> @@ -86,6 +87,8 @@ typedef struct stat STAT_T; #endif +#define MAX(x, y) (((x) > (y)) ? (x) : (y)) + #include "clar.h" static void fs_rm(const char *_source); @@ -117,6 +120,8 @@ struct clar_report { const char *suite; enum cl_test_status status; + time_t start; + double elapsed; struct clar_error *errors; struct clar_error *last_error; @@ -145,7 +150,7 @@ static struct { int report_errors_only; int exit_on_error; - int report_suite_names; + int verbosity; int write_summary; char *summary_filename; @@ -186,7 +191,7 @@ struct clar_suite { static void clar_print_init(int test_count, int suite_count, const char *suite_names); static void clar_print_shutdown(int test_count, int suite_count, int error_count); static void clar_print_error(int num, const struct clar_report *report, const struct clar_error *error); -static void clar_print_ontest(const char *test_name, int test_number, enum cl_test_status failed); +static void clar_print_ontest(const char *suite_name, const char *test_name, int test_number, enum cl_test_status failed); static void clar_print_onsuite(const char *suite_name, int suite_index); static void clar_print_onabort(const char *msg, ...); @@ -245,16 +250,53 @@ clar_report_all(void) } } +#ifdef WIN32 +# define clar_time DWORD + +static void clar_time_now(clar_time *out) +{ + *out = GetTickCount(); +} + +static double clar_time_diff(clar_time *start, clar_time *end) +{ + return ((double)*end - (double)*start) / 1000; +} +#else +# include <sys/time.h> + +# define clar_time struct timeval + +static void clar_time_now(clar_time *out) +{ + struct timezone tz; + + gettimeofday(out, &tz); +} + +static double clar_time_diff(clar_time *start, clar_time *end) +{ + return ((double)end->tv_sec + (double)end->tv_usec / 1.0E6) - + ((double)start->tv_sec + (double)start->tv_usec / 1.0E6); +} +#endif + static void clar_run_test( + const struct clar_suite *suite, const struct clar_func *test, const struct clar_func *initialize, const struct clar_func *cleanup) { + clar_time start, end; + _clar.trampoline_enabled = 1; CL_TRACE(CL_TRACE__TEST__BEGIN); + _clar.last_report->start = time(NULL); + clar_time_now(&start); + if (setjmp(_clar.trampoline) == 0) { if (initialize->ptr != NULL) initialize->ptr(); @@ -264,11 +306,15 @@ clar_run_test( CL_TRACE(CL_TRACE__TEST__RUN_END); } + clar_time_now(&end); + _clar.trampoline_enabled = 0; if (_clar.last_report->status == CL_TEST_NOTRUN) _clar.last_report->status = CL_TEST_OK; + _clar.last_report->elapsed = clar_time_diff(&start, &end); + if (_clar.local_cleanup != NULL) _clar.local_cleanup(_clar.local_cleanup_payload); @@ -286,7 +332,7 @@ clar_run_test( if (_clar.report_errors_only) { clar_report_errors(_clar.last_report); } else { - clar_print_ontest(test->name, _clar.tests_ran, _clar.last_report->status); + clar_print_ontest(suite->name, test->name, _clar.tests_ran, _clar.last_report->status); } } @@ -352,7 +398,7 @@ clar_run_suite(const struct clar_suite *suite, const char *filter) _clar.last_report = report; - clar_run_test(&test[i], &suite->initialize, &suite->cleanup); + clar_run_test(suite, &test[i], &suite->initialize, &suite->cleanup); if (_clar.exit_on_error && _clar.total_errors) return; @@ -427,7 +473,7 @@ clar_parse_args(int argc, char **argv) ++found; if (!exact) - _clar.report_suite_names = 1; + _clar.verbosity = MAX(_clar.verbosity, 1); switch (action) { case 's': { @@ -486,13 +532,13 @@ clar_parse_args(int argc, char **argv) } case 'v': - _clar.report_suite_names = 1; + _clar.verbosity++; break; case 'r': _clar.write_summary = 1; free(_clar.summary_filename); - _clar.summary_filename = strdup(*(argument + 2) ? (argument + 2) : "summary.xml"); + _clar.summary_filename = *(argument + 2) ? strdup(argument + 2) : NULL; break; default: @@ -504,6 +550,8 @@ clar_parse_args(int argc, char **argv) void clar_test_init(int argc, char **argv) { + const char *summary_env; + if (argc > 1) clar_parse_args(argc, argv); @@ -513,11 +561,15 @@ clar_test_init(int argc, char **argv) "" ); - if ((_clar.summary_filename = getenv("CLAR_SUMMARY")) != NULL) { + if (!_clar.summary_filename && + (summary_env = getenv("CLAR_SUMMARY")) != NULL) { _clar.write_summary = 1; - _clar.summary_filename = strdup(_clar.summary_filename); + _clar.summary_filename = strdup(summary_env); } + if (_clar.write_summary && !_clar.summary_filename) + _clar.summary_filename = strdup("summary.xml"); + if (_clar.write_summary && !(_clar.summary = clar_summary_init(_clar.summary_filename))) { clar_print_onabort("Failed to open the summary file\n"); diff --git a/tests/clar/clar.h b/tests/clar/clar.h index 3f659c2f6..8c22382bd 100644 --- a/tests/clar/clar.h +++ b/tests/clar/clar.h @@ -13,12 +13,12 @@ enum cl_test_status { CL_TEST_OK, CL_TEST_FAILURE, CL_TEST_SKIP, - CL_TEST_NOTRUN + CL_TEST_NOTRUN, }; enum cl_output_format { CL_OUTPUT_CLAP, - CL_OUTPUT_TAP + CL_OUTPUT_TAP, }; /** Setup clar environment */ @@ -60,7 +60,7 @@ typedef enum cl_trace_event { CL_TRACE__TEST__END, CL_TRACE__TEST__RUN_BEGIN, CL_TRACE__TEST__RUN_END, - CL_TRACE__TEST__LONGJMP + CL_TRACE__TEST__LONGJMP, } cl_trace_event; typedef void (cl_trace_cb)( diff --git a/tests/clar/clar/print.h b/tests/clar/clar/print.h index dbfd27655..c17e2f693 100644 --- a/tests/clar/clar/print.h +++ b/tests/clar/clar/print.h @@ -36,24 +36,35 @@ static void clar_print_clap_error(int num, const struct clar_report *report, con fflush(stdout); } -static void clar_print_clap_ontest(const char *test_name, int test_number, enum cl_test_status status) +static void clar_print_clap_ontest(const char *suite_name, const char *test_name, int test_number, enum cl_test_status status) { (void)test_name; (void)test_number; - switch(status) { - case CL_TEST_OK: printf("."); break; - case CL_TEST_FAILURE: printf("F"); break; - case CL_TEST_SKIP: printf("S"); break; - case CL_TEST_NOTRUN: printf("N"); break; + if (_clar.verbosity > 1) { + printf("%s::%s: ", suite_name, test_name); + + switch (status) { + case CL_TEST_OK: printf("ok\n"); break; + case CL_TEST_FAILURE: printf("fail\n"); break; + case CL_TEST_SKIP: printf("skipped"); break; + case CL_TEST_NOTRUN: printf("notrun"); break; + } + } else { + switch (status) { + case CL_TEST_OK: printf("."); break; + case CL_TEST_FAILURE: printf("F"); break; + case CL_TEST_SKIP: printf("S"); break; + case CL_TEST_NOTRUN: printf("N"); break; + } + + fflush(stdout); } - - fflush(stdout); } static void clar_print_clap_onsuite(const char *suite_name, int suite_index) { - if (_clar.report_suite_names) + if (_clar.verbosity == 1) printf("\n%s", suite_name); (void)suite_index; @@ -102,7 +113,7 @@ static void print_escaped(const char *str) printf("%s", str); } -static void clar_print_tap_ontest(const char *test_name, int test_number, enum cl_test_status status) +static void clar_print_tap_ontest(const char *suite_name, const char *test_name, int test_number, enum cl_test_status status) { const struct clar_error *error = _clar.last_report->errors; @@ -111,10 +122,10 @@ static void clar_print_tap_ontest(const char *test_name, int test_number, enum c switch(status) { case CL_TEST_OK: - printf("ok %d - %s::%s\n", test_number, _clar.active_suite, test_name); + printf("ok %d - %s::%s\n", test_number, suite_name, test_name); break; case CL_TEST_FAILURE: - printf("not ok %d - %s::%s\n", test_number, _clar.active_suite, test_name); + printf("not ok %d - %s::%s\n", test_number, suite_name, test_name); printf(" ---\n"); printf(" reason: |\n"); @@ -132,7 +143,7 @@ static void clar_print_tap_ontest(const char *test_name, int test_number, enum c break; case CL_TEST_SKIP: case CL_TEST_NOTRUN: - printf("ok %d - # SKIP %s::%s\n", test_number, _clar.active_suite, test_name); + printf("ok %d - # SKIP %s::%s\n", test_number, suite_name, test_name); break; } @@ -181,9 +192,9 @@ static void clar_print_error(int num, const struct clar_report *report, const st PRINT(error, num, report, error); } -static void clar_print_ontest(const char *test_name, int test_number, enum cl_test_status status) +static void clar_print_ontest(const char *suite_name, const char *test_name, int test_number, enum cl_test_status status) { - PRINT(ontest, test_name, test_number, status); + PRINT(ontest, suite_name, test_name, test_number, status); } static void clar_print_onsuite(const char *suite_name, int suite_index) diff --git a/tests/clar/clar/summary.h b/tests/clar/clar/summary.h index 6279f5057..4dd352e28 100644 --- a/tests/clar/clar/summary.h +++ b/tests/clar/clar/summary.h @@ -20,8 +20,8 @@ static int clar_summary_testsuites(struct clar_summary *summary) } static int clar_summary_testsuite(struct clar_summary *summary, - int idn, const char *name, const char *pkg, time_t timestamp, - double elapsed, int test_count, int fail_count, int error_count) + int idn, const char *name, time_t timestamp, + int test_count, int fail_count, int error_count) { struct tm *tm = localtime(×tamp); char iso_dt[20]; @@ -29,17 +29,15 @@ static int clar_summary_testsuite(struct clar_summary *summary, if (strftime(iso_dt, sizeof(iso_dt), "%Y-%m-%dT%H:%M:%S", tm) == 0) return -1; - return fprintf(summary->fp, "\t<testsuite " + return fprintf(summary->fp, "\t<testsuite" " id=\"%d\"" " name=\"%s\"" - " package=\"%s\"" " hostname=\"localhost\"" " timestamp=\"%s\"" - " time=\"%.2f\"" " tests=\"%d\"" " failures=\"%d\"" " errors=\"%d\">\n", - idn, name, pkg, iso_dt, elapsed, test_count, fail_count, error_count); + idn, name, iso_dt, test_count, fail_count, error_count); } static int clar_summary_testcase(struct clar_summary *summary, @@ -58,15 +56,23 @@ static int clar_summary_failure(struct clar_summary *summary, type, message, desc); } +static int clar_summary_skipped(struct clar_summary *summary) +{ + return fprintf(summary->fp, "\t\t\t<skipped />\n"); +} + struct clar_summary *clar_summary_init(const char *filename) { struct clar_summary *summary; FILE *fp; - if ((fp = fopen(filename, "w")) == NULL) + if ((fp = fopen(filename, "w")) == NULL) { + perror("fopen"); return NULL; + } if ((summary = malloc(sizeof(struct clar_summary))) == NULL) { + perror("malloc"); fclose(fp); return NULL; } @@ -90,14 +96,14 @@ int clar_summary_shutdown(struct clar_summary *summary) struct clar_error *error = report->errors; if (last_suite == NULL || strcmp(last_suite, report->suite) != 0) { - if (clar_summary_testsuite(summary, 0, report->suite, "", - time(NULL), 0, _clar.tests_ran, _clar.total_errors, 0) < 0) + if (clar_summary_testsuite(summary, 0, report->suite, + report->start, _clar.tests_ran, _clar.total_errors, 0) < 0) goto on_error; } last_suite = report->suite; - clar_summary_testcase(summary, report->test, "what", 0); + clar_summary_testcase(summary, report->test, report->suite, report->elapsed); while (error != NULL) { if (clar_summary_failure(summary, "assert", @@ -107,6 +113,9 @@ int clar_summary_shutdown(struct clar_summary *summary) error = error->next; } + if (report->status == CL_TEST_SKIP) + clar_summary_skipped(summary); + if (clar_summary_close_tag(summary, "testcase", 2) < 0) goto on_error; diff --git a/tests/clar/clar_libgit2.c b/tests/clar/clar_libgit2.c index 783b457f9..54122997d 100644 --- a/tests/clar/clar_libgit2.c +++ b/tests/clar/clar_libgit2.c @@ -1,6 +1,7 @@ #include "clar_libgit2.h" #include "posix.h" #include "fs_path.h" +#include "futils.h" #include "git2/sys/repository.h" void cl_git_report_failure( @@ -476,6 +477,25 @@ int cl_repo_get_bool(git_repository *repo, const char *cfg) return val; } +void cl_repo_set_int(git_repository *repo, const char *cfg, int value) +{ + git_config *config; + cl_git_pass(git_repository_config(&config, repo)); + cl_git_pass(git_config_set_int32(config, cfg, value)); + git_config_free(config); +} + +int cl_repo_get_int(git_repository *repo, const char *cfg) +{ + int val = 0; + git_config *config; + cl_git_pass(git_repository_config(&config, repo)); + if (git_config_get_int32(&val, config, cfg) < 0) + git_error_clear(); + git_config_free(config); + return val; +} + void cl_repo_set_string(git_repository *repo, const char *cfg, const char *value) { git_config *config; @@ -548,33 +568,95 @@ void clar__assert_equal_file( (size_t)expected_bytes, (size_t)total_bytes); } -static git_buf _cl_restore_home = GIT_BUF_INIT; +#define FAKE_HOMEDIR_NAME "cl_fake_home" -void cl_fake_home_cleanup(void *payload) +static git_buf _cl_restore_homedir = GIT_BUF_INIT; + +void cl_fake_homedir_cleanup(void *payload) { GIT_UNUSED(payload); - if (_cl_restore_home.ptr) { - cl_git_pass(git_libgit2_opts( - GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, _cl_restore_home.ptr)); - git_buf_dispose(&_cl_restore_home); + if (_cl_restore_homedir.ptr) { + cl_git_pass(git_futils_rmdir_r(FAKE_HOMEDIR_NAME, NULL, GIT_RMDIR_REMOVE_FILES)); + + cl_git_pass(git_libgit2_opts(GIT_OPT_SET_HOMEDIR, _cl_restore_homedir.ptr)); + git_buf_dispose(&_cl_restore_homedir); } } -void cl_fake_home(void) +void cl_fake_homedir(git_str *out) { git_str path = GIT_STR_INIT; cl_git_pass(git_libgit2_opts( - GIT_OPT_GET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, &_cl_restore_home)); + GIT_OPT_GET_HOMEDIR, &_cl_restore_homedir)); - cl_set_cleanup(cl_fake_home_cleanup, NULL); + cl_set_cleanup(cl_fake_homedir_cleanup, NULL); + + /* TOC/TOU but merely attempts to prevent accidental cleanup. */ + cl_assert(!git_fs_path_exists(FAKE_HOMEDIR_NAME)); + cl_must_pass(p_mkdir(FAKE_HOMEDIR_NAME, 0777)); + cl_git_pass(git_fs_path_prettify(&path, FAKE_HOMEDIR_NAME, NULL)); + cl_git_pass(git_libgit2_opts(GIT_OPT_SET_HOMEDIR, path.ptr)); + + if (out) + git_str_swap(out, &path); + + git_str_dispose(&path); +} + +#define FAKE_GLOBALCONFIG_NAME "cl_fake_global" + +static git_buf _cl_restore_globalconfig = GIT_BUF_INIT; + +void cl_fake_globalconfig_cleanup(void *payload) +{ + GIT_UNUSED(payload); + + if (_cl_restore_globalconfig.ptr) { + cl_git_pass(git_futils_rmdir_r(FAKE_GLOBALCONFIG_NAME, NULL, GIT_RMDIR_REMOVE_FILES)); + + cl_git_pass(git_libgit2_opts(GIT_OPT_SET_HOMEDIR, _cl_restore_globalconfig.ptr)); + git_buf_dispose(&_cl_restore_globalconfig); + } +} + +void cl_fake_globalconfig(git_str *out) +{ + git_str path = GIT_STR_INIT; - if (!git_fs_path_exists("home")) - cl_must_pass(p_mkdir("home", 0777)); - cl_git_pass(git_fs_path_prettify(&path, "home", NULL)); cl_git_pass(git_libgit2_opts( - GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, path.ptr)); + GIT_OPT_GET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, &_cl_restore_globalconfig)); + + cl_set_cleanup(cl_fake_globalconfig_cleanup, NULL); + + /* TOC/TOU but merely attempts to prevent accidental cleanup. */ + cl_assert(!git_fs_path_exists(FAKE_GLOBALCONFIG_NAME)); + cl_must_pass(p_mkdir(FAKE_GLOBALCONFIG_NAME, 0777)); + cl_git_pass(git_fs_path_prettify(&path, FAKE_GLOBALCONFIG_NAME, NULL)); + cl_git_pass(git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, path.ptr)); + + if (out) + git_str_swap(out, &path); + + git_str_dispose(&path); +} + +void cl_sandbox_set_homedir(const char *home) +{ + git_str path = GIT_STR_INIT; + + if (home) { + git_libgit2_opts(GIT_OPT_SET_HOMEDIR, home); + } else { + git_str_joinpath(&path, clar_sandbox_path(), "__home"); + + if (!git_fs_path_exists(path.ptr)) + cl_must_pass(p_mkdir(path.ptr, 0777)); + + git_libgit2_opts(GIT_OPT_SET_HOMEDIR, path.ptr); + } + git_str_dispose(&path); } diff --git a/tests/clar/clar_libgit2.h b/tests/clar/clar_libgit2.h index d2d9da0aa..c33b5d28b 100644 --- a/tests/clar/clar_libgit2.h +++ b/tests/clar/clar_libgit2.h @@ -231,16 +231,28 @@ void cl_repo_commit_from_index( void cl_repo_set_bool(git_repository *repo, const char *cfg, int value); int cl_repo_get_bool(git_repository *repo, const char *cfg); +void cl_repo_set_int(git_repository *repo, const char *cfg, int value); +int cl_repo_get_int(git_repository *repo, const char *cfg); + void cl_repo_set_string(git_repository *repo, const char *cfg, const char *value); -/* set up a fake "home" directory and set libgit2 GLOBAL search path. - * - * automatically configures cleanup function to restore the regular search - * path, although you can call it explicitly if you wish (with NULL). +/* + * set up a fake "home" directory -- automatically configures cleanup + * function to restore the home directory, although you can call it + * explicitly if you wish (with NULL). + */ +void cl_fake_homedir(git_str *); +void cl_fake_homedir_cleanup(void *); + +/* + * set up a fake global configuration directory -- automatically + * configures cleanup function to restore the global config + * although you can call it explicitly if you wish (with NULL). */ -void cl_fake_home(void); -void cl_fake_home_cleanup(void *); +void cl_fake_globalconfig(git_str *); +void cl_fake_globalconfig_cleanup(void *); +void cl_sandbox_set_homedir(const char *); void cl_sandbox_set_search_path_defaults(void); void cl_sandbox_disable_ownership_validation(void); diff --git a/tests/clar/main.c b/tests/clar/main.c index d879073a8..e3f4fe740 100644 --- a/tests/clar/main.c +++ b/tests/clar/main.c @@ -25,6 +25,7 @@ int main(int argc, char *argv[]) } cl_global_trace_register(); + cl_sandbox_set_homedir(getenv("CLAR_HOMEDIR")); cl_sandbox_set_search_path_defaults(); cl_sandbox_disable_ownership_validation(); |