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_pass(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 return; 71 72 for (p = prefixes, q = strstr(p, PREFIX_DELIMITER) + 2; 73 *q; 74 p = q, q = strstr(p, PREFIX_DELIMITER) + 2) 75 ; 76 *p = '\0'; 77 78 spin_unlock(&lock); 79 } 80 81 static void va_report(const char *msg_fmt, 82 bool pass, bool xfail, bool skip, va_list va) 83 { 84 const char *prefix = skip ? "SKIP" 85 : xfail ? (pass ? "XPASS" : "XFAIL") 86 : (pass ? "PASS" : "FAIL"); 87 88 spin_lock(&lock); 89 90 tests++; 91 printf("%s: ", prefix); 92 puts(prefixes); 93 vprintf(msg_fmt, va); 94 puts("\n"); 95 if (skip) 96 skipped++; 97 else if (xfail && !pass) 98 xfailures++; 99 else if (xfail || !pass) 100 failures++; 101 102 spin_unlock(&lock); 103 } 104 105 void report(const char *msg_fmt, bool pass, ...) 106 { 107 va_list va; 108 va_start(va, pass); 109 va_report(msg_fmt, pass, false, false, va); 110 va_end(va); 111 } 112 113 void report_xfail(const char *msg_fmt, bool xfail, bool pass, ...) 114 { 115 va_list va; 116 va_start(va, pass); 117 va_report(msg_fmt, pass, xfail, false, va); 118 va_end(va); 119 } 120 121 void report_skip(const char *msg_fmt, ...) 122 { 123 va_list va; 124 va_start(va, msg_fmt); 125 va_report(msg_fmt, false, false, true, va); 126 va_end(va); 127 } 128 129 void report_info(const char *msg_fmt, ...) 130 { 131 va_list va; 132 133 spin_lock(&lock); 134 puts("INFO: "); 135 puts(prefixes); 136 va_start(va, msg_fmt); 137 vprintf(msg_fmt, va); 138 va_end(va); 139 puts("\n"); 140 spin_unlock(&lock); 141 } 142 143 int report_summary(void) 144 { 145 spin_lock(&lock); 146 147 printf("SUMMARY: %d tests", tests); 148 if (failures) 149 printf(", %d unexpected failures", failures); 150 if (xfailures) 151 printf(", %d expected failures", xfailures); 152 if (skipped) 153 printf(", %d skipped", skipped); 154 printf("\n"); 155 156 if (tests == skipped) 157 /* Blame AUTOTOOLS for using 77 for skipped test and QEMU for 158 * mangling error codes in a way that gets 77 if we ... */ 159 return 77 >> 1; 160 161 return failures > 0 ? 1 : 0; 162 163 spin_unlock(&lock); 164 } 165 166 void report_abort(const char *msg_fmt, ...) 167 { 168 va_list va; 169 170 spin_lock(&lock); 171 puts("ABORT: "); 172 puts(prefixes); 173 va_start(va, msg_fmt); 174 vprintf(msg_fmt, va); 175 va_end(va); 176 puts("\n"); 177 spin_unlock(&lock); 178 report_summary(); 179 abort(); 180 } 181