]> git.saurik.com Git - apple/xnu.git/blob - osfmk/tests/ktest_emit.c
xnu-6153.121.1.tar.gz
[apple/xnu.git] / osfmk / tests / ktest_emit.c
1 /*
2 * Copyright (c) 2015 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 #include <tests/ktest_internal.h>
30 #include <kern/misc_protos.h>
31 #include <kern/debug.h>
32
33 #define EMIT(buf, size) do {\
34 console_write(buf, size); \
35 } while(0)
36
37 /* TODO: intelligently truncate messages if possible */
38 #define BOUNDS_CHECK_AND_UPDATE(ret, size) do {\
39 if(ret < 0 || ret >= size) {\
40 panic("Internal ktest error in %s", __func__);\
41 }\
42 size -= ret;\
43 msg += ret;\
44 } while(0)
45
46 int vsnprintf(char *, size_t, const char *, va_list);
47
48 void
49 ktest_emit_start(void)
50 {
51 char str[] = "\n[KTEST]\tSTART\t" KTEST_VERSION_STR "\n";
52 EMIT((char *)&str[0], sizeof(str) - 1);
53 }
54
55 void
56 ktest_emit_finish(void)
57 {
58 char str[] = "\n[KTEST]\tFINISH\n";
59 EMIT((char *)&str[0], sizeof(str) - 1);
60 }
61
62 void
63 ktest_emit_testbegin(const char * test_name)
64 {
65 char * msg = ktest_output_buf;
66 int size = sizeof(ktest_output_buf);
67 int ret;
68
69 /* left trim the file path for readability */
70 char *fname = strnstr((char *)(uintptr_t)ktest_current_file, "xnu", 100);
71
72 ret = snprintf(msg,
73 size,
74 "\n[KTEST]\t" /* header */
75 "TESTBEGIN\t" /* type */
76 "%lld\t" /* time */
77 "%d\t" /* index */
78 "%s\t" /* file */
79 "%d\t" /* line */
80 "%s\n", /* name */
81 ktest_current_time,
82 ktest_test_index,
83 fname,
84 ktest_current_line,
85 test_name);
86 BOUNDS_CHECK_AND_UPDATE(ret, size);
87
88 EMIT(ktest_output_buf, (int)(msg - ktest_output_buf));
89 }
90
91 void
92 ktest_emit_testskip(const char * skip_msg, va_list args)
93 {
94 char * msg = ktest_output_buf;
95 int size = sizeof(ktest_output_buf);
96 int ret;
97
98 char *fname = strnstr((char *)(uintptr_t)ktest_current_file, "xnu", 100);
99
100 ret = snprintf(msg,
101 size,
102 "\n[KTEST]\t" /* header */
103 "TESTSKIP\t" /* type */
104 "%lld\t" /* time */
105 "%s\t" /* file */
106 "%d\t", /* line */
107 ktest_current_time,
108 fname,
109 ktest_current_line);
110 BOUNDS_CHECK_AND_UPDATE(ret, size);
111
112 ret = vsnprintf(msg, size, skip_msg, args);
113 BOUNDS_CHECK_AND_UPDATE(ret, size);
114
115 ret = snprintf(msg, size, "\n");
116 BOUNDS_CHECK_AND_UPDATE(ret, size);
117
118 EMIT(ktest_output_buf, (int)(msg - ktest_output_buf));
119 }
120
121 void
122 ktest_emit_testend()
123 {
124 char * msg = ktest_output_buf;
125 int size = sizeof(ktest_output_buf);
126 int ret;
127
128 char *fname = strnstr((char *)(uintptr_t)ktest_current_file, "xnu", 100);
129
130 ret = snprintf(msg,
131 size,
132 "\n[KTEST]\t" /* header */
133 "TESTEND\t" /* type */
134 "%lld\t" /* time */
135 "%d\t" /* index */
136 "%s\t" /* file */
137 "%d\t" /* line */
138 "%s\n", /* name */
139 ktest_current_time,
140 ktest_test_index,
141 fname,
142 ktest_current_line,
143 ktest_test_name);
144 BOUNDS_CHECK_AND_UPDATE(ret, size);
145
146 EMIT(ktest_output_buf, (int)(msg - ktest_output_buf));
147 }
148
149 void
150 ktest_emit_log(const char * log_msg, va_list args)
151 {
152 char * msg = ktest_output_buf;
153 int size = sizeof(ktest_output_buf);
154 int ret;
155
156 char *fname = strnstr((char *)(uintptr_t)ktest_current_file, "xnu", 100);
157
158 ret = snprintf(msg,
159 size,
160 "\n[KTEST]\t" /* header */
161 "LOG\t" /* type */
162 "%lld\t" /* time */
163 "%s\t" /* file */
164 "%d\t", /* line */
165 ktest_current_time,
166 fname,
167 ktest_current_line);
168 BOUNDS_CHECK_AND_UPDATE(ret, size);
169
170 ret = vsnprintf(msg, size, log_msg, args);
171 BOUNDS_CHECK_AND_UPDATE(ret, size);
172
173 ret = snprintf(msg, size, "\n");
174 BOUNDS_CHECK_AND_UPDATE(ret, size);
175
176 EMIT(ktest_output_buf, (int)(msg - ktest_output_buf));
177 }
178
179 void
180 ktest_emit_perfdata(const char * metric, const char * unit, double value, const char * desc)
181 {
182 static const char * perfstr = "%s\t%lld\t%s\t\"%s\"";
183 char * msg = ktest_output_buf;
184 int64_t print_value = (int64_t)value;
185 int size = sizeof(ktest_output_buf);
186 int ret;
187
188 char *fname = strnstr((char *)(uintptr_t)ktest_current_file, "xnu", 100);
189
190 ret = snprintf(msg, size,
191 "\n[KTEST]\t" /* header */
192 "PERF\t" /* type */
193 "%lld\t" /* time */
194 "%s\t" /* file */
195 "%d\t", /* line */
196 ktest_current_time,
197 fname,
198 ktest_current_line);
199 BOUNDS_CHECK_AND_UPDATE(ret, size);
200
201 ret = snprintf(msg, size, perfstr, metric, print_value, unit, desc);
202 BOUNDS_CHECK_AND_UPDATE(ret, size);
203
204 ret = snprintf(msg, size, "\n");
205 BOUNDS_CHECK_AND_UPDATE(ret, size);
206
207 EMIT(ktest_output_buf, (int)(msg - ktest_output_buf));
208 }
209
210 void
211 ktest_emit_testcase(void)
212 {
213 char * msg = ktest_output_buf;
214 int size = sizeof(ktest_output_buf);
215 int ret;
216
217 char *fname = strnstr((char *)(uintptr_t)ktest_current_file, "xnu", 100);
218
219 ret = snprintf(msg,
220 size,
221 "\n[KTEST]\t" /* header */
222 "%s\t" /* type */
223 "%lld\t" /* time */
224 "%d\t" /* index */
225 "%s\t" /* file */
226 "%d\t" /* line */
227 "%s\t" /* message */
228 "%s", /* current_expr */
229 ktest_testcase_result_tokens[ktest_testcase_mode]
230 [ktest_testcase_result],
231 ktest_current_time,
232 ktest_expression_index,
233 fname,
234 ktest_current_line,
235 ktest_current_msg,
236 ktest_current_expr);
237 BOUNDS_CHECK_AND_UPDATE(ret, size);
238
239 for (int i = 0; ktest_current_var_names[i][0]; i++) {
240 ret = snprintf(msg,
241 size,
242 "\t%s\t%s",
243 ktest_current_var_names[i],
244 ktest_current_var_values[i]);
245 BOUNDS_CHECK_AND_UPDATE(ret, size);
246 }
247
248 ret = snprintf(msg, size, "\n");
249 BOUNDS_CHECK_AND_UPDATE(ret, size);
250
251 EMIT(ktest_output_buf, (int)(msg - ktest_output_buf));
252 }