| // Copyright (c) 2012, 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 "bin/console.h" |
| #include "bin/dartutils.h" |
| #include "bin/dfe.h" |
| #include "bin/eventhandler.h" |
| #include "bin/file.h" |
| #include "bin/loader.h" |
| #include "bin/platform.h" |
| #include "bin/snapshot_utils.h" |
| #include "bin/thread.h" |
| #include "bin/utils.h" |
| #include "platform/assert.h" |
| #include "vm/benchmark_test.h" |
| #include "vm/dart.h" |
| #include "vm/unit_test.h" |
| |
| extern "C" { |
| extern const uint8_t kDartVmSnapshotData[]; |
| extern const uint8_t kDartVmSnapshotInstructions[]; |
| extern const uint8_t kDartCoreIsolateSnapshotData[]; |
| extern const uint8_t kDartCoreIsolateSnapshotInstructions[]; |
| } |
| |
| // TODO(iposva, asiva): This is a placeholder for the real unittest framework. |
| namespace dart { |
| |
| // Defined in vm/os_thread_win.cc |
| extern bool private_flag_windows_run_tls_destructors; |
| |
| // Snapshot pieces when we link in a snapshot. |
| #if defined(DART_NO_SNAPSHOT) |
| #error "run_vm_tests must be built with a snapshot" |
| #else |
| const uint8_t* bin::vm_snapshot_data = kDartVmSnapshotData; |
| const uint8_t* bin::vm_snapshot_instructions = kDartVmSnapshotInstructions; |
| const uint8_t* bin::core_isolate_snapshot_data = kDartCoreIsolateSnapshotData; |
| const uint8_t* bin::core_isolate_snapshot_instructions = |
| kDartCoreIsolateSnapshotInstructions; |
| #endif |
| |
| // Only run tests that match the filter string. The default does not match any |
| // tests. |
| static const char* const kNone = "No Test or Benchmarks"; |
| static const char* const kList = "List all Tests and Benchmarks"; |
| static const char* const kAllBenchmarks = "All Benchmarks"; |
| static const char* run_filter = kNone; |
| static const char* kernel_snapshot = NULL; |
| |
| static int run_matches = 0; |
| |
| void TestCase::Run() { |
| bin::Log::Print("Running test: %s\n", name()); |
| (*run_)(); |
| bin::Log::Print("Done: %s\n", name()); |
| } |
| |
| void RawTestCase::Run() { |
| bin::Log::Print("Running raw test: %s\n", name()); |
| (*run_)(); |
| bin::Log::Print("Done: %s\n", name()); |
| } |
| |
| void TestCaseBase::RunTest() { |
| if (strcmp(run_filter, this->name()) == 0) { |
| this->Run(); |
| run_matches++; |
| } else if (run_filter == kList) { |
| bin::Log::Print("%s\n", this->name()); |
| run_matches++; |
| } |
| } |
| |
| void Benchmark::RunBenchmark() { |
| if ((run_filter == kAllBenchmarks) || |
| (strcmp(run_filter, this->name()) == 0)) { |
| this->Run(); |
| bin::Log::Print("%s(%s): %" Pd64 "\n", this->name(), this->score_kind(), |
| this->score()); |
| run_matches++; |
| } else if (run_filter == kList) { |
| bin::Log::Print("%s\n", this->name()); |
| run_matches++; |
| } |
| } |
| |
| static void PrintUsage() { |
| bin::Log::PrintErr( |
| "Usage: one of the following\n" |
| " run_vm_tests --list\n" |
| " run_vm_tests [--dfe=<snapshot file name>] --benchmarks\n" |
| " run_vm_tests [--dfe=<snapshot file name>] [vm-flags ...] <test name>\n" |
| " run_vm_tests [--dfe=<snapshot file name>] [vm-flags ...] <benchmark " |
| "name>\n"); |
| } |
| |
| #define CHECK_RESULT(result) \ |
| if (Dart_IsError(result)) { \ |
| *error = strdup(Dart_GetError(result)); \ |
| Dart_ExitScope(); \ |
| Dart_ShutdownIsolate(); \ |
| return NULL; \ |
| } |
| |
| static Dart_Isolate CreateIsolateAndSetup(const char* script_uri, |
| const char* main, |
| const char* package_root, |
| const char* packages_config, |
| Dart_IsolateFlags* flags, |
| void* data, |
| char** error) { |
| ASSERT(script_uri != NULL); |
| const bool is_service_isolate = |
| strcmp(script_uri, DART_VM_SERVICE_ISOLATE_NAME) == 0; |
| if (is_service_isolate) { |
| // We don't need service isolate for VM tests. |
| return NULL; |
| } |
| const bool is_kernel_isolate = |
| strcmp(script_uri, DART_KERNEL_ISOLATE_NAME) == 0; |
| if (!is_kernel_isolate) { |
| *error = |
| strdup("Spawning of only Kernel isolate is supported in run_vm_tests."); |
| return NULL; |
| } |
| Dart_Isolate isolate = NULL; |
| bin::IsolateData* isolate_data = NULL; |
| const uint8_t* kernel_service_buffer = NULL; |
| intptr_t kernel_service_buffer_size = 0; |
| |
| // Kernel isolate uses an app snapshot or the kernel service dill file. |
| if (kernel_snapshot != NULL && |
| (bin::DartUtils::SniffForMagicNumber(kernel_snapshot) == |
| bin::DartUtils::kAppJITMagicNumber)) { |
| script_uri = kernel_snapshot; |
| bin::AppSnapshot* app_snapshot = |
| bin::Snapshot::TryReadAppSnapshot(script_uri); |
| ASSERT(app_snapshot != NULL); |
| const uint8_t* ignore_vm_snapshot_data; |
| const uint8_t* ignore_vm_snapshot_instructions; |
| const uint8_t* isolate_snapshot_data; |
| const uint8_t* isolate_snapshot_instructions; |
| app_snapshot->SetBuffers( |
| &ignore_vm_snapshot_data, &ignore_vm_snapshot_instructions, |
| &isolate_snapshot_data, &isolate_snapshot_instructions); |
| isolate_data = new bin::IsolateData(script_uri, package_root, |
| packages_config, app_snapshot); |
| isolate = Dart_CreateIsolate( |
| DART_KERNEL_ISOLATE_NAME, main, isolate_snapshot_data, |
| isolate_snapshot_instructions, NULL, NULL, flags, isolate_data, error); |
| if (*error != NULL) { |
| free(*error); |
| *error = NULL; |
| } |
| } |
| if (isolate == NULL) { |
| delete isolate_data; |
| isolate_data = NULL; |
| |
| bin::dfe.Init(); |
| bin::dfe.LoadKernelService(&kernel_service_buffer, |
| &kernel_service_buffer_size); |
| ASSERT(kernel_service_buffer != NULL); |
| isolate_data = |
| new bin::IsolateData(script_uri, package_root, packages_config, NULL); |
| isolate_data->set_kernel_buffer(const_cast<uint8_t*>(kernel_service_buffer), |
| kernel_service_buffer_size, |
| false /* take_ownership */); |
| isolate = Dart_CreateIsolateFromKernel( |
| script_uri, main, kernel_service_buffer, kernel_service_buffer_size, |
| flags, isolate_data, error); |
| } |
| if (isolate == NULL) { |
| delete isolate_data; |
| return NULL; |
| } |
| |
| Dart_EnterScope(); |
| |
| bin::DartUtils::SetOriginalWorkingDirectory(); |
| Dart_Handle result = bin::DartUtils::PrepareForScriptLoading( |
| false /* is_service_isolate */, false /* trace_loading */); |
| CHECK_RESULT(result); |
| |
| // Setup kernel service as the main script for this isolate. |
| if (kernel_service_buffer) { |
| result = Dart_LoadScriptFromKernel(kernel_service_buffer, |
| kernel_service_buffer_size); |
| CHECK_RESULT(result); |
| } |
| |
| Dart_ExitScope(); |
| Dart_ExitIsolate(); |
| *error = Dart_IsolateMakeRunnable(isolate); |
| if (*error != NULL) { |
| Dart_EnterIsolate(isolate); |
| Dart_ShutdownIsolate(); |
| return NULL; |
| } |
| |
| return isolate; |
| } |
| |
| static void CleanupIsolate(void* callback_data) { |
| bin::IsolateData* isolate_data = |
| reinterpret_cast<bin::IsolateData*>(callback_data); |
| delete isolate_data; |
| } |
| |
| static int Main(int argc, const char** argv) { |
| // Flags being passed to the Dart VM. |
| int dart_argc = 0; |
| const char** dart_argv = NULL; |
| |
| // Perform platform specific initialization. |
| if (!dart::bin::Platform::Initialize()) { |
| bin::Log::PrintErr("Initialization failed\n"); |
| return 1; |
| } |
| |
| // Save the console state so we can restore it later. |
| dart::bin::Console::SaveConfig(); |
| |
| // Store the executable name. |
| dart::bin::Platform::SetExecutableName(argv[0]); |
| |
| if (argc < 2) { |
| // Bad parameter count. |
| PrintUsage(); |
| return 1; |
| } |
| |
| if (argc == 2 && strcmp(argv[1], "--list") == 0) { |
| run_filter = kList; |
| // List all tests and benchmarks and exit without initializing the VM. |
| TestCaseBase::RunAll(); |
| Benchmark::RunAll(argv[0]); |
| TestCaseBase::RunAllRaw(); |
| fflush(stdout); |
| return 0; |
| } |
| |
| int arg_pos = 1; |
| bool start_kernel_isolate = false; |
| if (strstr(argv[arg_pos], "--dfe") == argv[arg_pos]) { |
| const char* delim = strstr(argv[arg_pos], "="); |
| if (delim == NULL || strlen(delim + 1) == 0) { |
| bin::Log::PrintErr("Invalid value for the option: %s\n", argv[arg_pos]); |
| PrintUsage(); |
| return 1; |
| } |
| kernel_snapshot = strdup(delim + 1); |
| // Remove this flag from the list by shifting all arguments down. |
| for (intptr_t i = arg_pos; i < argc - 1; i++) { |
| argv[i] = argv[i + 1]; |
| } |
| argv[argc - 1] = nullptr; |
| argc--; |
| start_kernel_isolate = true; |
| } |
| |
| if (arg_pos == argc - 1 && strcmp(argv[arg_pos], "--benchmarks") == 0) { |
| // "--benchmarks" is the last argument. |
| run_filter = kAllBenchmarks; |
| } else { |
| // Last argument is the test name, the rest are vm flags. |
| run_filter = argv[argc - 1]; |
| // Remove the first value (executable) from the arguments and |
| // exclude the last argument which is the test name. |
| dart_argc = argc - 2; |
| dart_argv = &argv[1]; |
| } |
| |
| bin::Thread::InitOnce(); |
| bin::TimerUtils::InitOnce(); |
| bin::EventHandler::Start(); |
| |
| char* error = Flags::ProcessCommandLineFlags(dart_argc, dart_argv); |
| if (error != NULL) { |
| bin::Log::PrintErr("Failed to parse flags: %s\n", error); |
| free(error); |
| return 1; |
| } |
| |
| TesterState::vm_snapshot_data = dart::bin::vm_snapshot_data; |
| TesterState::create_callback = CreateIsolateAndSetup; |
| TesterState::cleanup_callback = CleanupIsolate; |
| TesterState::argv = dart_argv; |
| TesterState::argc = dart_argc; |
| |
| error = Dart::Init( |
| dart::bin::vm_snapshot_data, dart::bin::vm_snapshot_instructions, |
| CreateIsolateAndSetup /* create */, nullptr /* shutdown */, |
| CleanupIsolate /* cleanup */, nullptr /* thread_exit */, |
| dart::bin::DartUtils::OpenFile, dart::bin::DartUtils::ReadFile, |
| dart::bin::DartUtils::WriteFile, dart::bin::DartUtils::CloseFile, |
| nullptr /* entropy_source */, nullptr /* get_service_assets */, |
| start_kernel_isolate); |
| if (error != nullptr) { |
| bin::Log::PrintErr("Failed to initialize VM: %s\n", error); |
| free(error); |
| return 1; |
| } |
| |
| // Apply the filter to all registered tests. |
| TestCaseBase::RunAll(); |
| // Apply the filter to all registered benchmarks. |
| Benchmark::RunAll(argv[0]); |
| |
| error = Dart::Cleanup(); |
| if (error != nullptr) { |
| bin::Log::PrintErr("Failed shutdown VM: %s\n", error); |
| free(error); |
| return 1; |
| } |
| |
| TestCaseBase::RunAllRaw(); |
| |
| bin::EventHandler::Stop(); |
| |
| // Print a warning message if no tests or benchmarks were matched. |
| if (run_matches == 0) { |
| bin::Log::PrintErr("No tests matched: %s\n", run_filter); |
| return 1; |
| } |
| if (Expect::failed()) { |
| return 255; |
| } |
| return 0; |
| } |
| |
| } // namespace dart |
| |
| int main(int argc, const char** argv) { |
| dart::bin::Platform::Exit(dart::Main(argc, argv)); |
| } |