// 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/crashpad.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 "bin/vmservice_impl.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 {

// 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 = nullptr;

static int run_matches = 0;

void TestCase::Run() {
  Syslog::Print("Running test: %s\n", name());
  (*run_)();
  Syslog::Print("Done: %s\n", name());
}

void RawTestCase::Run() {
  Syslog::Print("Running raw test: %s\n", name());
  (*run_)();
  Syslog::Print("Done: %s\n", name());
}

void TestCaseBase::RunTest() {
  if (strcmp(run_filter, this->name()) == 0) {
    this->Run();
    run_matches++;
  } else if (run_filter == kList) {
    Syslog::Print("%s %s\n", this->name(), this->expectation());
    run_matches++;
  }
}

void Benchmark::RunBenchmark() {
  if ((run_filter == kAllBenchmarks) ||
      (strcmp(run_filter, this->name()) == 0)) {
    this->Run();
    Syslog::Print("%s(%s): %" Pd64 "\n", this->name(), this->score_kind(),
                  this->score());
    run_matches++;
  } else if (run_filter == kList) {
    Syslog::Print("%s Pass\n", this->name());
    run_matches++;
  }
}

static void PrintUsage() {
  Syslog::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 nullptr;                                                            \
  }

static Dart_Isolate CreateAndSetupServiceIsolate(const char* script_uri,
                                                 const char* package_root,
                                                 const char* packages_config,
                                                 Dart_IsolateFlags* flags,
                                                 char** error) {
  // We only enable the vm-service for this particular test.
  // The vm-service seems to have some shutdown race which would cause other
  // vm/cc tests to randomly time out due to inability to shut service-isolate
  // down.
  // Issue(https://dartbug.com/37741):
  if (strcmp(run_filter, "DartAPI_InvokeVMServiceMethod") != 0) {
    return nullptr;
  }

  ASSERT(script_uri != nullptr);
  Dart_Isolate isolate = nullptr;
  auto isolate_group_data = new bin::IsolateGroupData(
      script_uri, package_root, packages_config, /*app_snapshot=*/nullptr,
      /*isolate_run_app_snapshot=*/false);

  const uint8_t* kernel_buffer = nullptr;
  intptr_t kernel_buffer_size = 0;

  bin::dfe.Init();
  bin::dfe.LoadPlatform(&kernel_buffer, &kernel_buffer_size);
  RELEASE_ASSERT(kernel_buffer != nullptr);

  flags->load_vmservice_library = true;
  isolate_group_data->SetKernelBufferUnowned(
      const_cast<uint8_t*>(kernel_buffer), kernel_buffer_size);
  isolate = Dart_CreateIsolateGroupFromKernel(
      script_uri, DART_VM_SERVICE_ISOLATE_NAME, kernel_buffer,
      kernel_buffer_size, flags, isolate_group_data, /*isolate_data=*/nullptr,
      error);
  if (isolate == nullptr) {
    delete isolate_group_data;
    return nullptr;
  }

  Dart_EnterScope();

  Dart_Handle result =
      Dart_SetLibraryTagHandler(bin::Loader::LibraryTagHandler);
  CHECK_RESULT(result);

  // Load embedder specific bits and return.
  if (!bin::VmService::Setup("127.0.0.1", 0,
                             /*dev_mode=*/false, /*auth_disabled=*/true,
                             /*write_service_info_filename*/ "",
                             /*trace_loading=*/false, /*deterministic=*/true)) {
    *error = strdup(bin::VmService::GetErrorMessage());
    return nullptr;
  }
  result = Dart_SetEnvironmentCallback(bin::DartUtils::EnvironmentCallback);
  CHECK_RESULT(result);
  Dart_ExitScope();
  Dart_ExitIsolate();
  return isolate;
}

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 != nullptr);
  if (strcmp(script_uri, DART_VM_SERVICE_ISOLATE_NAME) == 0) {
    return CreateAndSetupServiceIsolate(script_uri, package_root,
                                        packages_config, flags, error);
  }
  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 nullptr;
  }
  Dart_Isolate isolate = nullptr;
  bin::IsolateGroupData* isolate_group_data = nullptr;
  const uint8_t* kernel_service_buffer = nullptr;
  intptr_t kernel_service_buffer_size = 0;

  // Kernel isolate uses an app snapshot or the kernel service dill file.
  if (kernel_snapshot != nullptr &&
      (bin::DartUtils::SniffForMagicNumber(kernel_snapshot) ==
       bin::DartUtils::kAppJITMagicNumber)) {
    script_uri = kernel_snapshot;
    bin::AppSnapshot* app_snapshot =
        bin::Snapshot::TryReadAppSnapshot(script_uri);
    ASSERT(app_snapshot != nullptr);
    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_group_data =
        new bin::IsolateGroupData(script_uri, package_root, packages_config,
                                  app_snapshot, app_snapshot != nullptr);
    isolate = Dart_CreateIsolateGroup(
        DART_KERNEL_ISOLATE_NAME, DART_KERNEL_ISOLATE_NAME,
        isolate_snapshot_data, isolate_snapshot_instructions,
        /*shared_data=*/nullptr, /*shared_instructions=*/nullptr, flags,
        isolate_group_data, /*isolate_data=*/nullptr, error);
    if (*error != nullptr) {
      OS::PrintErr("Error creating isolate group: %s\n", *error);
      free(*error);
      *error = nullptr;
    }
    // If a test does not actually require the kernel isolate the main thead can
    // start calling Dart::Cleanup() while the kernel isolate is booting up.
    // This can cause the isolate to be killed early which will return `nullptr`
    // here.
    if (isolate == nullptr) {
      delete isolate_group_data;
      return nullptr;
    }
  }
  if (isolate == nullptr) {
    delete isolate_group_data;
    isolate_group_data = nullptr;

    bin::dfe.Init();
    bin::dfe.LoadKernelService(&kernel_service_buffer,
                               &kernel_service_buffer_size);
    ASSERT(kernel_service_buffer != nullptr);
    isolate_group_data = new bin::IsolateGroupData(
        script_uri, package_root, packages_config, nullptr, false);
    isolate_group_data->SetKernelBufferUnowned(
        const_cast<uint8_t*>(kernel_service_buffer),
        kernel_service_buffer_size);
    isolate = Dart_CreateIsolateGroupFromKernel(
        script_uri, main, kernel_service_buffer, kernel_service_buffer_size,
        flags, isolate_group_data, /*isolate_data=*/nullptr, error);
  }
  if (isolate == nullptr) {
    delete isolate_group_data;
    return nullptr;
  }

  Dart_EnterScope();

  bin::DartUtils::SetOriginalWorkingDirectory();
  Dart_Handle result = bin::DartUtils::PrepareForScriptLoading(
      /*is_service_isolate=*/false, /*trace_loading=*/false);
  CHECK_RESULT(result);

  // Setup kernel service as the main script for this isolate.
  if (kernel_service_buffer != nullptr) {
    result = Dart_LoadScriptFromKernel(kernel_service_buffer,
                                       kernel_service_buffer_size);
    CHECK_RESULT(result);
  }

  Dart_ExitScope();
  Dart_ExitIsolate();
  *error = Dart_IsolateMakeRunnable(isolate);
  if (*error != nullptr) {
    Dart_EnterIsolate(isolate);
    Dart_ShutdownIsolate();
    return nullptr;
  }

  return isolate;
}

