OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include <fcntl.h> | 5 #include <fcntl.h> |
6 #include <launchpad/launchpad.h> | 6 #include <launchpad/launchpad.h> |
7 #include <launchpad/vmo.h> | 7 #include <launchpad/vmo.h> |
8 #include <magenta/status.h> | 8 #include <magenta/status.h> |
9 #include <magenta/syscalls.h> | 9 #include <magenta/syscalls.h> |
10 #include <magenta/syscalls/object.h> | 10 #include <magenta/syscalls/object.h> |
11 #include <mxio/util.h> | 11 #include <mxio/util.h> |
12 #include <pthread.h> | 12 #include <pthread.h> |
13 #include <stdbool.h> | 13 #include <stdbool.h> |
14 #include <stdio.h> | 14 #include <stdio.h> |
15 #include <stdlib.h> | 15 #include <stdlib.h> |
16 #include <string.h> | 16 #include <string.h> |
17 #include <unistd.h> | 17 #include <unistd.h> |
18 | 18 |
19 // This program runs Dart VM unit tests. The Dart VM unit tests are contained | 19 // This program runs Dart VM unit tests. The Dart VM unit tests are contained |
20 // in a separate binary whose location is defined in kRunVmTestsPath below. | 20 // in a separate binary whose location is defined in kRunVmTestsPath below. |
21 // That program accepts a command line argument --list to list all the available | 21 // That program accepts a command line argument --list to list all the available |
22 // tests, or the name of a single test to run. This program grabs the list of | 22 // tests, or the name of a single test to run. This program grabs the list of |
23 // tests, and then runs them. | 23 // tests, and then runs them. |
24 | 24 |
25 // TODO(zra): Make this a command line argument | 25 // TODO(zra): Make this a command line argument |
26 const char* kRunVmTestsPath = "/boot/bin/dart_vm_tests"; | 26 const char* kRunVmTestsPath = "/boot/bin/dart_vm_tests"; |
27 | 27 |
| 28 // clang-format off |
28 // Tests that are invalid, wedge, or cause panics. | 29 // Tests that are invalid, wedge, or cause panics. |
29 const char* kSkip[] = { | 30 const char* kSkip[] = { |
30 // These expect a file to exist that we aren't putting in the image. | 31 // These expect a file to exist that we aren't putting in the image. |
31 "Read", | 32 "Read", |
32 "FileLength", | 33 "FileLength", |
33 "FilePosition", | 34 "FilePosition", |
34 // Crash in abort() and then hang. (MG-252) | 35 // Crash in abort() and then hang. (MG-252) |
35 "ArrayLengthMaxElements", | 36 "ArrayLengthMaxElements", |
36 "Int8ListLengthMaxElements", | 37 "Int8ListLengthMaxElements", |
37 "ArrayNew_Overflow_Crash", | 38 "ArrayNew_Overflow_Crash", |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 "CodeImmutability", | 101 "CodeImmutability", |
101 // Assumes initial thread's stack is the same size as spawned thread stacks. | 102 // Assumes initial thread's stack is the same size as spawned thread stacks. |
102 "StackOverflowStacktraceInfo", | 103 "StackOverflowStacktraceInfo", |
103 }; | 104 }; |
104 | 105 |
105 // Bugs to fix, or things that are not yet implemented. | 106 // Bugs to fix, or things that are not yet implemented. |
106 const char* kBugs[] = { | 107 const char* kBugs[] = { |
107 // Needs read of RSS. | 108 // Needs read of RSS. |
108 "InitialRSS", | 109 "InitialRSS", |
109 }; | 110 }; |
110 | 111 // clang-format on |
111 | 112 |
112 static bool contains(const char** list, intptr_t len, const char* str) { | 113 static bool contains(const char** list, intptr_t len, const char* str) { |
113 for (intptr_t i = 0; i < len; i++) { | 114 for (intptr_t i = 0; i < len; i++) { |
114 if (strcmp(list[i], str) == 0) { | 115 if (strcmp(list[i], str) == 0) { |
115 return true; | 116 return true; |
116 } | 117 } |
117 } | 118 } |
118 return false; | 119 return false; |
119 } | 120 } |
120 | 121 |
121 | 122 |
122 static bool isSkip(const char* test) { | 123 static bool isSkip(const char* test) { |
123 return contains( | 124 return contains(kSkip, sizeof(kSkip) / sizeof(kSkip[0]), test); |
124 kSkip, sizeof(kSkip) / sizeof(kSkip[0]), test); | |
125 } | 125 } |
126 | 126 |
127 | 127 |
128 static bool isExpectFail(const char* test) { | 128 static bool isExpectFail(const char* test) { |
129 return contains( | 129 return contains(kExpectFail, sizeof(kExpectFail) / sizeof(kExpectFail[0]), |
130 kExpectFail, sizeof(kExpectFail) / sizeof(kExpectFail[0]), test); | 130 test); |
131 } | 131 } |
132 | 132 |
133 | 133 |
134 static bool isBug(const char* test) { | 134 static bool isBug(const char* test) { |
135 return contains(kBugs, sizeof(kBugs) / sizeof(kBugs[0]), test); | 135 return contains(kBugs, sizeof(kBugs) / sizeof(kBugs[0]), test); |
136 } | 136 } |
137 | 137 |
138 #define RETURN_IF_ERROR(status) \ | 138 #define RETURN_IF_ERROR(status) \ |
139 if (status < 0) { \ | 139 if (status < 0) { \ |
140 fprintf(stderr, "%s:%d: Magenta call failed: %s\n", __FILE__, __LINE__, \ | 140 fprintf(stderr, "%s:%d: Magenta call failed: %s\n", __FILE__, __LINE__, \ |
141 mx_status_get_string(static_cast<mx_status_t>(status))); \ | 141 mx_status_get_string(static_cast<mx_status_t>(status))); \ |
142 fflush(0); \ | 142 fflush(0); \ |
143 return status; \ | 143 return status; \ |
144 } | 144 } |
145 | 145 |
146 // This is mostly taken from //magenta/system/uapp/mxsh with the addtion of | 146 // This is mostly taken from //magenta/system/uapp/mxsh with the addtion of |
147 // launchpad_add_pipe calls to setup pipes for stdout and stderr. | 147 // launchpad_add_pipe calls to setup pipes for stdout and stderr. |
148 static mx_status_t lp_setup(launchpad_t** lp_out, mx_handle_t binary_vmo, | 148 static mx_status_t lp_setup(launchpad_t** lp_out, |
149 int argc, const char* const* argv, | 149 mx_handle_t binary_vmo, |
150 int *stdout_out, int *stderr_out) { | 150 int argc, |
| 151 const char* const* argv, |
| 152 int* stdout_out, |
| 153 int* stderr_out) { |
151 if ((lp_out == NULL) || (stdout_out == NULL) || (stderr_out == NULL)) { | 154 if ((lp_out == NULL) || (stdout_out == NULL) || (stderr_out == NULL)) { |
152 return ERR_INVALID_ARGS; | 155 return ERR_INVALID_ARGS; |
153 } | 156 } |
154 launchpad_t* lp; | 157 launchpad_t* lp; |
155 mx_status_t status; | 158 mx_status_t status; |
156 status = launchpad_create(0, argv[0], &lp); | 159 status = launchpad_create(0, argv[0], &lp); |
157 RETURN_IF_ERROR(status); | 160 RETURN_IF_ERROR(status); |
158 status = launchpad_arguments(lp, argc, argv); | 161 status = launchpad_arguments(lp, argc, argv); |
159 RETURN_IF_ERROR(status); | 162 RETURN_IF_ERROR(status); |
160 status = launchpad_clone_mxio_root(lp); | 163 status = launchpad_clone_mxio_root(lp); |
161 RETURN_IF_ERROR(status); | 164 RETURN_IF_ERROR(status); |
162 status = launchpad_add_pipe(lp, stdout_out, 1); | 165 status = launchpad_add_pipe(lp, stdout_out, 1); |
163 RETURN_IF_ERROR(status); | 166 RETURN_IF_ERROR(status); |
164 status = launchpad_add_pipe(lp, stderr_out, 2); | 167 status = launchpad_add_pipe(lp, stderr_out, 2); |
165 RETURN_IF_ERROR(status); | 168 RETURN_IF_ERROR(status); |
166 status = launchpad_add_vdso_vmo(lp); | 169 status = launchpad_add_vdso_vmo(lp); |
167 RETURN_IF_ERROR(status); | 170 RETURN_IF_ERROR(status); |
168 status = launchpad_elf_load(lp, binary_vmo); | 171 status = launchpad_elf_load(lp, binary_vmo); |
169 RETURN_IF_ERROR(status); | 172 RETURN_IF_ERROR(status); |
170 status = launchpad_load_vdso(lp, MX_HANDLE_INVALID); | 173 status = launchpad_load_vdso(lp, MX_HANDLE_INVALID); |
171 RETURN_IF_ERROR(status); | 174 RETURN_IF_ERROR(status); |
172 *lp_out = lp; | 175 *lp_out = lp; |
173 return status; | 176 return status; |
174 } | 177 } |
175 | 178 |
176 | 179 |
177 // Start the test running and return file descriptors for the stdout and stderr | 180 // Start the test running and return file descriptors for the stdout and stderr |
178 // pipes. | 181 // pipes. |
179 static mx_handle_t start_test(mx_handle_t binary_vmo, const char* test_name, | 182 static mx_handle_t start_test(mx_handle_t binary_vmo, |
180 int* stdout_out, int* stderr_out) { | 183 const char* test_name, |
| 184 int* stdout_out, |
| 185 int* stderr_out) { |
181 const intptr_t kArgc = 2; | 186 const intptr_t kArgc = 2; |
182 const char* argv[kArgc]; | 187 const char* argv[kArgc]; |
183 | 188 |
184 argv[0] = kRunVmTestsPath; | 189 argv[0] = kRunVmTestsPath; |
185 argv[1] = test_name; | 190 argv[1] = test_name; |
186 | 191 |
187 launchpad_t* lp = NULL; | 192 launchpad_t* lp = NULL; |
188 int stdout_pipe = -1; | 193 int stdout_pipe = -1; |
189 int stderr_pipe = -1; | 194 int stderr_pipe = -1; |
190 mx_status_t status = lp_setup( | 195 mx_status_t status = |
191 &lp, binary_vmo, kArgc, argv, &stdout_pipe, &stderr_pipe); | 196 lp_setup(&lp, binary_vmo, kArgc, argv, &stdout_pipe, &stderr_pipe); |
192 if (status != NO_ERROR) { | 197 if (status != NO_ERROR) { |
193 if (lp != NULL) { | 198 if (lp != NULL) { |
194 launchpad_destroy(lp); | 199 launchpad_destroy(lp); |
195 } | 200 } |
196 if (stdout_pipe != -1) { | 201 if (stdout_pipe != -1) { |
197 close(stdout_pipe); | 202 close(stdout_pipe); |
198 } | 203 } |
199 if (stderr_pipe != -1) { | 204 if (stderr_pipe != -1) { |
200 close(stderr_pipe); | 205 close(stderr_pipe); |
201 } | 206 } |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 } | 252 } |
248 buf[total_read] = '\0'; | 253 buf[total_read] = '\0'; |
249 close(fd); | 254 close(fd); |
250 *buffer = buf; | 255 *buffer = buf; |
251 return total_read; | 256 return total_read; |
252 } | 257 } |
253 | 258 |
254 | 259 |
255 // Runs test 'test_name' and gives stdout and stderr for the test in | 260 // Runs test 'test_name' and gives stdout and stderr for the test in |
256 // 'test_stdout' and 'test_stderr'. Returns the exit code from the test. | 261 // 'test_stdout' and 'test_stderr'. Returns the exit code from the test. |
257 static int run_test(mx_handle_t binary_vmo, const char* test_name, | 262 static int run_test(mx_handle_t binary_vmo, |
258 char** test_stdout, char** test_stderr) { | 263 const char* test_name, |
| 264 char** test_stdout, |
| 265 char** test_stderr) { |
259 int stdout_pipe = -1; | 266 int stdout_pipe = -1; |
260 int stderr_pipe = -1; | 267 int stderr_pipe = -1; |
261 mx_handle_t p = start_test(binary_vmo, test_name, &stdout_pipe, &stderr_pipe); | 268 mx_handle_t p = start_test(binary_vmo, test_name, &stdout_pipe, &stderr_pipe); |
262 RETURN_IF_ERROR(p); | 269 RETURN_IF_ERROR(p); |
263 | 270 |
264 drain_fd(stdout_pipe, test_stdout); | 271 drain_fd(stdout_pipe, test_stdout); |
265 drain_fd(stderr_pipe, test_stderr); | 272 drain_fd(stderr_pipe, test_stderr); |
266 | 273 |
267 mx_status_t r = mx_handle_wait_one( | 274 mx_status_t r = |
268 p, MX_SIGNAL_SIGNALED, MX_TIME_INFINITE, NULL); | 275 mx_handle_wait_one(p, MX_SIGNAL_SIGNALED, MX_TIME_INFINITE, NULL); |
269 RETURN_IF_ERROR(r); | 276 RETURN_IF_ERROR(r); |
270 | 277 |
271 mx_info_process_t proc_info; | 278 mx_info_process_t proc_info; |
272 mx_size_t info_size; | 279 mx_size_t info_size; |
273 mx_status_t status = | 280 mx_status_t status = |
274 mx_object_get_info(p, MX_INFO_PROCESS, sizeof(proc_info.rec), | 281 mx_object_get_info(p, MX_INFO_PROCESS, sizeof(proc_info.rec), &proc_info, |
275 &proc_info, sizeof(proc_info), &info_size); | 282 sizeof(proc_info), &info_size); |
276 RETURN_IF_ERROR(status); | 283 RETURN_IF_ERROR(status); |
277 | 284 |
278 r = mx_handle_close(p); | 285 r = mx_handle_close(p); |
279 RETURN_IF_ERROR(r); | 286 RETURN_IF_ERROR(r); |
280 return proc_info.rec.return_code; | 287 return proc_info.rec.return_code; |
281 } | 288 } |
282 | 289 |
283 | 290 |
284 static void handle_result( | 291 static void handle_result(intptr_t result, |
285 intptr_t result, char* test_stdout, char* test_stderr, const char* test) { | 292 char* test_stdout, |
| 293 char* test_stderr, |
| 294 const char* test) { |
286 if (result != 0) { | 295 if (result != 0) { |
287 if (!isExpectFail(test) && !isBug(test)) { | 296 if (!isExpectFail(test) && !isBug(test)) { |
288 printf("**** Test %s FAILED\n\nstdout:\n%s\nstderr:\n%s\n", | 297 printf("**** Test %s FAILED\n\nstdout:\n%s\nstderr:\n%s\n", test, |
289 test, test_stdout, test_stderr); | 298 test_stdout, test_stderr); |
290 } else { | 299 } else { |
291 printf("Test %s FAILED and is expected to fail\n", test); | 300 printf("Test %s FAILED and is expected to fail\n", test); |
292 } | 301 } |
293 } else { | 302 } else { |
294 if (isExpectFail(test)) { | 303 if (isExpectFail(test)) { |
295 printf("**** Test %s is expected to fail, but PASSED\n\n" | 304 printf( |
296 "stdout:\n%s\nstderr:\n%s\n", | 305 "**** Test %s is expected to fail, but PASSED\n\n" |
297 test, test_stdout, test_stderr); | 306 "stdout:\n%s\nstderr:\n%s\n", |
| 307 test, test_stdout, test_stderr); |
298 } else if (isBug(test)) { | 308 } else if (isBug(test)) { |
299 printf("**** Test %s is marked as a bug, but PASSED\n", test); | 309 printf("**** Test %s is marked as a bug, but PASSED\n", test); |
300 } else { | 310 } else { |
301 printf("Test %s PASSED\n", test); | 311 printf("Test %s PASSED\n", test); |
302 } | 312 } |
303 } | 313 } |
304 } | 314 } |
305 | 315 |
306 | 316 |
307 typedef struct { | 317 typedef struct { |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
439 RETURN_IF_ERROR(status); | 449 RETURN_IF_ERROR(status); |
440 | 450 |
441 // Complain if we didn't try to run all of the tests. | 451 // Complain if we didn't try to run all of the tests. |
442 if (test_list_index != lines_count) { | 452 if (test_list_index != lines_count) { |
443 fprintf(stderr, "Failed to attempt all the tests!\n"); | 453 fprintf(stderr, "Failed to attempt all the tests!\n"); |
444 fflush(0); | 454 fflush(0); |
445 return -1; | 455 return -1; |
446 } | 456 } |
447 return 0; | 457 return 0; |
448 } | 458 } |
OLD | NEW |