0001 #include <cgreen/text_reporter.h>
0002 #include <cgreen/reporter.h>
0003 #include <cgreen/breadcrumb.h>
0004 #include <stdlib.h>
0005 #include <stdio.h>
0006 #ifndef __cplusplus
0007 #include <stdbool.h>
0008 #endif
0009
0010 #define GREEN "\x1b[32m"
0011 #define RED "\x1b[31m"
0012 #define MAGENTA "\x1b[35m"
0013 #define RESET "\x1b[0m"
0014
0015
0016 #ifdef __cplusplus
0017 namespace cgreen {
0018 #endif
0019
0020 static void text_reporter_start_suite(TestReporter *reporter, const char *name,
0021 const int number_of_tests);
0022 static void text_reporter_start_test(TestReporter *reporter, const char *name);
0023 static void text_reporter_finish(TestReporter *reporter, const char *filename,
0024 int line, const char *message);
0025 static void show_fail(TestReporter *reporter, const char *file, int line,
0026 const char *message, va_list arguments);
0027 static void show_incomplete(TestReporter *reporter, const char *file, int line,
0028 const char *message, va_list arguments);
0029 static void show_breadcrumb(const char *name, void *memo);
0030 static void text_reporter_finish_suite(TestReporter *reporter, const char *file, int line);
0031
0032 TestReporter *create_text_reporter(void) {
0033 TestReporter *reporter = create_reporter();
0034 if (reporter == NULL) {
0035 return NULL;
0036 }
0037 reporter->start_suite = &text_reporter_start_suite;
0038 reporter->start_test = &text_reporter_start_test;
0039 reporter->show_fail = &show_fail;
0040 reporter->show_incomplete = &show_incomplete;
0041 reporter->finish_test = &text_reporter_finish;
0042 reporter->finish_suite = &text_reporter_finish_suite;
0043 return reporter;
0044 }
0045
0046 static void text_reporter_start_suite(TestReporter *reporter, const char *name,
0047 const int number_of_tests) {
0048 reporter_start(reporter, name);
0049 if (get_breadcrumb_depth((CgreenBreadcrumb *) reporter->breadcrumb) == 1) {
0050 printf("Running \"%s\" (%d tests)...\n",
0051 get_current_from_breadcrumb(
0052 (CgreenBreadcrumb *) reporter->breadcrumb),
0053 number_of_tests);
0054 fflush(stdout);
0055 }
0056 }
0057
0058 static void text_reporter_start_test(TestReporter *reporter, const char *name) {
0059 reporter_start(reporter, name);
0060 }
0061
0062 static void text_reporter_finish(TestReporter *reporter, const char *filename,
0063 int line, const char *message) {
0064 reporter_finish(reporter, filename, line, message);
0065 }
0066
0067 static void text_reporter_finish_suite(TestReporter *reporter, const char *file, int line) {
0068 const char *name = get_current_from_breadcrumb((CgreenBreadcrumb *) reporter->breadcrumb);
0069
0070 reporter_finish_suite(reporter, file, line);
0071
0072 if (reporter->options && ((TextReporterOptions *)reporter->options)->use_colours)
0073 printf("Completed \"%s\": %s%d pass%s%s, %s%d failure%s%s, %s%d exception%s%s.\n",
0074 name,
0075 (reporter->passes > 0) ? GREEN : "", reporter->passes, reporter->passes == 1 ? "" : "es", RESET,
0076 (reporter->failures > 0) ? RED : "", reporter->failures, reporter->failures == 1 ? "" : "s", RESET,
0077 (reporter->exceptions > 0) ? MAGENTA : "", reporter->exceptions, reporter->exceptions == 1 ? "" : "s", RESET);
0078 else
0079 printf("Completed \"%s\": %d pass%s, %d failure%s, %d exception%s.\n",
0080 name, reporter->passes, reporter->passes == 1 ? "" : "es",
0081 reporter->failures, reporter->failures == 1 ? "" : "s",
0082 reporter->exceptions, reporter->exceptions == 1 ? "" : "s");
0083 }
0084
0085 static void show_fail(TestReporter *reporter, const char *file, int line,
0086 const char *message, va_list arguments) {
0087 int i = 0;
0088 printf("%s:%d: ", file, line);
0089 printf("Failure: ");
0090 walk_breadcrumb((CgreenBreadcrumb *) reporter->breadcrumb, &show_breadcrumb,
0091 (void *) &i);
0092 printf("\n\t");
0093 vprintf((message == NULL ? "<NULL for failure message>" : message), arguments);
0094 printf("\n");
0095 printf("\n");
0096 fflush(NULL);
0097 }
0098
0099 static void show_incomplete(TestReporter *reporter, const char *file, int line,
0100 const char *message, va_list arguments) {
0101 int i = 0;
0102 printf("%s:%d: ", file, line);
0103 printf("Exception: ");
0104 walk_breadcrumb((CgreenBreadcrumb *) reporter->breadcrumb, &show_breadcrumb,
0105 (void *) &i);
0106
0107 printf("\n\t");
0108 vprintf(message ? message: "Test terminated unexpectedly, likely from a non-standard exception or Posix signal", arguments);
0109 printf("\n");
0110 printf("\n");
0111 fflush(NULL);
0112 }
0113
0114 static void show_breadcrumb(const char *name, void *memo) {
0115 if (*(int *) memo > 1) {
0116 printf("-> ");
0117 }
0118 if (*(int *) memo > 0) {
0119 printf("%s ", name);
0120 }
0121 (*(int *) memo)++;
0122 }
0123
0124 #ifdef __cplusplus
0125 }
0126 #endif
0127
0128
0129
0130
0131