Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(279)

Side by Side Diff: runtime/bin/run_vm_tests_fuchsia.cc

Issue 2708163002: [Fuchsia] Remove dead code (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/bin/BUILD.gn ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 #include <fcntl.h>
6 #include <launchpad/launchpad.h>
7 #include <launchpad/vmo.h>
8 #include <magenta/status.h>
9 #include <magenta/syscalls.h>
10 #include <magenta/syscalls/object.h>
11 #include <mxio/util.h>
12 #include <pthread.h>
13 #include <stdbool.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <unistd.h>
18
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.
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
23 // tests, and then runs them.
24
25 // TODO(zra): Make this a command line argument
26 const char* kRunVmTestsPath = "/system/bin/dart_vm_tests";
27
28 // clang-format off
29 // Tests that are invalid, wedge, or cause panics.
30 const char* kSkip[] = {
31 // These expect a file to exist that we aren't putting in the image.
32 "Read",
33 "FileLength",
34 "FilePosition",
35 // No realpath, files not in image.
36 "Dart2JSCompilerStats",
37 "Dart2JSCompileAll",
38 // The profiler is turned off.
39 "Profiler_AllocationSampleTest",
40 "Profiler_ArrayAllocation",
41 "Profiler_BasicSourcePosition",
42 "Profiler_BasicSourcePositionOptimized",
43 "Profiler_BinaryOperatorSourcePosition",
44 "Profiler_BinaryOperatorSourcePositionOptimized",
45 "Profiler_ChainedSamples",
46 "Profiler_ClosureAllocation",
47 "Profiler_CodeTicks",
48 "Profiler_ContextAllocation",
49 "Profiler_FunctionInline",
50 "Profiler_FunctionTicks",
51 "Profiler_InliningIntervalBoundry",
52 "Profiler_IntrinsicAllocation",
53 "Profiler_SampleBufferIterateTest",
54 "Profiler_SampleBufferWrapTest",
55 "Profiler_SourcePosition",
56 "Profiler_SourcePositionOptimized",
57 "Profiler_StringAllocation",
58 "Profiler_StringInterpolation",
59 "Profiler_ToggleRecordAllocation",
60 "Profiler_TrivialRecordAllocation",
61 "Profiler_TypedArrayAllocation",
62 "Profiler_GetSourceReport",
63 "Service_Profile",
64 };
65
66 // Expected to fail/crash.
67 const char* kExpectFail[] = {
68 "Fail0",
69 "Fail1",
70 "Fail2",
71 "AllocGeneric_Overflow",
72 "CodeImmutability",
73 "IsolateReload_PendingUnqualifiedCall_StaticToInstance",
74 "IsolateReload_PendingConstructorCall_AbstractToConcrete",
75 "IsolateReload_PendingConstructorCall_ConcreteToAbstract",
76 "IsolateReload_PendingUnqualifiedCall_InstanceToStatic",
77 "IsolateReload_PendingStaticCall_DefinedToNSM",
78 "IsolateReload_PendingStaticCall_NSMToDefined",
79 "ArrayNew_Overflow_Crash",
80 "SNPrint_BadArgs",
81 };
82
83 // Bugs to fix, or things that are not yet implemented.
84 const char* kBugs[] = {
85 // Assumes initial thread's stack is the same size as spawned thread stacks.
86 "StackOverflowStackTraceInfo",
87 };
88 // clang-format on
89
90 static bool contains(const char** list, intptr_t len, const char* str) {
91 for (intptr_t i = 0; i < len; i++) {
92 if (strcmp(list[i], str) == 0) {
93 return true;
94 }
95 }
96 return false;
97 }
98
99
100 static bool isSkip(const char* test) {
101 return contains(kSkip, sizeof(kSkip) / sizeof(kSkip[0]), test);
102 }
103
104
105 static bool isExpectFail(const char* test) {
106 return contains(kExpectFail, sizeof(kExpectFail) / sizeof(kExpectFail[0]),
107 test);
108 }
109
110
111 static bool isBug(const char* test) {
112 return contains(kBugs, sizeof(kBugs) / sizeof(kBugs[0]), test);
113 }
114
115 #define RETURN_IF_ERROR(status) \
116 if (status < 0) { \
117 fprintf(stderr, "%s:%d: Magenta call failed: %s\n", __FILE__, __LINE__, \
118 mx_status_get_string(static_cast<mx_status_t>(status))); \
119 fflush(0); \
120 return status; \
121 }
122
123 // This is mostly taken from //magenta/system/uapp/mxsh with the addtion of
124 // launchpad_add_pipe calls to setup pipes for stdout and stderr.
125 static mx_status_t lp_setup(launchpad_t** lp_out,
126 mx_handle_t binary_vmo,
127 int argc,
128 const char* const* argv,
129 int* stdout_out,
130 int* stderr_out) {
131 if ((lp_out == NULL) || (stdout_out == NULL) || (stderr_out == NULL)) {
132 return ERR_INVALID_ARGS;
133 }
134 launchpad_t* lp;
135 mx_status_t status;
136 mx_handle_t job = MX_HANDLE_INVALID;
137 status = mx_handle_duplicate(mx_job_default(), MX_RIGHT_SAME_RIGHTS, &job);
138 RETURN_IF_ERROR(status);
139 status = launchpad_create(job, argv[0], &lp);
140 RETURN_IF_ERROR(status);
141 status = launchpad_arguments(lp, argc, argv);
142 RETURN_IF_ERROR(status);
143 status = launchpad_clone_mxio_root(lp);
144 RETURN_IF_ERROR(status);
145 status = launchpad_add_pipe(lp, stdout_out, 1);
146 RETURN_IF_ERROR(status);
147 status = launchpad_add_pipe(lp, stderr_out, 2);
148 RETURN_IF_ERROR(status);
149 status = launchpad_add_vdso_vmo(lp);
150 RETURN_IF_ERROR(status);
151 status = launchpad_elf_load(lp, binary_vmo);
152 RETURN_IF_ERROR(status);
153 status = launchpad_load_vdso(lp, MX_HANDLE_INVALID);
154 RETURN_IF_ERROR(status);
155 *lp_out = lp;
156 return status;
157 }
158
159
160 // Start the test running and return file descriptors for the stdout and stderr
161 // pipes.
162 static mx_handle_t start_test(mx_handle_t binary_vmo,
163 const char* test_name,
164 int* stdout_out,
165 int* stderr_out) {
166 const intptr_t kArgc = 2;
167 const char* argv[kArgc];
168
169 argv[0] = kRunVmTestsPath;
170 argv[1] = test_name;
171
172 launchpad_t* lp = NULL;
173 int stdout_pipe = -1;
174 int stderr_pipe = -1;
175 mx_status_t status =
176 lp_setup(&lp, binary_vmo, kArgc, argv, &stdout_pipe, &stderr_pipe);
177 if (status != NO_ERROR) {
178 if (lp != NULL) {
179 launchpad_destroy(lp);
180 }
181 if (stdout_pipe != -1) {
182 close(stdout_pipe);
183 }
184 if (stderr_pipe != -1) {
185 close(stderr_pipe);
186 }
187 }
188 RETURN_IF_ERROR(status);
189
190 mx_handle_t p = launchpad_start(lp);
191 launchpad_destroy(lp);
192 if (p < 0) {
193 close(stdout_pipe);
194 close(stderr_pipe);
195 }
196 RETURN_IF_ERROR(p);
197
198 if (stdout_out != NULL) {
199 *stdout_out = stdout_pipe;
200 } else {
201 close(stdout_pipe);
202 }
203 if (stderr_out != NULL) {
204 *stderr_out = stderr_pipe;
205 } else {
206 close(stderr_pipe);
207 }
208 return p;
209 }
210
211
212 // Drain fd into a buffer pointed to by 'buffer'. Assumes that the data is a
213 // C string, and null-terminates it. Returns the number of bytes read.
214 static intptr_t drain_fd(int fd, char** buffer) {
215 const intptr_t kDrainInitSize = 64;
216 char* buf = reinterpret_cast<char*>(malloc(kDrainInitSize));
217 intptr_t free_space = kDrainInitSize;
218 intptr_t total_read = 0;
219 intptr_t read_size = 0;
220 while ((read_size = read(fd, buf + total_read, free_space)) != 0) {
221 if (read_size == -1) {
222 break;
223 }
224 total_read += read_size;
225 free_space -= read_size;
226 if (free_space <= 1) {
227 // new_size = size * 1.5.
228 intptr_t new_size = (total_read << 1) - (total_read >> 1);
229 buf = reinterpret_cast<char*>(realloc(buf, new_size));
230 free_space = new_size - total_read;
231 }
232 }
233 buf[total_read] = '\0';
234 close(fd);
235 *buffer = buf;
236 return total_read;
237 }
238
239
240 // Runs test 'test_name' and gives stdout and stderr for the test in
241 // 'test_stdout' and 'test_stderr'. Returns the exit code from the test.
242 static int run_test(mx_handle_t binary_vmo,
243 const char* test_name,
244 char** test_stdout,
245 char** test_stderr) {
246 int stdout_pipe = -1;
247 int stderr_pipe = -1;
248 mx_handle_t p = start_test(binary_vmo, test_name, &stdout_pipe, &stderr_pipe);
249 RETURN_IF_ERROR(p);
250
251 drain_fd(stdout_pipe, test_stdout);
252 drain_fd(stderr_pipe, test_stderr);
253
254 mx_status_t r =
255 mx_object_wait_one(p, MX_PROCESS_SIGNALED, MX_TIME_INFINITE, NULL);
256 RETURN_IF_ERROR(r);
257
258 mx_info_process_t proc_info;
259 mx_status_t status = mx_object_get_info(p, MX_INFO_PROCESS, &proc_info,
260 sizeof(proc_info), nullptr, nullptr);
261 RETURN_IF_ERROR(status);
262
263 r = mx_handle_close(p);
264 RETURN_IF_ERROR(r);
265 return proc_info.return_code;
266 }
267
268
269 static void handle_result(intptr_t result,
270 char* test_stdout,
271 char* test_stderr,
272 const char* test) {
273 if (result != 0) {
274 if (!isExpectFail(test) && !isBug(test)) {
275 printf("**** Test %s FAILED\n\nstdout:\n%s\nstderr:\n%s\n", test,
276 test_stdout, test_stderr);
277 } else {
278 printf("Test %s FAILED and is expected to fail\n", test);
279 }
280 } else {
281 if (isExpectFail(test)) {
282 printf(
283 "**** Test %s is expected to fail, but PASSED\n\n"
284 "stdout:\n%s\nstderr:\n%s\n",
285 test, test_stdout, test_stderr);
286 } else if (isBug(test)) {
287 printf("**** Test %s is marked as a bug, but PASSED\n", test);
288 } else {
289 printf("Test %s PASSED\n", test);
290 }
291 }
292 }
293
294
295 typedef struct {
296 pthread_mutex_t* test_list_lock;
297 char** test_list;
298 intptr_t test_list_length;
299 intptr_t* test_list_index;
300 mx_handle_t binary_vmo;
301 } runner_args_t;
302
303
304 static void* test_runner_thread(void* arg) {
305 runner_args_t* args = reinterpret_cast<runner_args_t*>(arg);
306
307 pthread_mutex_lock(args->test_list_lock);
308 mx_handle_t binary_vmo = args->binary_vmo;
309 while (*args->test_list_index < args->test_list_length) {
310 const intptr_t index = *args->test_list_index;
311 *args->test_list_index = index + 1;
312 pthread_mutex_unlock(args->test_list_lock);
313
314 const char* test = args->test_list[index];
315 char* test_stdout = NULL;
316 char* test_stderr = NULL;
317 mx_handle_t vmo_dup = MX_HANDLE_INVALID;
318 mx_handle_duplicate(binary_vmo, MX_RIGHT_SAME_RIGHTS, &vmo_dup);
319 int test_status = run_test(vmo_dup, test, &test_stdout, &test_stderr);
320 handle_result(test_status, test_stdout, test_stderr, test);
321 free(test_stdout);
322 free(test_stderr);
323 pthread_mutex_lock(args->test_list_lock);
324 }
325 pthread_mutex_unlock(args->test_list_lock);
326
327 return NULL;
328 }
329
330
331 static void run_all_tests(runner_args_t* args) {
332 const intptr_t num_cpus = sysconf(_SC_NPROCESSORS_CONF);
333 pthread_t* threads =
334 reinterpret_cast<pthread_t*>(malloc(num_cpus * sizeof(pthread_t)));
335 for (int i = 0; i < num_cpus; i++) {
336 pthread_create(&threads[i], NULL, test_runner_thread, args);
337 }
338 for (int i = 0; i < num_cpus; i++) {
339 pthread_join(threads[i], NULL);
340 }
341 free(threads);
342 }
343
344
345 static bool should_run(const char* test) {
346 return !(test[0] == '#') && !isSkip(test);
347 }
348
349
350 static char** parse_test_list(char* list_output, intptr_t* length) {
351 const intptr_t list_output_length = strlen(list_output);
352 intptr_t test_count = 0;
353 for (int i = 0; i < list_output_length; i++) {
354 if (list_output[i] == '\n') {
355 test_count++;
356 }
357 }
358 char** test_list;
359 test_list = reinterpret_cast<char**>(malloc(test_count * sizeof(*test_list)));
360 char* test = list_output;
361 char* strtok_context;
362 intptr_t idx = 0;
363 while ((test = strtok_r(test, "\n", &strtok_context)) != NULL) {
364 if (should_run(test)) {
365 test_list[idx] = strdup(test);
366 idx++;
367 }
368 test = NULL;
369 }
370
371 *length = idx;
372 return test_list;
373 }
374
375
376 int main(int argc, char** argv) {
377 // TODO(zra): Read test binary path from the command line.
378
379 // Load in the binary.
380 mx_handle_t binary_vmo = launchpad_vmo_from_file(kRunVmTestsPath);
381 RETURN_IF_ERROR(binary_vmo);
382
383 // Run with --list to grab the list of tests.
384 char* list_stdout = NULL;
385 char* list_stderr = NULL;
386 mx_handle_t list_vmo = MX_HANDLE_INVALID;
387 mx_status_t status =
388 mx_handle_duplicate(binary_vmo, MX_RIGHT_SAME_RIGHTS, &list_vmo);
389 RETURN_IF_ERROR(status);
390 int list_result = run_test(list_vmo, "--list", &list_stdout, &list_stderr);
391 if (list_result != 0) {
392 fprintf(stderr, "Failed to list tests: %s\n%s\n", list_stdout, list_stderr);
393 fflush(0);
394 free(list_stdout);
395 free(list_stderr);
396 return list_result;
397 }
398
399 // Parse the test list into an array of C strings.
400 intptr_t lines_count;
401 char** test_list = parse_test_list(list_stdout, &lines_count);
402 free(list_stdout);
403 free(list_stderr);
404
405 fprintf(stdout, "Found %ld tests\n", lines_count);
406 fflush(0);
407
408 // Run the tests across a number of threads equal to the number of cores.
409 pthread_mutex_t args_mutex;
410 pthread_mutex_init(&args_mutex, NULL);
411 intptr_t test_list_index = 0;
412 runner_args_t args;
413 args.test_list_lock = &args_mutex;
414 args.test_list = test_list;
415 args.test_list_length = lines_count;
416 args.test_list_index = &test_list_index;
417 args.binary_vmo = binary_vmo;
418 run_all_tests(&args);
419
420 // Cleanup.
421 for (int i = 0; i < lines_count; i++) {
422 free(test_list[i]);
423 }
424 free(test_list);
425 pthread_mutex_destroy(&args_mutex);
426 status = mx_handle_close(binary_vmo);
427 RETURN_IF_ERROR(status);
428
429 // Complain if we didn't try to run all of the tests.
430 if (test_list_index != lines_count) {
431 fprintf(stderr, "Failed to attempt all the tests!\n");
432 fflush(0);
433 return -1;
434 }
435 return 0;
436 }
OLDNEW
« no previous file with comments | « runtime/bin/BUILD.gn ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698