1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Simple unit test library 4 * 5 * Copyright (c) 2013 Google, Inc 6 */ 7 8#include <common.h> 9#include <console.h> 10#include <malloc.h> 11#ifdef CONFIG_SANDBOX 12#include <asm/state.h> 13#endif 14#include <asm/global_data.h> 15#include <test/test.h> 16#include <test/ut.h> 17 18DECLARE_GLOBAL_DATA_PTR; 19 20void ut_fail(struct unit_test_state *uts, const char *fname, int line, 21 const char *func, const char *cond) 22{ 23 gd->flags &= ~(GD_FLG_SILENT | GD_FLG_RECORD); 24 printf("%s:%d, %s(): %s\n", fname, line, func, cond); 25 uts->fail_count++; 26} 27 28void ut_failf(struct unit_test_state *uts, const char *fname, int line, 29 const char *func, const char *cond, const char *fmt, ...) 30{ 31 va_list args; 32 33 gd->flags &= ~(GD_FLG_SILENT | GD_FLG_RECORD); 34 printf("%s:%d, %s(): %s: ", fname, line, func, cond); 35 va_start(args, fmt); 36 vprintf(fmt, args); 37 va_end(args); 38 putc('\n'); 39 uts->fail_count++; 40} 41 42ulong ut_check_free(void) 43{ 44 struct mallinfo info = mallinfo(); 45 46 return info.uordblks; 47} 48 49long ut_check_delta(ulong last) 50{ 51 return ut_check_free() - last; 52} 53 54static int readline_check(struct unit_test_state *uts) 55{ 56 int ret; 57 58 ret = console_record_readline(uts->actual_str, sizeof(uts->actual_str)); 59 if (ret == -ENOSPC) { 60 ut_fail(uts, __FILE__, __LINE__, __func__, 61 "Console record buffer too small - increase CONFIG_CONSOLE_RECORD_OUT_SIZE"); 62 return ret; 63 } 64 65 return 0; 66} 67 68int ut_check_console_line(struct unit_test_state *uts, const char *fmt, ...) 69{ 70 va_list args; 71 int len; 72 int ret; 73 74 va_start(args, fmt); 75 len = vsnprintf(uts->expect_str, sizeof(uts->expect_str), fmt, args); 76 va_end(args); 77 if (len >= sizeof(uts->expect_str)) { 78 ut_fail(uts, __FILE__, __LINE__, __func__, 79 "unit_test_state->expect_str too small"); 80 return -EOVERFLOW; 81 } 82 ret = readline_check(uts); 83 if (ret < 0) 84 return ret; 85 86 return strcmp(uts->expect_str, uts->actual_str); 87} 88 89int ut_check_console_linen(struct unit_test_state *uts, const char *fmt, ...) 90{ 91 va_list args; 92 int len; 93 int ret; 94 95 va_start(args, fmt); 96 len = vsnprintf(uts->expect_str, sizeof(uts->expect_str), fmt, args); 97 va_end(args); 98 if (len >= sizeof(uts->expect_str)) { 99 ut_fail(uts, __FILE__, __LINE__, __func__, 100 "unit_test_state->expect_str too small"); 101 return -EOVERFLOW; 102 } 103 ret = readline_check(uts); 104 if (ret < 0) 105 return ret; 106 107 return strncmp(uts->expect_str, uts->actual_str, 108 strlen(uts->expect_str)); 109} 110 111int ut_check_skipline(struct unit_test_state *uts) 112{ 113 int ret; 114 115 if (!console_record_avail()) 116 return -ENFILE; 117 ret = readline_check(uts); 118 if (ret < 0) 119 return ret; 120 121 return 0; 122} 123 124int ut_check_skip_to_linen(struct unit_test_state *uts, const char *fmt, ...) 125{ 126 va_list args; 127 int len; 128 int ret; 129 130 va_start(args, fmt); 131 len = vsnprintf(uts->expect_str, sizeof(uts->expect_str), fmt, args); 132 va_end(args); 133 if (len >= sizeof(uts->expect_str)) { 134 ut_fail(uts, __FILE__, __LINE__, __func__, 135 "unit_test_state->expect_str too small"); 136 return -EOVERFLOW; 137 } 138 while (1) { 139 if (!console_record_avail()) 140 return -ENOENT; 141 ret = readline_check(uts); 142 if (ret < 0) 143 return ret; 144 145 if (!strncmp(uts->expect_str, uts->actual_str, 146 strlen(uts->expect_str))) 147 return 0; 148 } 149} 150 151int ut_check_skip_to_line(struct unit_test_state *uts, const char *fmt, ...) 152{ 153 va_list args; 154 int len; 155 int ret; 156 157 va_start(args, fmt); 158 len = vsnprintf(uts->expect_str, sizeof(uts->expect_str), fmt, args); 159 va_end(args); 160 if (len >= sizeof(uts->expect_str)) { 161 ut_fail(uts, __FILE__, __LINE__, __func__, 162 "unit_test_state->expect_str too small"); 163 return -EOVERFLOW; 164 } 165 while (1) { 166 if (!console_record_avail()) 167 return -ENOENT; 168 ret = readline_check(uts); 169 if (ret < 0) 170 return ret; 171 172 if (!strcmp(uts->expect_str, uts->actual_str)) 173 return 0; 174 } 175} 176 177int ut_check_console_end(struct unit_test_state *uts) 178{ 179 int ret; 180 181 if (!console_record_avail()) 182 return 0; 183 ret = readline_check(uts); 184 if (ret < 0) 185 return ret; 186 187 return 1; 188} 189 190int ut_check_console_dump(struct unit_test_state *uts, int total_bytes) 191{ 192 char *str = uts->actual_str; 193 int upto; 194 195 /* Handle empty dump */ 196 if (!total_bytes) 197 return 0; 198 199 for (upto = 0; upto < total_bytes;) { 200 int len; 201 int bytes; 202 203 len = console_record_readline(str, sizeof(uts->actual_str)); 204 if (str[8] != ':' || str[9] != ' ') 205 return 1; 206 207 bytes = len - 8 - 2 - 3 * 16 - 2; 208 upto += bytes; 209 } 210 211 return upto == total_bytes ? 0 : 1; 212} 213 214void ut_silence_console(struct unit_test_state *uts) 215{ 216#ifdef CONFIG_SANDBOX 217 struct sandbox_state *state = state_get_current(); 218 219 if (!state->show_test_output) 220 gd->flags |= GD_FLG_SILENT; 221#endif 222} 223 224void ut_unsilence_console(struct unit_test_state *uts) 225{ 226 gd->flags &= ~(GD_FLG_SILENT | GD_FLG_RECORD); 227} 228 229void ut_set_skip_delays(struct unit_test_state *uts, bool skip_delays) 230{ 231#ifdef CONFIG_SANDBOX 232 state_set_skip_delays(skip_delays); 233#endif 234} 235