1 /*
2 * Test result reporting
3 *
4 * Copyright (c) Siemens AG, 2014
5 *
6 * Authors:
7 * Jan Kiszka <jan.kiszka@siemens.com>
8 * Andrew Jones <drjones@redhat.com>
9 *
10 * This work is licensed under the terms of the GNU LGPL, version 2.
11 */
12
13 #include "libcflat.h"
14 #include "asm/spinlock.h"
15
16 static unsigned int tests, failures, xfailures, kfailures, skipped;
17 static char prefixes[256];
18 static struct spinlock lock;
19
20 #define PREFIX_DELIMITER ": "
21
report_passed(void)22 void report_passed(void)
23 {
24 spin_lock(&lock);
25 tests++;
26 spin_unlock(&lock);
27 }
28
report_prefix_pushf(const char * prefix_fmt,...)29 void report_prefix_pushf(const char *prefix_fmt, ...)
30 {
31 va_list va;
32 unsigned int len;
33 int start;
34
35 spin_lock(&lock);
36
37 len = strlen(prefixes);
38 assert_msg(len < sizeof(prefixes), "%d >= %zu", len, sizeof(prefixes));
39 start = len;
40
41 va_start(va, prefix_fmt);
42 len += vsnprintf(&prefixes[len], sizeof(prefixes) - len, prefix_fmt,
43 va);
44 va_end(va);
45 assert_msg(len < sizeof(prefixes), "%d >= %zu", len, sizeof(prefixes));
46
47 assert_msg(!strstr(&prefixes[start], PREFIX_DELIMITER),
48 "Prefix \"%s\" contains delimiter \"" PREFIX_DELIMITER "\"",
49 &prefixes[start]);
50
51 len += snprintf(&prefixes[len], sizeof(prefixes) - len,
52 PREFIX_DELIMITER);
53 assert_msg(len < sizeof(prefixes), "%d >= %zu", len, sizeof(prefixes));
54
55 spin_unlock(&lock);
56 }
57
report_prefix_push(const char * prefix)58 void report_prefix_push(const char *prefix)
59 {
60 report_prefix_pushf("%s", prefix);
61 }
62
__report_prefix_pop(void)63 static void __report_prefix_pop(void)
64 {
65 char *p, *q;
66
67 if (!*prefixes)
68 return;
69
70 for (p = prefixes, q = strstr(p, PREFIX_DELIMITER) + 2;
71 *q;
72 p = q, q = strstr(p, PREFIX_DELIMITER) + 2)
73 ;
74 *p = '\0';
75 }
76
report_prefix_pop(void)77 void report_prefix_pop(void)
78 {
79 spin_lock(&lock);
80 __report_prefix_pop();
81 spin_unlock(&lock);
82 }
83
report_prefix_popn(int n)84 void report_prefix_popn(int n)
85 {
86 spin_lock(&lock);
87 while (n--)
88 __report_prefix_pop();
89 spin_unlock(&lock);
90 }
91
va_report(const char * msg_fmt,bool pass,bool xfail,bool kfail,bool skip,va_list va)92 static bool va_report(const char *msg_fmt,
93 bool pass, bool xfail, bool kfail, bool skip, va_list va)
94 {
95 const char *prefix = skip ? "SKIP"
96 : xfail ? (pass ? "XPASS" : "XFAIL")
97 : kfail ? (pass ? "PASS" : "KFAIL")
98 : (pass ? "PASS" : "FAIL");
99
100 spin_lock(&lock);
101
102 tests++;
103 printf("%s: ", prefix);
104 puts(prefixes);
105 vprintf(msg_fmt, va);
106 puts("\n");
107 if (skip)
108 skipped++;
109 else if (xfail && !pass)
110 xfailures++;
111 else if (kfail && !pass)
112 kfailures++;
113 else if (xfail || !pass)
114 failures++;
115
116 spin_unlock(&lock);
117
118 return pass || xfail;
119 }
120
report(bool pass,const char * msg_fmt,...)121 bool report(bool pass, const char *msg_fmt, ...)
122 {
123 va_list va;
124 bool ret;
125
126 va_start(va, msg_fmt);
127 ret = va_report(msg_fmt, pass, false, false, false, va);
128 va_end(va);
129
130 return ret;
131 }
132
report_pass(const char * msg_fmt,...)133 void report_pass(const char *msg_fmt, ...)
134 {
135 va_list va;
136
137 va_start(va, msg_fmt);
138 va_report(msg_fmt, true, false, false, false, va);
139 va_end(va);
140 }
141
report_fail(const char * msg_fmt,...)142 void report_fail(const char *msg_fmt, ...)
143 {
144 va_list va;
145
146 va_start(va, msg_fmt);
147 va_report(msg_fmt, false, false, false, false, va);
148 va_end(va);
149 }
150
report_xfail(bool xfail,bool pass,const char * msg_fmt,...)151 bool report_xfail(bool xfail, bool pass, const char *msg_fmt, ...)
152 {
153 bool ret;
154
155 va_list va;
156 va_start(va, msg_fmt);
157 ret = va_report(msg_fmt, pass, xfail, false, false, va);
158 va_end(va);
159
160 return ret;
161 }
162
163 /*
164 * kfail is known failure. If kfail is true then test will succeed
165 * regardless of pass.
166 */
report_kfail(bool kfail,bool pass,const char * msg_fmt,...)167 bool report_kfail(bool kfail, bool pass, const char *msg_fmt, ...)
168 {
169 bool ret;
170
171 va_list va;
172 va_start(va, msg_fmt);
173 ret = va_report(msg_fmt, pass, false, kfail, false, va);
174 va_end(va);
175
176 return ret;
177 }
178
report_skip(const char * msg_fmt,...)179 void report_skip(const char *msg_fmt, ...)
180 {
181 va_list va;
182 va_start(va, msg_fmt);
183 va_report(msg_fmt, false, false, false, true, va);
184 va_end(va);
185 }
186
report_info(const char * msg_fmt,...)187 void report_info(const char *msg_fmt, ...)
188 {
189 va_list va;
190
191 spin_lock(&lock);
192 puts("INFO: ");
193 puts(prefixes);
194 va_start(va, msg_fmt);
195 vprintf(msg_fmt, va);
196 va_end(va);
197 puts("\n");
198 spin_unlock(&lock);
199 }
200
report_summary(void)201 int report_summary(void)
202 {
203 int ret;
204 spin_lock(&lock);
205
206 printf("SUMMARY: %d tests", tests);
207 if (failures)
208 printf(", %d unexpected failures", failures);
209 if (kfailures)
210 printf(", %d known failures", kfailures);
211 if (xfailures)
212 printf(", %d expected failures", xfailures);
213 if (skipped)
214 printf(", %d skipped", skipped);
215 printf("\n");
216
217 if (tests == skipped) {
218 spin_unlock(&lock);
219 /* Blame AUTOTOOLS for using 77 for skipped test and QEMU for
220 * mangling error codes in a way that gets 77 if we ... */
221 return 77 >> 1;
222 }
223
224 ret = failures > 0 ? 1 : 0;
225 spin_unlock(&lock);
226 return ret;
227 }
228
report_abort(const char * msg_fmt,...)229 void report_abort(const char *msg_fmt, ...)
230 {
231 va_list va;
232
233 spin_lock(&lock);
234 puts("ABORT: ");
235 puts(prefixes);
236 va_start(va, msg_fmt);
237 vprintf(msg_fmt, va);
238 va_end(va);
239 puts("\n");
240 spin_unlock(&lock);
241 report_summary();
242 abort();
243 }
244