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 
18 DECLARE_GLOBAL_DATA_PTR;
19 
ut_fail(struct unit_test_state * uts,const char * fname,int line,const char * func,const char * cond)20 void 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 
ut_failf(struct unit_test_state * uts,const char * fname,int line,const char * func,const char * cond,const char * fmt,...)28 void 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 
ut_check_free(void)42 ulong ut_check_free(void)
43 {
44 	struct mallinfo info = mallinfo();
45 
46 	return info.uordblks;
47 }
48 
ut_check_delta(ulong last)49 long ut_check_delta(ulong last)
50 {
51 	return ut_check_free() - last;
52 }
53 
readline_check(struct unit_test_state * uts)54 static 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 
ut_check_console_line(struct unit_test_state * uts,const char * fmt,...)68 int 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 
ut_check_console_linen(struct unit_test_state * uts,const char * fmt,...)89 int 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 
ut_check_skipline(struct unit_test_state * uts)111 int 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 
ut_check_skip_to_line(struct unit_test_state * uts,const char * fmt,...)124 int ut_check_skip_to_line(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 (!strcmp(uts->expect_str, uts->actual_str))
146 			return 0;
147 	}
148 }
149 
ut_check_console_end(struct unit_test_state * uts)150 int ut_check_console_end(struct unit_test_state *uts)
151 {
152 	int ret;
153 
154 	if (!console_record_avail())
155 		return 0;
156 	ret = readline_check(uts);
157 	if (ret < 0)
158 		return ret;
159 
160 	return 1;
161 }
162 
ut_check_console_dump(struct unit_test_state * uts,int total_bytes)163 int ut_check_console_dump(struct unit_test_state *uts, int total_bytes)
164 {
165 	char *str = uts->actual_str;
166 	int upto;
167 
168 	/* Handle empty dump */
169 	if (!total_bytes)
170 		return 0;
171 
172 	for (upto = 0; upto < total_bytes;) {
173 		int len;
174 		int bytes;
175 
176 		len = console_record_readline(str, sizeof(uts->actual_str));
177 		if (str[8] != ':' || str[9] != ' ')
178 			return 1;
179 
180 		bytes = len - 8 - 2 - 3 * 16 - 2;
181 		upto += bytes;
182 	}
183 
184 	return upto == total_bytes ? 0 : 1;
185 }
186 
ut_silence_console(struct unit_test_state * uts)187 void ut_silence_console(struct unit_test_state *uts)
188 {
189 #ifdef CONFIG_SANDBOX
190 	struct sandbox_state *state = state_get_current();
191 
192 	if (!state->show_test_output)
193 		gd->flags |= GD_FLG_SILENT;
194 #endif
195 }
196 
ut_unsilence_console(struct unit_test_state * uts)197 void ut_unsilence_console(struct unit_test_state *uts)
198 {
199 	gd->flags &= ~(GD_FLG_SILENT | GD_FLG_RECORD);
200 }
201 
ut_set_skip_delays(struct unit_test_state * uts,bool skip_delays)202 void ut_set_skip_delays(struct unit_test_state *uts, bool skip_delays)
203 {
204 #ifdef CONFIG_SANDBOX
205 	state_set_skip_delays(skip_delays);
206 #endif
207 }
208