diff options
Diffstat (limited to 'test/framework.c')
-rw-r--r-- | test/framework.c | 289 |
1 files changed, 289 insertions, 0 deletions
diff --git a/test/framework.c b/test/framework.c new file mode 100644 index 0000000..53a8d60 --- /dev/null +++ b/test/framework.c @@ -0,0 +1,289 @@ +/* + * Copyright (C) 2010 Joel Rosdahl + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "ccache.h" +#include "test/framework.h" + +#if defined(HAVE_TERMIOS_H) +#define USE_COLOR +#include <termios.h> +#endif + +static unsigned total_asserts; +static unsigned total_tests; +static unsigned total_suites; +static unsigned failed_tests; +static const char *current_suite; +static const char *current_test; +static char *dir_before_suite; +static char *dir_before_test; +static int verbose; + +static const char COLOR_END[] = "\x1b[m"; +static const char COLOR_GREEN[] = "\x1b[32m"; +static const char COLOR_RED[] = "\x1b[31m"; + +#define COLOR(tty, color) ((tty) ? COLOR_##color : "") + +static int +is_tty(int fd) +{ +#ifdef USE_COLOR + struct termios t; + return tcgetattr(fd, &t) == 0; +#else + (void)fd; + return 0; +#endif +} + +static const char * +plural_s(unsigned n) +{ + return n == 1 ? "" : "s"; +} + +int +cct_run(suite_fn *suites, int verbose_output) +{ + suite_fn *suite; + int tty = is_tty(1); + + verbose = verbose_output; + + for (suite = suites; *suite; suite++) { + unsigned test_index = 0; + while (1) { + test_index = (*suite)(test_index + 1); + if (test_index == 0) { + /* We have reached the end of the suite. */ + break; + } + } + } + + if (failed_tests == 0) { + printf("%sPASSED%s: %u assertion%s, %u test%s, %u suite%s\n", + COLOR(tty, GREEN), COLOR(tty, END), + total_asserts, plural_s(total_asserts), + total_tests, plural_s(total_tests), + total_suites, plural_s(total_suites)); + } else { + printf("%sFAILED%s: %u test%s\n", + COLOR(tty, RED), COLOR(tty, END), + failed_tests, plural_s(failed_tests)); + } + return failed_tests > 0 ? 1 : 0; +} + +void +cct_suite_begin(const char *name) +{ + ++total_suites; + if (verbose) { + printf("=== SUITE: %s ===\n", name); + } + dir_before_suite = gnu_getcwd(); + create_dir(name); + cct_chdir(name); + current_suite = name; +} + +void +cct_suite_end() +{ + cct_chdir(dir_before_suite); + free(dir_before_suite); + dir_before_suite = NULL; +} + +void +cct_test_begin(const char *name) +{ + extern char *cache_logfile; + + ++total_tests; + if (verbose) { + printf("--- TEST: %s ---\n", name); + } + dir_before_test = gnu_getcwd(); + create_dir(name); + cct_chdir(name); + current_test = name; + + cc_reset(); + cache_logfile = getenv("CCACHE_LOGFILE"); +} + +void +cct_test_end() +{ + if (dir_before_test) { + cct_chdir(dir_before_test); + free(dir_before_test); + dir_before_test = NULL; + } +} + +void +cct_check_passed(const char *file, int line, const char *what) +{ + ++total_asserts; + if (verbose) { + printf("%s:%d: Passed assertion: %s\n", file, line, what); + } +} + +void +cct_check_failed(const char *file, int line, const char *what, + const char *expected, const char *actual) +{ + ++total_asserts; + ++failed_tests; + fprintf(stderr, "%s:%d: Failed assertion:\n", file, line); + fprintf(stderr, " Suite: %s\n", current_suite); + fprintf(stderr, " Test: %s\n", current_test); + if (expected && actual) { + fprintf(stderr, " Expression: %s\n", what); + fprintf(stderr, " Expected: %s\n", expected); + fprintf(stderr, " Actual: %s\n", actual); + } else { + fprintf(stderr, " Assertion: %s\n", what); + } + fprintf(stderr, "\n"); +} + +int +cct_check_int_eq(const char *file, int line, const char *expression, + int expected, int actual) +{ + if (expected == actual) { + cct_check_passed(file, line, expression); + return 1; + } else { + char *exp_str = format("%i", expected); + char *act_str = format("%i", actual); + cct_check_failed(file, line, expression, exp_str, act_str); + free(exp_str); + free(act_str); + return 0; + } +} + +int +cct_check_uns_eq(const char *file, int line, const char *expression, + unsigned expected, unsigned actual) +{ + if (expected == actual) { + cct_check_passed(file, line, expression); + return 1; + } else { + char *exp_str = format("%i", expected); + char *act_str = format("%i", actual); + cct_check_failed(file, line, expression, exp_str, act_str); + free(exp_str); + free(act_str); + return 0; + } +} + +int +cct_check_str_eq(const char *file, int line, const char *expression, + const char *expected, const char *actual, int free1, + int free2) +{ + int result; + + if (expected && actual && str_eq(actual, expected)) { + cct_check_passed(file, line, expression); + result = 1; + } else { + char *exp_str = expected ? format("\"%s\"", expected) : x_strdup("(null)"); + char *act_str = actual ? format("\"%s\"", actual) : x_strdup("(null)"); + cct_check_failed(file, line, expression, exp_str, act_str); + free(exp_str); + free(act_str); + result = 0; + } + + if (free1) { + free((char *)expected); + } + if (free2) { + free((char *)actual); + } + return result; +} + +int +cct_check_args_eq(const char *file, int line, const char *expression, + struct args *expected, struct args *actual, + int free1, int free2) +{ + int result; + + if (expected && actual && args_equal(actual, expected)) { + cct_check_passed(file, line, expression); + result = 1; + } else { + char *exp_str = expected ? args_to_string(expected) : x_strdup("(null)"); + char *act_str = actual ? args_to_string(actual) : x_strdup("(null)"); + cct_check_failed(file, line, expression, exp_str, act_str); + free(exp_str); + free(act_str); + result = 0; + } + + if (free1) { + args_free(expected); + } + if (free2) { + args_free(actual); + } + return result; +} + +void +cct_chdir(const char *path) +{ + if (chdir(path) != 0) { + fprintf(stderr, "chdir: %s: %s", path, strerror(errno)); + abort(); + } +} + +void +cct_wipe(const char *path) +{ + /* TODO: rewrite using traverse(). */ + char *command = format("rm -rf %s", path); + if (system(command) != 0) { + perror(command); + } + free(command); +} + +void +cct_create_fresh_dir(const char *path) +{ + cct_wipe(path); + if (mkdir(path, 0777) != 0) { + fprintf(stderr, "mkdir: %s: %s", path, strerror(errno));; + abort(); + } +} |