Index: runtime/bin/run_vm_tests_fuchsia.cc |
diff --git a/runtime/bin/run_vm_tests_fuchsia.cc b/runtime/bin/run_vm_tests_fuchsia.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..a860822432763a3307a520ab1ca4b78606ee9541 |
--- /dev/null |
+++ b/runtime/bin/run_vm_tests_fuchsia.cc |
@@ -0,0 +1,255 @@ |
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
+// for details. All rights reserved. Use of this source code is governed by a |
+// BSD-style license that can be found in the LICENSE file. |
+ |
+#include <fcntl.h> |
+#include <magenta/syscalls.h> |
+#include <mxio/util.h> |
+#include <stdbool.h> |
+#include <stdio.h> |
+#include <stdlib.h> |
+#include <string.h> |
+#include <unistd.h> |
+ |
+// This program runs Dart VM unit tests. The Dart VM unit tests are contained |
+// in a separate binary whose location is defined in kRunVmTestsPath below. |
+// That program accepts a command line argument --list to list all the available |
+// tests, or the name of a single test to run. This program accepts a single |
+// command line argument which is the path to a file containing a list of tests |
+// to run, one per line. |
+ |
+const char* kRunVmTestsPath = "/boot/bin/dart_vm_tests"; |
+ |
+// Tests that are invalid, wedge, or cause panics. |
+const char* kSkip[] = { |
+ // These expect a file to exist that we aren't putting in the image. |
+ "Read", |
+ "FileLength", |
+ "FilePosition", |
+ // Wedges the system. |
+ "ArrayLengthMaxElements", |
+ "Int8ListLengthMaxElements", |
+ // Kernel panic. |
+ "ThreadBarrier", |
+ // Wedges. |
+ "ThreadPool_WorkerShutdown", |
+ "LargeMap", |
+ // The profiler is turned off. |
+ "Profiler_AllocationSampleTest", |
+ "Profiler_ArrayAllocation", |
+ "Profiler_BasicSourcePosition", |
+ "Profiler_BasicSourcePositionOptimized", |
+ "Profiler_BinaryOperatorSourcePosition", |
+ "Profiler_BinaryOperatorSourcePositionOptimized", |
+ "Profiler_ChainedSamples", |
+ "Profiler_ClosureAllocation", |
+ "Profiler_CodeTicks", |
+ "Profiler_ContextAllocation", |
+ "Profiler_FunctionInline", |
+ "Profiler_FunctionTicks", |
+ "Profiler_InliningIntervalBoundry", |
+ "Profiler_IntrinsicAllocation", |
+ "Profiler_SampleBufferIterateTest", |
+ "Profiler_SampleBufferWrapTest", |
+ "Profiler_SourcePosition", |
+ "Profiler_SourcePositionOptimized", |
+ "Profiler_StringAllocation", |
+ "Profiler_StringInterpolation", |
+ "Profiler_ToggleRecordAllocation", |
+ "Profiler_TrivialRecordAllocation", |
+ "Profiler_TypedArrayAllocation", |
+ "Profiler_GetSourceReport", |
+ "Service_Profile", |
+ // No realpath. |
+ "Dart2JSCompilerStats", |
+ "Dart2JSCompileAll", |
+}; |
+ |
+// Expected to fail/crash. |
+const char* kExpectFail[] = { |
+ "Fail0", |
+ "Fail1", |
+ "Fail2", |
+ "IsolateReload_PendingUnqualifiedCall_InstanceToStatic", |
+ "IsolateReload_PendingUnqualifiedCall_StaticToInstance", |
+ "IsolateReload_PendingConstructorCall_AbstractToConcrete", |
+ "IsolateReload_PendingConstructorCall_ConcreteToAbstract", |
+ "IsolateReload_PendingStaticCall_DefinedToNSM", |
+ "IsolateReload_PendingStaticCall_NSMToDefined", |
+ "ArrayNew_Overflow_Crash", |
+ "AllocGeneric_Overflow", |
+ "CodeImmutability", |
+ "SNPrint_BadArgs", |
+}; |
+ |
+// Bugs to fix, or things that are not yet impelemnted. |
+const char* kBugs[] = { |
+ // pthreads not using specified stack size. |
+ "StackOverflowStacktraceInfo", |
+ // Needs OS::GetCurrentThreadCPUMicros. |
+ "Timeline_Dart_TimelineDuration", |
+ "Timeline_Dart_TimelineInstant" |
+ "Timeline_Dart_TimelineAsyncDisabled", |
+ "Timeline_Dart_TimelineAsync", |
+ "Timeline_Dart_TimelineGetTrace", |
+ "Timeline_Dart_TimelineGetTraceOnlyDartEvents", |
+ "Timeline_Dart_TimelineGetTraceWithDartEvents", |
+ "Timeline_Dart_TimelineGetTraceGlobalOverride", |
+ "Timeline_Dart_GlobalTimelineGetTrace", |
+ "Timeline_Dart_GlobalTimelineGetTrace_Threaded", |
+ "TimelineEventDuration", |
+ "TimelineEventDurationPrintJSON", |
+ "TimelineEventArguments", |
+ "TimelineEventArgumentsPrintJSON", |
+ "TimelineEventBufferPrintJSON", |
+ "TimelineEventCallbackRecorderBasic", |
+ "TimelineAnalysis_ThreadBlockCount", |
+ "TimelineRingRecorderJSONOrder", |
+ "TimelinePauses_BeginEnd", |
+ // Crash. |
+ "FindCodeObject", |
+ // Needs OS::Sleep. |
+ "MessageHandler_Run", |
+ "Sleep", |
+ // Calls VirtualMemory::FreeSubSegment. |
+ "GrowableObjectArray", |
+ "PrintJSON", |
+ "GenerateSource", |
+ "FreeVirtualMemory", |
+ // Several missing calls. |
+ "OsFuncs", |
+ // OS::AlignedAllocate. |
+ "OSAlignedAllocate", |
+ // Needs NativeSymbolResolver |
+ "Service_PersistentHandles", |
+ // Need to investigate: |
+ "ThreadPool_RunOne", |
+ "ThreadPool_WorkerTimeout", |
+ "Monitor", |
+ "ThreadIterator_AddFindRemove", |
+ // Needs Utils::HostToBigEndian16 |
+ "Endianity", |
+}; |
+ |
+ |
+static bool contains(const char** list, intptr_t len, const char* str) { |
+ for (intptr_t i = 0; i < len; i++) { |
+ if (strcmp(list[i], str) == 0) { |
+ return true; |
+ } |
+ } |
+ return false; |
+} |
+ |
+ |
+static bool isSkip(const char* test) { |
+ return contains( |
+ kSkip, sizeof(kSkip) / sizeof(kSkip[0]), test); |
+} |
+ |
+ |
+static bool isExpectFail(const char* test) { |
+ return contains( |
+ kExpectFail, sizeof(kExpectFail) / sizeof(kExpectFail[0]), test); |
+} |
+ |
+ |
+static bool isBug(const char* test) { |
+ return contains(kBugs, sizeof(kBugs) / sizeof(kBugs[0]), test); |
+} |
+ |
+ |
+static int run_test(const char* test_name) { |
+ const intptr_t kArgc = 2; |
+ const char* argv[3]; |
+ argv[0] = kRunVmTestsPath; |
+ argv[1] = test_name; |
+ |
+ mx_handle_t p = mxio_start_process(argv[0], kArgc, argv); |
+ if (p < 0) { |
+ printf("process failed to start\n"); |
+ return -1; |
+ } |
+ |
+ mx_signals_state_t state; |
+ mx_status_t r = mx_handle_wait_one( |
+ p, MX_SIGNAL_SIGNALED, MX_TIME_INFINITE, &state); |
+ if (r != NO_ERROR) { |
+ printf("[process(%x): wait failed? %d]\n", p, r); |
+ return -1; |
+ } |
+ |
+ mx_process_info_t proc_info; |
+ mx_ssize_t ret = mx_handle_get_info( |
+ p, MX_INFO_PROCESS, &proc_info, sizeof(proc_info)); |
+ if (ret != sizeof(proc_info)) { |
+ printf("[process(%x): handle_get_info failed? %ld]\n", p, ret); |
+ return -1; |
+ } |
+ |
+ mx_handle_close(p); |
+ return proc_info.return_code; |
+} |
+ |
+ |
+static void trim(char* line) { |
+ const intptr_t line_len = strlen(line); |
+ if (line[line_len - 1] == '\n') { |
+ line[line_len - 1] = '\0'; |
+ } |
+} |
+ |
+ |
+static bool should_run(const char* test) { |
+ return !(test[0] == '#') && !isSkip(test); |
+} |
+ |
+ |
+static void handle_result(intptr_t result, const char* test) { |
+ if (result != 0) { |
+ if (!isExpectFail(test) && !isBug(test)) { |
+ printf("******** Test %s FAILED\n", test); |
+ } |
+ } else { |
+ if (isExpectFail(test)) { |
+ printf("******** Test %s is expected to fail, but PASSED\n", test); |
+ } |
+ if (isBug(test)) { |
+ printf("******** Test %s is marked as a bug, but PASSED\n", test); |
+ } |
+ } |
+} |
+ |
+ |
+int main(int argc, char** argv) { |
+ if (argc <= 1) { |
+ fprintf(stderr, "Pass the path to a file containing the list of tests\n"); |
+ return -1; |
+ } |
+ const char* tests_path = argv[1]; |
+ |
+ FILE* fp = fopen(tests_path, "r"); |
+ if (fp == NULL) { |
+ fprintf(stderr, "Failed to read the file: %s\n", tests_path); |
+ return -1; |
+ } |
+ |
+ char* test = NULL; |
+ size_t len = 0; |
+ ssize_t read; |
+ while ((read = getline(&test, &len, fp)) != -1) { |
+ trim(test); |
+ if (!should_run(test)) { |
+ continue; |
+ } |
+ intptr_t result = run_test(test); |
+ handle_result(result, test); |
+ } |
+ |
+ fclose(fp); |
+ if (test != NULL) { |
+ free(test); |
+ } |
+ return 0; |
+} |
+ |