static void CleanupIsolateGroup(void* callback_data) {
  bin::IsolateGroupData* isolate_data =
      reinterpret_cast<bin::IsolateGroupData*>(callback_data);
  delete isolate_data;
}

void ShiftArgs(int* argc, const char** argv) {
  // Remove the first flag from the list by shifting all arguments down.
  for (intptr_t i = 1; i < *argc - 1; i++) {
    argv[i] = argv[i + 1];
  }
  argv[*argc - 1] = nullptr;
  (*argc)--;
}

static int Main(int argc, const char** argv) {
  // Flags being passed to the Dart VM.
  int dart_argc = 0;
  const char** dart_argv = nullptr;

  // Perform platform specific initialization.
  if (!dart::bin::Platform::Initialize()) {
    Syslog::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;
  bool suppress_core_dump = false;
  if (strcmp(argv[arg_pos], "--suppress-core-dump") == 0) {
    suppress_core_dump = true;
    ShiftArgs(&argc, argv);
  }

  if (suppress_core_dump) {
    bin::Platform::SetCoreDumpResourceLimit(0);
  } else {
    bin::InitializeCrashpadClient();
  }

  if (strncmp(argv[arg_pos], "--dfe", strlen("--dfe")) == 0) {
    const char* delim = strstr(argv[arg_pos], "=");
    if (delim == nullptr || strlen(delim + 1) == 0) {
      Syslog::PrintErr("Invalid value for the option: %s\n", argv[arg_pos]);
      PrintUsage();
      return 1;
    }
    kernel_snapshot = strdup(delim + 1);
    start_kernel_isolate = true;
    ShiftArgs(&argc, argv);
  }

  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::TimerUtils::InitOnce();
  bin::EventHandler::Start();

  char* error = Flags::ProcessCommandLineFlags(dart_argc, dart_argv);
  if (error != nullptr) {
    Syslog::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::group_cleanup_callback = CleanupIsolateGroup;
  TesterState::argv = dart_argv;
  TesterState::argc = dart_argc;

  error = Dart::Init(
      dart::bin::vm_snapshot_data, dart::bin::vm_snapshot_instructions,
      /*create_group=*/CreateIsolateAndSetup,
      /*initialize_isolate=*/nullptr,
      /*shutdown_isolate=*/nullptr,
      /*cleanup_isolate=*/nullptr,
      /*cleanup_group=*/CleanupIsolateGroup,
      /*thread_exit=*/nullptr, dart::bin::DartUtils::OpenFile,
      dart::bin::DartUtils::ReadFile, dart::bin::DartUtils::WriteFile,
      dart::bin::DartUtils::CloseFile, /*entropy_source=*/nullptr,
      /*get_service_assets=*/nullptr, start_kernel_isolate,
      /*code_observer=*/nullptr);
  if (error != nullptr) {
    Syslog::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) {
    Syslog::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) {
    Syslog::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));
}
