summaryrefslogtreecommitdiff
path: root/test/framework.c
diff options
context:
space:
mode:
Diffstat (limited to 'test/framework.c')
-rw-r--r--test/framework.c289
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();
+ }
+}