// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/at_exit.h"
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread.h"
#include "crypto/random.h"
#include "mojo/dart/embedder/dart_controller.h"
#include "mojo/dart/embedder/test/dart_to_cpp.mojom.h"
#include "mojo/edk/test/test_utils.h"
#include "mojo/public/cpp/system/core.h"
#include "mojo/public/cpp/system/macros.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace mojo {
namespace dart {

// Global value updated by some checks to prevent compilers from optimizing
// reads out of existence.
uint32 g_waste_accumulator = 0;

namespace {

// Negative numbers with different values in each byte, the last of
// which can survive promotion to double and back.
const int8  kExpectedInt8Value = -65;
const int16 kExpectedInt16Value = -16961;
const int32 kExpectedInt32Value = -1145258561;
const int64 kExpectedInt64Value = -77263311946305LL;

// Positive numbers with different values in each byte, the last of
// which can survive promotion to double and back.
const uint8  kExpectedUInt8Value = 65;
const uint16 kExpectedUInt16Value = 16961;
const uint32 kExpectedUInt32Value = 1145258561;
const uint64 kExpectedUInt64Value = 77263311946305LL;

// Double/float values, including special case constants.
const double kExpectedDoubleVal = 3.14159265358979323846;
const double kExpectedDoubleInf = std::numeric_limits<double>::infinity();
const double kExpectedDoubleNan = std::numeric_limits<double>::quiet_NaN();
const float kExpectedFloatVal = static_cast<float>(kExpectedDoubleVal);
const float kExpectedFloatInf = std::numeric_limits<float>::infinity();
const float kExpectedFloatNan = std::numeric_limits<float>::quiet_NaN();

// NaN has the property that it is not equal to itself.
#define EXPECT_NAN(x) EXPECT_NE(x, x)

void CheckDataPipe(MojoHandle data_pipe_handle) {
  unsigned char buffer[100];
  uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer));
  MojoResult result = MojoReadData(
      data_pipe_handle, buffer, &buffer_size, MOJO_READ_DATA_FLAG_NONE);
  EXPECT_EQ(MOJO_RESULT_OK, result);
  EXPECT_EQ(64u, buffer_size);
  for (int i = 0; i < 64; ++i) {
    EXPECT_EQ(i, buffer[i]);
  }
}

void CheckMessagePipe(MojoHandle message_pipe_handle) {
  unsigned char buffer[100];
  uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer));
  MojoResult result = MojoReadMessage(
      message_pipe_handle, buffer, &buffer_size, 0, 0, 0);
  EXPECT_EQ(MOJO_RESULT_OK, result);
  EXPECT_EQ(64u, buffer_size);
  for (int i = 0; i < 64; ++i) {
    EXPECT_EQ(255 - i, buffer[i]);
  }
}

dart_to_cpp::EchoArgsPtr BuildSampleEchoArgs() {
  dart_to_cpp::EchoArgsPtr args(dart_to_cpp::EchoArgs::New());
  args->si64 = kExpectedInt64Value;
  args->si32 = kExpectedInt32Value;
  args->si16 = kExpectedInt16Value;
  args->si8 = kExpectedInt8Value;
  args->ui64 = kExpectedUInt64Value;
  args->ui32 = kExpectedUInt32Value;
  args->ui16 = kExpectedUInt16Value;
  args->ui8 = kExpectedUInt8Value;
  args->float_val = kExpectedFloatVal;
  args->float_inf = kExpectedFloatInf;
  args->float_nan = kExpectedFloatNan;
  args->double_val = kExpectedDoubleVal;
  args->double_inf = kExpectedDoubleInf;
  args->double_nan = kExpectedDoubleNan;
  args->name = "coming";
  Array<String> string_array(3);
  string_array[0] = "one";
  string_array[1] = "two";
  string_array[2] = "three";
  args->string_array = string_array.Pass();
  return args.Pass();
}

