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