xref: /kvm-unit-tests/lib/report.c (revision 2c96b77ec9d3b1fcec7525174e23a6240ee05949)
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, skipped;
17 static char prefixes[256];
18 static struct spinlock lock;
19 
20 #define PREFIX_DELIMITER ": "
21 
22 void report_passed(void)
23 {
24 	spin_lock(&lock);
25 	tests++;
26 	spin_unlock(&lock);
27 }
28 
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 
58 void report_prefix_push(const char *prefix)
59 {
60 	report_prefix_pushf("%s", prefix);
61 }
62 
63 void report_prefix_pop(void)
64 {
65 	char *p, *q;
66 
67 	spin_lock(&lock);
68 
69 	if (!*prefixes) {
70 		spin_unlock(&lock);
71 		return;
72 	}
73 
74 	for (p = prefixes, q = strstr(p, PREFIX_DELIMITER) + 2;
75 			*q;
76 			p = q, q = strstr(p, PREFIX_DELIMITER) + 2)
77 		;
78 	*p = '\0';
79 
80 	spin_unlock(&lock);
81 }
82 
83 static void va_report(const char *msg_fmt,
84 		bool pass, bool xfail, bool skip, va_list va)
85 {
86 	const char *prefix = skip ? "SKIP"
87 				  : xfail ? (pass ? "XPASS" : "XFAIL")
88 					  : (pass ? "PASS"  : "FAIL");
89 
90 	spin_lock(&lock);
91 
92 	tests++;
93 	printf("%s: ", prefix);
94 	puts(prefixes);
95 	vprintf(msg_fmt, va);
96 	puts("\n");
97 	if (skip)
98 		skipped++;
99 	else if (xfail && !pass)
100 		xfailures++;
101 	else if (xfail || !pass)
102 		failures++;
103 
104 	spin_unlock(&lock);
105 }
106 
107 void report(bool pass, const char *msg_fmt, ...)
108 {
109 	va_list va;
110 	va_start(va, msg_fmt);
111 	va_report(msg_fmt, pass, false, false, va);
112 	va_end(va);
113 }
114 
115 void report_pass(const char *msg_fmt, ...)
116 {
117 	va_list va;
118 
119 	va_start(va, msg_fmt);
120 	va_report(msg_fmt, true, false, false, va);
121 	va_end(va);
122 }
123 
124 void report_fail(const char *msg_fmt, ...)
125 {
126 	va_list va;
127 
128 	va_start(va, msg_fmt);
129 	va_report(msg_fmt, false, false, false, va);
130 	va_end(va);
131 }
132 
133 void report_xfail(bool xfail, bool pass, const char *msg_fmt, ...)
134 {
135 	va_list va;
136 	va_start(va, msg_fmt);
137 	va_report(msg_fmt, pass, xfail, false, va);
138 	va_end(va);
139 }
140 
141 void report_skip(const char *msg_fmt, ...)
142 {
143 	va_list va;
144 	va_start(va, msg_fmt);
145 	va_report(msg_fmt, false, false, true, va);
146 	va_end(va);
147 }
148 
149 void report_info(const char *msg_fmt, ...)
150 {
151 	va_list va;
152 
153 	spin_lock(&lock);
154 	puts("INFO: ");
155 	puts(prefixes);
156 	va_start(va, msg_fmt);
157 	vprintf(msg_fmt, va);
158 	va_end(va);
159 	puts("\n");
160 	spin_unlock(&lock);
161 }
162 
163 int report_summary(void)
164 {
165 	int ret;
166 	spin_lock(&lock);
167 
168 	printf("SUMMARY: %d tests", tests);
169 	if (failures)
170 		printf(", %d unexpected failures", failures);
171 	if (xfailures)
172 		printf(", %d expected failures", xfailures);
173 	if (skipped)
174 		printf(", %d skipped", skipped);
175 	printf("\n");
176 
177 	if (tests == skipped) {
178 		spin_unlock(&lock);
179 		/* Blame AUTOTOOLS for using 77 for skipped test and QEMU for
180 		 * mangling error codes in a way that gets 77 if we ... */
181 		return 77 >> 1;
182 	}
183 
184 	ret = failures > 0 ? 1 : 0;
185 	spin_unlock(&lock);
186 	return ret;
187 }
188 
189 void report_abort(const char *msg_fmt, ...)
190 {
191 	va_list va;
192 
193 	spin_lock(&lock);
194 	puts("ABORT: ");
195 	puts(prefixes);
196 	va_start(va, msg_fmt);
197 	vprintf(msg_fmt, va);
198 	va_end(va);
199 	puts("\n");
200 	spin_unlock(&lock);
201 	report_summary();
202 	abort();
203 }
204