void CheckSampleEchoArgs(const dart_to_cpp::EchoArgs& arg) {
  EXPECT_EQ(kExpectedInt64Value, arg.si64);
  EXPECT_EQ(kExpectedInt32Value, arg.si32);
  EXPECT_EQ(kExpectedInt16Value, arg.si16);
  EXPECT_EQ(kExpectedInt8Value, arg.si8);
  EXPECT_EQ(kExpectedUInt64Value, arg.ui64);
  EXPECT_EQ(kExpectedUInt32Value, arg.ui32);
  EXPECT_EQ(kExpectedUInt16Value, arg.ui16);
  EXPECT_EQ(kExpectedUInt8Value, arg.ui8);
  EXPECT_EQ(kExpectedFloatVal, arg.float_val);
  EXPECT_EQ(kExpectedFloatInf, arg.float_inf);
  EXPECT_NAN(arg.float_nan);
  EXPECT_EQ(kExpectedDoubleVal, arg.double_val);
  EXPECT_EQ(kExpectedDoubleInf, arg.double_inf);
  EXPECT_NAN(arg.double_nan);
  EXPECT_EQ(std::string("coming"), arg.name.get());
  EXPECT_EQ(std::string("one"), arg.string_array[0].get());
  EXPECT_EQ(std::string("two"), arg.string_array[1].get());
  EXPECT_EQ(std::string("three"), arg.string_array[2].get());
  CheckDataPipe(arg.data_handle.get().value());
  CheckMessagePipe(arg.message_handle.get().value());
}

void CheckSampleEchoArgsList(const dart_to_cpp::EchoArgsListPtr& list) {
  if (list.is_null())
    return;
  CheckSampleEchoArgs(*list->item);
  CheckSampleEchoArgsList(list->next);
}

// Base Provider implementation class. It's expected that tests subclass and
// override the appropriate Provider functions. When test is done quit the
// run_loop().
class CppSideConnection : public dart_to_cpp::CppSide {
 public:
  CppSideConnection() :
      run_loop_(NULL),
      dart_side_(NULL),
      mishandled_messages_(0) {
  }
  ~CppSideConnection() override {}

  void set_run_loop(base::RunLoop* run_loop) { run_loop_ = run_loop; }
  base::RunLoop* run_loop() { return run_loop_; }

  void set_dart_side(dart_to_cpp::DartSide* dart_side) {
    dart_side_ = dart_side;
  }
  dart_to_cpp::DartSide* dart_side() { return dart_side_; }

  // dart_to_cpp::CppSide:
  void StartTest() override { NOTREACHED(); }

  void TestFinished() override { NOTREACHED(); }

  void PingResponse() override { mishandled_messages_ += 1; }

  void EchoResponse(dart_to_cpp::EchoArgsListPtr list) override {
    mishandled_messages_ += 1;
  }

 protected:
  base::RunLoop* run_loop_;
  dart_to_cpp::DartSide* dart_side_;
  int mishandled_messages_;

 private:
  DISALLOW_COPY_AND_ASSIGN(CppSideConnection);
};

// Trivial test to verify a message sent from JS is received.
class PingCppSideConnection : public CppSideConnection {
 public:
  PingCppSideConnection() : got_message_(false) {}
  ~PingCppSideConnection() override {}

  // dart_to_cpp::CppSide:
  void StartTest() override {
    dart_side_->Ping();
  }

  void PingResponse() override {
    got_message_ = true;
    run_loop()->Quit();
  }

  bool DidSucceed() {
    return got_message_ && !mishandled_messages_;
  }

 private:
  bool got_message_;
  DISALLOW_COPY_AND_ASSIGN(PingCppSideConnection);
};

// Test that parameters are passed with correct values.
class EchoCppSideConnection : public CppSideConnection {
 public:
  EchoCppSideConnection() :
      message_count_(0),
      termination_seen_(false) {
  }
  ~EchoCppSideConnection() override {}

  // dart_to_cpp::CppSide:
  void StartTest() override {
    dart_side_->Echo(kExpectedMessageCount, BuildSampleEchoArgs());
  }

  void EchoResponse(dart_to_cpp::EchoArgsListPtr list) override {
    const dart_to_cpp::EchoArgsPtr& special_arg = list->item;
    message_count_ += 1;
    EXPECT_EQ(-1, special_arg->si64);
    EXPECT_EQ(-1, special_arg->si32);
    EXPECT_EQ(-1, special_arg->si16);
    EXPECT_EQ(-1, special_arg->si8);
    EXPECT_EQ(std::string("going"), special_arg->name.To<std::string>());
    CheckSampleEchoArgsList(list->next);
  }

  void TestFinished() override {
    termination_seen_ = true;
    run_loop()->Quit();
  }

  bool DidSucceed() {
    return termination_seen_ &&
        !mishandled_messages_ &&
        message_count_ == kExpectedMessageCount;
  }

 private:
  static const int kExpectedMessageCount = 10;
  int message_count_;
  bool termination_seen_;
  DISALLOW_COPY_AND_ASSIGN(EchoCppSideConnection);
};

}  // namespace

class DartToCppTest : public testing::Test {
 public:
  DartToCppTest() {}

