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 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 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 77 void report_prefix_pop(void) 78 { 79 spin_lock(&lock); 80 __report_prefix_pop(); 81 spin_unlock(&lock); 82 } 83 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 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 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 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 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 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 */ 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 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 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 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 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