1 #include <cgreen/reporter.h>
2 #include <cgreen/messaging.h>
3 #include <cgreen/breadcrumb.h>
4 #include <stdlib.h>
5 #include <stdio.h>
6 #include <stdarg.h>
7
8 enum {pass = 1, fail, completion};
9
10 struct TestContext_ {
11 TestReporter *reporter;
12 };
13 static TestContext context;
14
15 static void show_pass(TestReporter *reporter, const char *file, int line, const char *message, va_list arguments);
16 static void show_fail(TestReporter *reporter, const char *file, int line, const char *message, va_list arguments);
17 static void show_incomplete(TestReporter *reporter, const char *name);
18 static void assert_true(TestReporter *reporter, const char *file, int line, int result, const char *message, ...);
19 static void read_reporter_results(TestReporter *reporter);
20
get_test_reporter()21 TestReporter *get_test_reporter() {
22 return context.reporter;
23 }
24
setup_reporting(TestReporter * reporter)25 void setup_reporting(TestReporter *reporter) {
26 reporter->ipc = start_cgreen_messaging(45);
27 context.reporter = reporter;
28 }
29
create_reporter()30 TestReporter *create_reporter() {
31 TestReporter *reporter = malloc(sizeof(TestReporter));
32 if (reporter == NULL) {
33 return NULL;
34 }
35 CgreenBreadcrumb *breadcrumb = create_breadcrumb();
36 if (breadcrumb == NULL) {
37 destroy_reporter(reporter);
38 return NULL;
39 }
40 reporter->destroy = &destroy_reporter;
41 reporter->start_suite = &reporter_start_suite;
42 reporter->start_test = &reporter_start;
43 reporter->show_pass = &show_pass;
44 reporter->show_fail = &show_fail;
45 reporter->show_incomplete = &show_incomplete;
46 reporter->assert_true = &assert_true;
47 reporter->finish_test = &reporter_finish;
48 reporter->finish_suite = &reporter_finish;
49 reporter->passes = 0;
50 reporter->failures = 0;
51 reporter->exceptions = 0;
52 reporter->breadcrumb = breadcrumb;
53 reporter->memo = NULL;
54 return reporter;
55 }
56
destroy_reporter(TestReporter * reporter)57 void destroy_reporter(TestReporter *reporter) {
58 destroy_breadcrumb((CgreenBreadcrumb *)reporter->breadcrumb);
59 destroy_memo((TestReportMemo *)reporter->memo);
60 free(reporter);
61 context.reporter = NULL;
62 }
63
destroy_memo(TestReportMemo * memo)64 void destroy_memo(TestReportMemo *memo) {
65 if (! memo) {
66 free(memo);
67 memo = NULL;
68 }
69 }
70
reporter_start(TestReporter * reporter,const char * name)71 void reporter_start(TestReporter *reporter, const char *name) {
72 push_breadcrumb(reporter->breadcrumb, name);
73 }
74
reporter_start_suite(TestReporter * reporter,const char * name,const int count)75 void reporter_start_suite(TestReporter *reporter, const char *name, const int count) {
76 (void) count;
77 reporter_start(reporter, name);
78 }
79
reporter_finish(TestReporter * reporter,const char * name)80 void reporter_finish(TestReporter *reporter, const char *name) {
81 read_reporter_results(reporter);
82 pop_breadcrumb((CgreenBreadcrumb *)reporter->breadcrumb);
83 }
84
add_reporter_result(TestReporter * reporter,int result)85 void add_reporter_result(TestReporter *reporter, int result) {
86 send_cgreen_message(reporter->ipc, result ? pass : fail);
87 }
88
send_reporter_completion_notification(TestReporter * reporter)89 void send_reporter_completion_notification(TestReporter *reporter) {
90 send_cgreen_message(reporter->ipc, completion);
91 }
92
show_pass(TestReporter * reporter,const char * file,int line,const char * message,va_list arguments)93 static void show_pass(TestReporter *reporter, const char *file, int line, const char *message, va_list arguments) {
94 }
95
show_fail(TestReporter * reporter,const char * file,int line,const char * message,va_list arguments)96 static void show_fail(TestReporter *reporter, const char *file, int line, const char *message, va_list arguments) {
97 }
98
show_incomplete(TestReporter * reporter,const char * name)99 static void show_incomplete(TestReporter *reporter, const char *name) {
100 }
101
assert_true(TestReporter * reporter,const char * file,int line,int result,const char * message,...)102 static void assert_true(TestReporter *reporter, const char *file, int line, int result, const char *message, ...) {
103 va_list arguments;
104 va_start(arguments, message);
105 if (result) {
106 (*reporter->show_pass)(reporter, file, line, message, arguments);
107 } else {
108 (*reporter->show_fail)(reporter, file, line, message, arguments);
109 }
110 add_reporter_result(reporter, result);
111 va_end(arguments);
112 }
113
read_reporter_results(TestReporter * reporter)114 static void read_reporter_results(TestReporter *reporter) {
115 int completed = 0;
116 int result;
117 while ((result = receive_cgreen_message(reporter->ipc)) > 0) {
118 if (result == pass) {
119 reporter->passes++;
120 } else if (result == fail) {
121 reporter->failures++;
122 } else if (result == completion) {
123 completed = 1;
124 }
125 }
126 if (! completed) {
127 (*reporter->show_incomplete)(reporter, get_current_from_breadcrumb((CgreenBreadcrumb *)reporter->breadcrumb));
128 reporter->exceptions++;
129 }
130 }
131
132 /* vim: set ts=4 sw=4 et cindent: */
133