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 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 kfail, bool skip, va_list va) 85 { 86 const char *prefix = skip ? "SKIP" 87 : xfail ? (pass ? "XPASS" : "XFAIL") 88 : kfail ? (pass ? "PASS" : "KFAIL") 89 : (pass ? "PASS" : "FAIL"); 90 91 spin_lock(&lock); 92 93 tests++; 94 printf("%s: ", prefix); 95 puts(prefixes); 96 vprintf(msg_fmt, va); 97 puts("\n"); 98 if (skip) 99 skipped++; 100 else if (xfail && !pass) 101 xfailures++; 102 else if (kfail && !pass) 103 kfailures++; 104 else if (xfail || !pass) 105 failures++; 106 107 spin_unlock(&lock); 108 } 109 110 void report(bool pass, const char *msg_fmt, ...) 111 { 112 va_list va; 113 va_start(va, msg_fmt); 114 va_report(msg_fmt, pass, false, false, false, va); 115 va_end(va); 116 } 117 118 void report_pass(const char *msg_fmt, ...) 119 { 120 va_list va; 121 122 va_start(va, msg_fmt); 123 va_report(msg_fmt, true, false, false, false, va); 124 va_end(va); 125 } 126 127 void report_fail(const char *msg_fmt, ...) 128 { 129 va_list va; 130 131 va_start(va, msg_fmt); 132 va_report(msg_fmt, false, false, false, false, va); 133 va_end(va); 134 } 135 136 void report_xfail(bool xfail, bool pass, const char *msg_fmt, ...) 137 { 138 va_list va; 139 va_start(va, msg_fmt); 140 va_report(msg_fmt, pass, xfail, false, false, va); 141 va_end(va); 142 } 143 144 /* 145 * kfail is known failure. If kfail is true then test will succeed 146 * regardless of pass. 147 */ 148 void report_kfail(bool kfail, bool pass, const char *msg_fmt, ...) 149 { 150 va_list va; 151 va_start(va, msg_fmt); 152 va_report(msg_fmt, pass, false, kfail, false, va); 153 va_end(va); 154 } 155 156 void report_skip(const char *msg_fmt, ...) 157 { 158 va_list va; 159 va_start(va, msg_fmt); 160 va_report(msg_fmt, false, false, false, true, va); 161 va_end(va); 162 } 163 164 void report_info(const char *msg_fmt, ...) 165 { 166 va_list va; 167 168 spin_lock(&lock); 169 puts("INFO: "); 170 puts(prefixes); 171 va_start(va, msg_fmt); 172 vprintf(msg_fmt, va); 173 va_end(va); 174 puts("\n"); 175 spin_unlock(&lock); 176 } 177 178 int report_summary(void) 179 { 180 int ret; 181 spin_lock(&lock); 182 183 printf("SUMMARY: %d tests", tests); 184 if (failures) 185 printf(", %d unexpected failures", failures); 186 if (kfailures) 187 printf(", %d known failures", kfailures); 188 if (xfailures) 189 printf(", %d expected failures", xfailures); 190 if (skipped) 191 printf(", %d skipped", skipped); 192 printf("\n"); 193 194 if (tests == skipped) { 195 spin_unlock(&lock); 196 /* Blame AUTOTOOLS for using 77 for skipped test and QEMU for 197 * mangling error codes in a way that gets 77 if we ... */ 198 return 77 >> 1; 199 } 200 201 ret = failures > 0 ? 1 : 0; 202 spin_unlock(&lock); 203 return ret; 204 } 205 206 void report_abort(const char *msg_fmt, ...) 207 { 208 va_list va; 209 210 spin_lock(&lock); 211 puts("ABORT: "); 212 puts(prefixes); 213 va_start(va, msg_fmt); 214 vprintf(msg_fmt, va); 215 va_end(va); 216 puts("\n"); 217 spin_unlock(&lock); 218 report_summary(); 219 abort(); 220 } 221