| 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 |