xref: /kvm-unit-tests/lib/report.c (revision 7516869fc7fbc175d18adb165117ba502050b160)
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_prefix_pushf(const char *prefix_fmt, ...)
23 {
24 	va_list va;
25 	int len;
26 	int start;
27 
28 	spin_lock(&lock);
29 
30 	len = strlen(prefixes);
31 	assert_msg(len < sizeof(prefixes), "%d >= %lu", len, sizeof(prefixes));
32 	start = len;
33 
34 	va_start(va, prefix_fmt);
35 	len += vsnprintf(&prefixes[len], sizeof(prefixes) - len, prefix_fmt,
36 			 va);
37 	va_end(va);
38 	assert_msg(len < sizeof(prefixes), "%d >= %lu", len, sizeof(prefixes));
39 
40 	assert_msg(!strstr(&prefixes[start], PREFIX_DELIMITER),
41 		   "Prefix \"%s\" contains delimiter \"" PREFIX_DELIMITER "\"",
42 		   &prefixes[start]);
43 
44 	len += snprintf(&prefixes[len], sizeof(prefixes) - len,
45 			PREFIX_DELIMITER);
46 	assert_msg(len < sizeof(prefixes), "%d >= %lu", len, sizeof(prefixes));
47 
48 	spin_unlock(&lock);
49 }
50 
51 void report_prefix_push(const char *prefix)
52 {
53 	report_prefix_pushf("%s", prefix);
54 }
55 
56 void report_prefix_pop(void)
57 {
58 	char *p, *q;
59 
60 	spin_lock(&lock);
61 
62 	if (!*prefixes)
63 		return;
64 
65 	for (p = prefixes, q = strstr(p, PREFIX_DELIMITER) + 2;
66 			*q;
67 			p = q, q = strstr(p, PREFIX_DELIMITER) + 2)
68 		;
69 	*p = '\0';
70 
71 	spin_unlock(&lock);
72 }
73 
74 static void va_report(const char *msg_fmt,
75 		bool pass, bool xfail, bool skip, va_list va)
76 {
77 	char *prefix = skip ? "SKIP"
78 	                    : xfail ? (pass ? "XPASS" : "XFAIL")
79 	                            : (pass ? "PASS"  : "FAIL");
80 
81 	spin_lock(&lock);
82 
83 	tests++;
84 	printf("%s: ", prefix);
85 	puts(prefixes);
86 	vprintf(msg_fmt, va);
87 	puts("\n");
88 	if (skip)
89 		skipped++;
90 	else if (xfail && !pass)
91 		xfailures++;
92 	else if (xfail || !pass)
93 		failures++;
94 
95 	spin_unlock(&lock);
96 }
97 
98 void report(const char *msg_fmt, bool pass, ...)
99 {
100 	va_list va;
101 	va_start(va, pass);
102 	va_report(msg_fmt, pass, false, false, va);
103 	va_end(va);
104 }
105 
106 void report_xfail(const char *msg_fmt, bool xfail, bool pass, ...)
107 {
108 	va_list va;
109 	va_start(va, pass);
110 	va_report(msg_fmt, pass, xfail, false, va);
111 	va_end(va);
112 }
113 
114 void report_skip(const char *msg_fmt, ...)
115 {
116 	va_list va;
117 	va_start(va, msg_fmt);
118 	va_report(msg_fmt, false, false, true, va);
119 	va_end(va);
120 }
121 
122 void report_info(const char *msg_fmt, ...)
123 {
124 	va_list va;
125 
126 	spin_lock(&lock);
127 	puts("INFO: ");
128 	puts(prefixes);
129 	va_start(va, msg_fmt);
130 	vprintf(msg_fmt, va);
131 	va_end(va);
132 	puts("\n");
133 	spin_unlock(&lock);
134 }
135 
136 int report_summary(void)
137 {
138 	spin_lock(&lock);
139 
140 	printf("SUMMARY: %d tests", tests);
141 	if (failures)
142 		printf(", %d unexpected failures", failures);
143 	if (xfailures)
144 		printf(", %d expected failures", xfailures);
145 	if (skipped)
146 		printf(", %d skipped", skipped);
147 	printf("\n");
148 
149 	if (tests == skipped)
150 		/* Blame AUTOTOOLS for using 77 for skipped test and QEMU for
151 		 * mangling error codes in a way that gets 77 if we ... */
152 		return 77 >> 1;
153 
154 	return failures > 0 ? 1 : 0;
155 
156 	spin_unlock(&lock);
157 }
158 
159 void report_abort(const char *msg_fmt, ...)
160 {
161 	va_list va;
162 
163 	spin_lock(&lock);
164 	puts("ABORT: ");
165 	puts(prefixes);
166 	va_start(va, msg_fmt);
167 	vprintf(msg_fmt, va);
168 	va_end(va);
169 	puts("\n");
170 	spin_unlock(&lock);
171 	report_summary();
172 	abort();
173 }
174