blob: 3e7430a7b8f890c6c3740a0c275fd5409c4619da [file] [log] [blame]
// 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",
// Hangs.
"ArrayLengthMaxElements",
"Int8ListLengthMaxElements",
"ThreadPool_WorkerShutdown",
"LargeMap",
"CompileFunctionOnHelperThread",
// Kernel panic.
"ThreadBarrier",
// 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;
}