  bool RunTest(const std::string& test, CppSideConnection* cpp_side) {
    // Putting Dart on its own thread so we can use Dart_RunLoop (called from
    // DartController::RunDartScript) and base::RunLoop::Run together. Passing
    // the thread to RunWithDartOnThread instead of inlining that function here
    // so that we are sure the MessagePipe destructor runs and closes the
    // handles on the C++ side before the Thread destructor runs and joins on
    // the Dart thread. Closing the handles on the C++ side must happen first
    // because it is the client, and therefore the Dart side will run and not
    // join while handles are still open, until the C++ side closes them.
    base::Thread dart_thread("dart");
    cpp_side->set_run_loop(&run_loop_);
    return RunWithDartOnThread(&dart_thread, test, cpp_side);
  }

 private:
  base::MessageLoop loop;
  base::RunLoop run_loop_;

  static void UnhandledExceptionCallback(bool* exception, Dart_Handle error) {
    *exception = true;
  }

  static bool GenerateEntropy(uint8_t* buffer, intptr_t length) {
    crypto::RandBytes(reinterpret_cast<void*>(buffer), length);
    return true;
  }

  static void InitializeDartConfig(DartControllerConfig* config,
                                   const std::string& test,
                                   MojoHandle handle,
                                   const char** arguments,
                                   int arguments_count,
                                   bool* unhandled_exception,
                                   char** error) {
    base::FilePath path;
    PathService::Get(base::DIR_SOURCE_ROOT, &path);
    path = path.AppendASCII("mojo")
               .AppendASCII("dart")
               .AppendASCII("embedder")
               .AppendASCII("test")
               .AppendASCII(test);

    // Read in the source.
    std::string source;
    EXPECT_TRUE(ReadFileToString(path, &source)) << "Failed to read test file";

    // Setup the package root.
    base::FilePath package_root;
    PathService::Get(base::DIR_EXE, &package_root);
    package_root = package_root.AppendASCII("gen");

    config->script = source;
    config->script_uri = path.AsUTF8Unsafe();
    config->package_root = package_root.AsUTF8Unsafe();
    config->application_data = nullptr;
    config->callbacks.exception =
        base::Bind(&UnhandledExceptionCallback, unhandled_exception);
    config->entropy = GenerateEntropy;
    config->handle = handle;
    config->arguments = arguments;
    config->arguments_count = arguments_count;
    config->compile_all = false;
    config->error = error;
  }

  static void RunDartSide(const DartControllerConfig& config) {
    DartController::RunDartScript(config);
  }

  bool RunWithDartOnThread(base::Thread* dart_thread,
                           const std::string& test,
                           CppSideConnection* cpp_side) {
    MessagePipe pipe;
    dart_to_cpp::DartSidePtr dart_side =
        MakeProxy<dart_to_cpp::DartSide>(pipe.handle0.Pass());
    dart_side.set_client(cpp_side);

    dart_side.internal_state()->router_for_testing()->EnableTestingMode();

    cpp_side->set_dart_side(dart_side.get());

    DartControllerConfig config;
    // All tests run with these arguments.
    const int kNumArgs = 3;
    const char* args[kNumArgs];
    args[0] = "--enable_asserts";
    args[1] = "--enable_type_checks";
    args[2] = "--error_on_bad_type";
    char* error;
    bool unhandled_exception = false;
    InitializeDartConfig(
        &config,
        test,
        pipe.handle1.release().value(),
        args,
        kNumArgs,
        &unhandled_exception,
        &error);

    dart_thread->Start();
    dart_thread->message_loop()->PostTask(FROM_HERE,
        base::Bind(&RunDartSide, base::ConstRef(config)));

    run_loop_.Run();
    return unhandled_exception;
  }

  DISALLOW_COPY_AND_ASSIGN(DartToCppTest);
};

TEST_F(DartToCppTest, Ping) {
  PingCppSideConnection cpp_side_connection;
  bool unhandled_exception =
      RunTest("dart_to_cpp_tests.dart", &cpp_side_connection);
  EXPECT_TRUE(cpp_side_connection.DidSucceed());
  EXPECT_FALSE(unhandled_exception);
}

TEST_F(DartToCppTest, Echo) {
  EchoCppSideConnection cpp_side_connection;
  bool unhandled_exception =
      RunTest("dart_to_cpp_tests.dart", &cpp_side_connection);
  EXPECT_TRUE(cpp_side_connection.DidSucceed());
  EXPECT_FALSE(unhandled_exception);
}

}  // namespace dart
}  // namespace mojo
