// Copyright 2018 The Chromium OS 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 <fcntl.h>
#include <poll.h>
#include <sys/stat.h>
#include <unistd.h>
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include <base/bind.h>
#include <base/callback.h>
#include <base/files/file_path.h>
#include <base/files/scoped_file.h>
#include <base/files/scoped_temp_dir.h>
#include <base/logging.h>
#include <base/memory/ref_counted.h>
#include <base/memory/shared_memory.h>
#include <base/message_loop/message_loop.h>
#include <base/run_loop.h>
#include <base/strings/stringprintf.h>
#include <brillo/dbus/async_event_sequencer.h>
#include <dbus/diagnosticsd/dbus-constants.h>
#include <dbus/message.h>
#include <dbus/mock_bus.h>
#include <dbus/mock_exported_object.h>
#include <dbus/mock_object_proxy.h>
#include <dbus/property.h>
#include <gmock/gmock.h>
#include <google/protobuf/util/message_differencer.h>
#include <gtest/gtest.h>
#include <mojo/edk/embedder/embedder.h>
#include <mojo/public/cpp/bindings/binding.h>
#include <mojo/public/cpp/bindings/interface_ptr.h>

#include "diagnostics/wilco_dtc_supportd/ec_constants.h"
#include "diagnostics/wilco_dtc_supportd/fake_browser.h"
#include "diagnostics/wilco_dtc_supportd/fake_wilco_dtc.h"
#include "diagnostics/wilco_dtc_supportd/file_test_utils.h"
#include "diagnostics/wilco_dtc_supportd/mojo_test_utils.h"
#include "diagnostics/wilco_dtc_supportd/mojo_utils.h"
#include "diagnostics/wilco_dtc_supportd/protobuf_test_utils.h"
#include "diagnostics/wilco_dtc_supportd/wilco_dtc_supportd_core.h"
#include "mojo/diagnosticsd.mojom.h"
#include "wilco_dtc_supportd.pb.h"  // NOLINT(build/include)

using testing::_;
using testing::Invoke;
using testing::Mock;
using testing::Return;
using testing::SaveArg;
using testing::StrictMock;

namespace diagnostics {

// Templates for the gRPC URIs that should be used for testing. "%s" is
// substituted with a temporary directory.
const char kWilcoDtcSupportdGrpcUriTemplate[] =
    "unix:%s/test_wilco_dtc_supportd_socket";
const char kWilcoDtcGrpcUriTemplate[] = "unix:%s/test_wilco_dtc_socket";
const char kUiMessageReceiverWilcoDtcGrpcUriTemplate[] =
    "unix:%s/test_ui_message_receiver_wilco_dtc_socket";

using MojomDiagnosticsdService =
    chromeos::diagnosticsd::mojom::DiagnosticsdService;
using MojomDiagnosticsdServiceFactory =
    chromeos::diagnosticsd::mojom::DiagnosticsdServiceFactory;

namespace {

// Returns a callback that, once called, saves its parameter to |*response| and
// quits |*run_loop|.
template <typename ValueType>
base::Callback<void(std::unique_ptr<ValueType>)> MakeAsyncResponseWriter(
    std::unique_ptr<ValueType>* response, base::RunLoop* run_loop) {
  return base::Bind(
      [](std::unique_ptr<ValueType>* response, base::RunLoop* run_loop,
         std::unique_ptr<ValueType> received_response) {
        EXPECT_TRUE(received_response);
        EXPECT_FALSE(*response);
        *response = std::move(received_response);
        run_loop->Quit();
      },
      base::Unretained(response), base::Unretained(run_loop));
}

class MockWilcoDtcSupportdCoreDelegate : public WilcoDtcSupportdCore::Delegate {
 public:
  std::unique_ptr<mojo::Binding<MojomDiagnosticsdServiceFactory>>
  BindDiagnosticsdMojoServiceFactory(
      MojomDiagnosticsdServiceFactory* mojo_service_factory,
      base::ScopedFD mojo_pipe_fd) override {
    // Redirect to a separate mockable method to workaround GMock's issues with
    // move-only types.
    return std::unique_ptr<mojo::Binding<MojomDiagnosticsdServiceFactory>>(
        BindDiagnosticsdMojoServiceFactoryImpl(mojo_service_factory,
                                               mojo_pipe_fd.get()));
  }

  MOCK_METHOD2(BindDiagnosticsdMojoServiceFactoryImpl,
               mojo::Binding<MojomDiagnosticsdServiceFactory>*(
                   MojomDiagnosticsdServiceFactory* mojo_service_factory,
                   int mojo_pipe_fd));
  MOCK_METHOD0(BeginDaemonShutdown, void());
};

// Tests for the WilcoDtcSupportdCore class.
class WilcoDtcSupportdCoreTest : public testing::Test {
 protected:
  WilcoDtcSupportdCoreTest() { InitializeMojo(); }

  ~WilcoDtcSupportdCoreTest() { SetDBusShutdownExpectations(); }

  void SetUp() override {
    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());

    wilco_dtc_supportd_grpc_uri_ = base::StringPrintf(
        kWilcoDtcSupportdGrpcUriTemplate, temp_dir_.GetPath().value().c_str());
    ui_message_receiver_wilco_dtc_grpc_uri_ =
        base::StringPrintf(kUiMessageReceiverWilcoDtcGrpcUriTemplate,
                           temp_dir_.GetPath().value().c_str());

    wilco_dtc_grpc_uri_ = base::StringPrintf(
        kWilcoDtcGrpcUriTemplate, temp_dir_.GetPath().value().c_str());

    core_ = std::make_unique<WilcoDtcSupportdCore>(
        wilco_dtc_supportd_grpc_uri_, ui_message_receiver_wilco_dtc_grpc_uri_,
        std::vector<std::string>{wilco_dtc_grpc_uri_}, &core_delegate_);
    core_->set_root_dir_for_testing(temp_dir_.GetPath());

    SetUpEcEventService();

    ASSERT_TRUE(core_->Start());

    SetUpEcEventServiceFifoWriteEnd();

    SetUpDBus();

    fake_browser_ =
        std::make_unique<FakeBrowser>(&mojo_service_factory_interface_ptr_,
                                      bootstrap_mojo_connection_dbus_method_);
  }

  void TearDown() override {
    base::RunLoop run_loop;
    core_->ShutDown(run_loop.QuitClosure());
    run_loop.Run();
  }

  const base::FilePath& temp_dir_path() const {
    DCHECK(temp_dir_.IsValid());
    return temp_dir_.GetPath();
  }

  MockWilcoDtcSupportdCoreDelegate* core_delegate() { return &core_delegate_; }

  mojo::InterfacePtr<MojomDiagnosticsdServiceFactory>*
  mojo_service_factory_interface_ptr() {
    return &mojo_service_factory_interface_ptr_;
  }

  FakeBrowser* fake_browser() {
    DCHECK(fake_browser_);
    return fake_browser_.get();
  }

  // Set up mock for BindDiagnosticsdMojoServiceFactory() that simulates
  // successful Mojo service binding to the given file descriptor. After the
  // mock gets triggered, |mojo_service_factory_interface_ptr_| become
  // initialized to point to the tested Mojo service.
  void SetSuccessMockBindDiagnosticsdMojoService(
      FakeMojoFdGenerator* fake_mojo_fd_generator) {
    EXPECT_CALL(core_delegate_, BindDiagnosticsdMojoServiceFactoryImpl(_, _))
        .WillOnce(Invoke([fake_mojo_fd_generator, this](
                             MojomDiagnosticsdServiceFactory*
                                 mojo_service_factory,
                             int mojo_pipe_fd) {
          // Verify the file descriptor is a duplicate of an expected one.
          EXPECT_TRUE(fake_mojo_fd_generator->IsDuplicateFd(mojo_pipe_fd));
          // Initialize a Mojo binding that, instead of working through the
          // given (fake) file descriptor, talks to the test endpoint
          // |mojo_service_interface_ptr_|.
          auto mojo_service_factory_binding =
              std::make_unique<mojo::Binding<MojomDiagnosticsdServiceFactory>>(
                  mojo_service_factory, &mojo_service_factory_interface_ptr_);
          DCHECK(mojo_service_factory_interface_ptr_);
          return mojo_service_factory_binding.release();
        }));
  }

  void WriteEcEventToEcEventFile(
      const WilcoDtcSupportdEcEventService::EcEvent& ec_event) const {
    ASSERT_EQ(write(ec_event_service_fd_.get(), &ec_event, sizeof(ec_event)),
              sizeof(ec_event));
  }

  dbus::ExportedObject::MethodCallCallback
  bootstrap_mojo_connection_dbus_method() {
    return bootstrap_mojo_connection_dbus_method_;
  }

  const std::string& wilco_dtc_supportd_grpc_uri() const {
    DCHECK(!wilco_dtc_supportd_grpc_uri_.empty());
    return wilco_dtc_supportd_grpc_uri_;
  }

  const std::string& ui_message_receiver_wilco_dtc_grpc_uri() const {
    DCHECK(!ui_message_receiver_wilco_dtc_grpc_uri_.empty());
    return ui_message_receiver_wilco_dtc_grpc_uri_;
  }

  const std::string& wilco_dtc_grpc_uri() const {
    DCHECK(!wilco_dtc_grpc_uri_.empty());
    return wilco_dtc_grpc_uri_;
  }

 private:
  // Initialize the Mojo subsystem.
  void InitializeMojo() { mojo::edk::Init(); }

  // Perform initialization of the D-Bus object exposed by the tested code.
  void SetUpDBus() {
    const dbus::ObjectPath kDBusObjectPath(kDiagnosticsdServicePath);

    // Expect that the /org/chromium/Diagnosticsd object is exported.
    wilco_dtc_supportd_dbus_object_ = new StrictMock<dbus::MockExportedObject>(
        dbus_bus_.get(), kDBusObjectPath);
    EXPECT_CALL(*dbus_bus_, GetExportedObject(kDBusObjectPath))
        .WillOnce(Return(wilco_dtc_supportd_dbus_object_.get()));

    // Expect that standard methods on the org.freedesktop.DBus.Properties
    // interface are exported.
    EXPECT_CALL(
        *wilco_dtc_supportd_dbus_object_,
        ExportMethod(dbus::kPropertiesInterface, dbus::kPropertiesGet, _, _));
    EXPECT_CALL(
        *wilco_dtc_supportd_dbus_object_,
        ExportMethod(dbus::kPropertiesInterface, dbus::kPropertiesSet, _, _));
    EXPECT_CALL(*wilco_dtc_supportd_dbus_object_,
                ExportMethod(dbus::kPropertiesInterface,
                             dbus::kPropertiesGetAll, _, _));

    // Expect that methods on the org.chromium.DiagnosticsdInterface interface
    // are exported.
    EXPECT_CALL(*wilco_dtc_supportd_dbus_object_,
                ExportMethod(kDiagnosticsdServiceInterface,
                             kDiagnosticsdBootstrapMojoConnectionMethod, _, _))
        .WillOnce(SaveArg<2 /* method_call_callback */>(
            &bootstrap_mojo_connection_dbus_method_));

    // Run the tested code that exports D-Bus objects and methods.
    scoped_refptr<brillo::dbus_utils::AsyncEventSequencer> dbus_sequencer(
        new brillo::dbus_utils::AsyncEventSequencer());
    core_->RegisterDBusObjectsAsync(dbus_bus_, dbus_sequencer.get());

    // Verify that required D-Bus methods are exported.
    EXPECT_FALSE(bootstrap_mojo_connection_dbus_method_.is_null());
  }

  // Set mock expectations for calls triggered during test destruction.
  void SetDBusShutdownExpectations() {
    EXPECT_CALL(*wilco_dtc_supportd_dbus_object_, Unregister());
  }

  // Creates FIFO to emulates the EC event file used by EC event service.
  void SetUpEcEventService() {
    core_->set_ec_event_service_fd_events_for_testing(POLLIN);
    ASSERT_TRUE(base::CreateDirectory(ec_event_file_path().DirName()));
    ASSERT_EQ(mkfifo(ec_event_file_path().value().c_str(), 0600), 0);
  }

  // Setups |ec_event_service_fd_| FIFO file descriptor. Must be called only
  // after |WilcoDtcSupportdCore::Start()| call. Otherwise, it will block
  // thread.
  void SetUpEcEventServiceFifoWriteEnd() {
    ASSERT_FALSE(ec_event_service_fd_.is_valid());
    ec_event_service_fd_.reset(
        open(ec_event_file_path().value().c_str(), O_WRONLY));
    ASSERT_TRUE(ec_event_service_fd_.is_valid());
  }

  base::FilePath ec_event_file_path() const {
    return temp_dir_.GetPath().Append(kEcEventFilePath);
  }

  base::MessageLoop message_loop_;

  base::ScopedTempDir temp_dir_;

  // gRPC URI on which the tested "WilcoDtcSupportd" gRPC service (owned by
  // WilcoDtcSupportdCore) is listening.
  std::string wilco_dtc_supportd_grpc_uri_;
  // gRPC URI on which the fake "WilcoDtc" gRPC service (owned by FakeWilcoDtc)
  // is listening, eligible to receive UI messages.
  std::string ui_message_receiver_wilco_dtc_grpc_uri_;
  // gRPC URI on which the fake "WilcoDtc" gRPC service (owned by FakeWilcoDtc)
  // is listening.
  std::string wilco_dtc_grpc_uri_;

  scoped_refptr<StrictMock<dbus::MockBus>> dbus_bus_ =
      new StrictMock<dbus::MockBus>(dbus::Bus::Options());

  // Mock D-Bus integration helper for the object exposed by the tested code.
  scoped_refptr<StrictMock<dbus::MockExportedObject>>
      wilco_dtc_supportd_dbus_object_;

  // Mojo interface to the service factory exposed by the tested code.
  mojo::InterfacePtr<MojomDiagnosticsdServiceFactory>
      mojo_service_factory_interface_ptr_;

  // Write end of FIFO that emulates EC event file. EC event service
  // operates with read end of FIFO as with usual file.
  // Must be initialized only after |WilcoDtcSupportdCore::Start()| call.
  base::ScopedFD ec_event_service_fd_;

  StrictMock<MockWilcoDtcSupportdCoreDelegate> core_delegate_;

  std::unique_ptr<WilcoDtcSupportdCore> core_;

  // Callback that the tested code exposed as the BootstrapMojoConnection D-Bus
  // method.
  dbus::ExportedObject::MethodCallCallback
      bootstrap_mojo_connection_dbus_method_;

  std::unique_ptr<FakeBrowser> fake_browser_;
};

}  // namespace

// Test that the Mojo service gets successfully bootstrapped after the
// BootstrapMojoConnection D-Bus method is called.
TEST_F(WilcoDtcSupportdCoreTest, MojoBootstrapSuccess) {
  FakeMojoFdGenerator fake_mojo_fd_generator;
  SetSuccessMockBindDiagnosticsdMojoService(&fake_mojo_fd_generator);

  EXPECT_TRUE(fake_browser()->BootstrapMojoConnection(&fake_mojo_fd_generator));

  EXPECT_TRUE(*mojo_service_factory_interface_ptr());
}

// Test failure to bootstrap the Mojo service due to en error returned by
// BindDiagnosticsdMojoService() delegate method.
TEST_F(WilcoDtcSupportdCoreTest, MojoBootstrapErrorToBind) {
  FakeMojoFdGenerator fake_mojo_fd_generator;
  EXPECT_CALL(*core_delegate(), BindDiagnosticsdMojoServiceFactoryImpl(_, _))
      .WillOnce(Return(nullptr));
  EXPECT_CALL(*core_delegate(), BeginDaemonShutdown());

  EXPECT_FALSE(
      fake_browser()->BootstrapMojoConnection(&fake_mojo_fd_generator));

  Mock::VerifyAndClearExpectations(core_delegate());
}

// Test that second attempt to bootstrap the Mojo service results in error and
// the daemon shutdown.
TEST_F(WilcoDtcSupportdCoreTest, MojoBootstrapErrorRepeated) {
  FakeMojoFdGenerator first_fake_mojo_fd_generator;
  SetSuccessMockBindDiagnosticsdMojoService(&first_fake_mojo_fd_generator);

  EXPECT_TRUE(
      fake_browser()->BootstrapMojoConnection(&first_fake_mojo_fd_generator));
  Mock::VerifyAndClearExpectations(core_delegate());

  FakeMojoFdGenerator second_fake_mojo_fd_generator;
  EXPECT_CALL(*core_delegate(), BeginDaemonShutdown());

  EXPECT_FALSE(
      fake_browser()->BootstrapMojoConnection(&second_fake_mojo_fd_generator));

  Mock::VerifyAndClearExpectations(core_delegate());
}

// Test that the daemon gets shut down when the previously bootstrapped Mojo
// connection aborts.
TEST_F(WilcoDtcSupportdCoreTest, MojoBootstrapSuccessThenAbort) {
  FakeMojoFdGenerator fake_mojo_fd_generator;
  SetSuccessMockBindDiagnosticsdMojoService(&fake_mojo_fd_generator);

  EXPECT_TRUE(fake_browser()->BootstrapMojoConnection(&fake_mojo_fd_generator));

  Mock::VerifyAndClearExpectations(core_delegate());

  EXPECT_CALL(*core_delegate(), BeginDaemonShutdown());

  // Abort the Mojo connection by closing the browser-side endpoint.
  mojo_service_factory_interface_ptr()->reset();
  base::RunLoop().RunUntilIdle();
  Mock::VerifyAndClearExpectations(core_delegate());
}

namespace {

// Tests for the WilcoDtcSupportdCore class with the already established Mojo
// connection to the fake browser and gRPC communication with the fake
// wilco_dtc.
class BootstrappedWilcoDtcSupportdCoreTest : public WilcoDtcSupportdCoreTest {
 protected:
  void SetUp() override {
    ASSERT_NO_FATAL_FAILURE(WilcoDtcSupportdCoreTest::SetUp());

    FakeMojoFdGenerator fake_mojo_fd_generator;
    SetSuccessMockBindDiagnosticsdMojoService(&fake_mojo_fd_generator);
    ASSERT_TRUE(
        fake_browser()->BootstrapMojoConnection(&fake_mojo_fd_generator));
    ASSERT_TRUE(*mojo_service_factory_interface_ptr());

    fake_wilco_dtc_ = std::make_unique<FakeWilcoDtc>(
        wilco_dtc_grpc_uri(), wilco_dtc_supportd_grpc_uri());

    fake_ui_message_receiver_wilco_dtc_ =
        std::make_unique<FakeWilcoDtc>(ui_message_receiver_wilco_dtc_grpc_uri(),
                                       wilco_dtc_supportd_grpc_uri());
  }

  void TearDown() override {
    fake_wilco_dtc_.reset();
    fake_ui_message_receiver_wilco_dtc_.reset();
    WilcoDtcSupportdCoreTest::TearDown();
  }

  FakeWilcoDtc* fake_ui_message_receiver_wilco_dtc() {
    return fake_ui_message_receiver_wilco_dtc_.get();
  }

  FakeWilcoDtc* fake_wilco_dtc() { return fake_wilco_dtc_.get(); }

  base::Callback<void(mojo::ScopedHandle)> fake_browser_valid_handle_callback(
      const base::Closure& callback,
      const std::string& expected_response_json_message) {
    return base::Bind(
        [](const base::Closure& callback,
           const std::string& expected_response_json_message,
           mojo::ScopedHandle response_json_message_handle) {
          std::unique_ptr<base::SharedMemory> shared_memory =
              GetReadOnlySharedMemoryFromMojoHandle(
                  std::move(response_json_message_handle));
          ASSERT_TRUE(shared_memory);
          ASSERT_EQ(
              expected_response_json_message,
              std::string(static_cast<const char*>(shared_memory->memory()),
                          shared_memory->mapped_size()));
          callback.Run();
        },
        callback, expected_response_json_message);
  }

  base::Callback<void(mojo::ScopedHandle)> fake_browser_invalid_handle_callback(
      const base::Closure& callback) {
    return base::Bind(
        [](const base::Closure& callback,
           mojo::ScopedHandle response_json_message_handle) {
          ASSERT_FALSE(response_json_message_handle.is_valid());
          callback.Run();
        },
        callback);
  }

  MockMojomWilcoDtcSupportdClient* wilco_dtc_supportd_client() {
    return fake_browser()->wilco_dtc_supportd_client();
  }

 private:
  std::unique_ptr<FakeWilcoDtc> fake_ui_message_receiver_wilco_dtc_;
  std::unique_ptr<FakeWilcoDtc> fake_wilco_dtc_;
};

}  // namespace

// Test that the UI message receiver wilco_dtc will receive message from
// browser.
// TODO(crbug.com/946330): Disabled due to flakiness.
TEST_F(BootstrappedWilcoDtcSupportdCoreTest,
       DISABLED_SendGrpcUiMessageToWilcoDtc) {
  const std::string json_message = "{\"some_key\": \"some_value\"}";
  const std::string response_json_message = "{\"key\": \"value\"}";

  base::RunLoop run_loop_wilco_dtc;
  base::RunLoop run_loop_fake_browser;

  fake_ui_message_receiver_wilco_dtc()->set_handle_message_from_ui_callback(
      run_loop_wilco_dtc.QuitClosure());
  fake_ui_message_receiver_wilco_dtc()
      ->set_handle_message_from_ui_json_message_response(response_json_message);
  fake_wilco_dtc()->set_handle_message_from_ui_callback(base::Bind([]() {
    // The wilco_dtc not eligible to receive messages from UI must not
    // receive them.
    FAIL();
  }));

  auto callback = fake_browser_valid_handle_callback(
      run_loop_fake_browser.QuitClosure(), response_json_message);
  EXPECT_TRUE(fake_browser()->SendUiMessageToDiagnosticsProcessor(json_message,
                                                                  callback));

  run_loop_wilco_dtc.Run();
  run_loop_fake_browser.Run();
  EXPECT_EQ(json_message, fake_ui_message_receiver_wilco_dtc()
                              ->handle_message_from_ui_actual_json_message());
}

// Test that the UI message receiver wilco_dtc will not receive message from
// browser if JSON message is invalid.
// TODO(crbug.com/946330): Disabled due to flakiness.
TEST_F(BootstrappedWilcoDtcSupportdCoreTest,
       DISABLED_SendGrpcUiMessageToWilcoDtcInvalidJSON) {
  const std::string json_message = "{'some_key': 'some_value'}";

  base::RunLoop run_loop_fake_browser;

  auto callback =
      fake_browser_invalid_handle_callback(run_loop_fake_browser.QuitClosure());
  EXPECT_TRUE(fake_browser()->SendUiMessageToDiagnosticsProcessor(json_message,
                                                                  callback));

  run_loop_fake_browser.Run();
  // There's no reliable way to wait till the wrong HandleMessageFromUi(), if
  // the tested code is buggy and calls it, gets executed. The RunUntilIdle() is
  // used to make the test failing at least with some probability in case of
  // such a bug.
  base::RunLoop().RunUntilIdle();

  EXPECT_FALSE(fake_ui_message_receiver_wilco_dtc()
                   ->handle_message_from_ui_actual_json_message()
                   .has_value());
}

// Test that the UI message receiver wilco_dtc will receive message from
// browser.
// TODO(crbug.com/946330): Disabled due to flakiness.
TEST_F(BootstrappedWilcoDtcSupportdCoreTest,
       DISABLED_SendGrpcUiMessageToWilcoDtcInvalidResponseJSON) {
  const std::string json_message = "{\"some_key\": \"some_value\"}";
  const std::string response_json_message = "{'key': 'value'}";

  base::RunLoop run_loop_wilco_dtc;
  base::RunLoop run_loop_fake_browser;

  fake_ui_message_receiver_wilco_dtc()->set_handle_message_from_ui_callback(
      run_loop_wilco_dtc.QuitClosure());
  fake_ui_message_receiver_wilco_dtc()
      ->set_handle_message_from_ui_json_message_response(response_json_message);

  auto callback =
      fake_browser_invalid_handle_callback(run_loop_fake_browser.QuitClosure());
  EXPECT_TRUE(fake_browser()->SendUiMessageToDiagnosticsProcessor(json_message,
                                                                  callback));

  run_loop_wilco_dtc.Run();
  run_loop_fake_browser.Run();
  EXPECT_EQ(json_message, fake_ui_message_receiver_wilco_dtc()
                              ->handle_message_from_ui_actual_json_message());
}

// Test that the GetProcData() method exposed by the daemon's gRPC server
// returns a dump of the corresponding file from the disk.
TEST_F(BootstrappedWilcoDtcSupportdCoreTest, GetProcDataGrpcCall) {
  const std::string kFakeFileContents = "foo";
  const base::FilePath file_path = temp_dir_path().Append("proc/uptime");
  ASSERT_TRUE(WriteFileAndCreateParentDirs(file_path, kFakeFileContents));

  grpc_api::GetProcDataRequest request;
  request.set_type(grpc_api::GetProcDataRequest::FILE_UPTIME);
  std::unique_ptr<grpc_api::GetProcDataResponse> response;
  base::RunLoop run_loop;
  fake_wilco_dtc()->GetProcData(request,
                                MakeAsyncResponseWriter(&response, &run_loop));
  run_loop.Run();

  ASSERT_TRUE(response);
  grpc_api::GetProcDataResponse expected_response;
  expected_response.add_file_dump();
  expected_response.mutable_file_dump(0)->set_path(file_path.value());
  expected_response.mutable_file_dump(0)->set_canonical_path(file_path.value());
  expected_response.mutable_file_dump(0)->set_contents(kFakeFileContents);
  EXPECT_TRUE(google::protobuf::util::MessageDifferencer::Equals(
      *response, expected_response))
      << "Obtained: " << response->ShortDebugString()
      << ",\nExpected: " << expected_response.ShortDebugString();
}

// Test that the GetEcTelemetry() method exposed by the daemon's gRPC server
// writes payload to devfs file exposed by the EC driver and reads response
// using the same file.
TEST_F(BootstrappedWilcoDtcSupportdCoreTest, GetEcTelemetryGrpcCall) {
  const base::FilePath file_path =
      temp_dir_path().Append(kEcGetTelemetryFilePath);
  const std::string kRequestPayload = "1";
  ASSERT_TRUE(WriteFileAndCreateParentDirs(file_path, ""));

  grpc_api::GetEcTelemetryRequest request;
  request.set_payload(kRequestPayload);
  std::unique_ptr<grpc_api::GetEcTelemetryResponse> response;
  base::RunLoop run_loop;
  fake_wilco_dtc()->GetEcTelemetry(
      request, MakeAsyncResponseWriter(&response, &run_loop));
  run_loop.Run();

  ASSERT_TRUE(response);
  grpc_api::GetEcTelemetryResponse expected_response;
  expected_response.set_status(grpc_api::GetEcTelemetryResponse::STATUS_OK);
  expected_response.set_payload(kRequestPayload);
  EXPECT_THAT(*response, ProtobufEquals(expected_response))
      << "Actual: {" << response->ShortDebugString() << "}";
}

// Test that the GetEcProperty() method exposed by the daemon's gRPC server
// returns a dump of the corresponding file from the disk.
TEST_F(BootstrappedWilcoDtcSupportdCoreTest, GetEcPropertyGrpcCall) {
  const base::FilePath file_path = temp_dir_path()
                                       .Append(kEcDriverSysfsPath)
                                       .Append(kEcDriverSysfsPropertiesPath)
                                       .Append(kEcPropertyGlobalMicMuteLed);
  const std::string kFakeFileContents = "1";
  ASSERT_TRUE(WriteFileAndCreateParentDirs(file_path, kFakeFileContents));

  grpc_api::GetEcPropertyRequest request;
  request.set_property(
      grpc_api::GetEcPropertyRequest::PROPERTY_GLOBAL_MIC_MUTE_LED);
  std::unique_ptr<grpc_api::GetEcPropertyResponse> response;
  base::RunLoop run_loop;
  fake_wilco_dtc()->GetEcProperty(
      request, MakeAsyncResponseWriter(&response, &run_loop));
  run_loop.Run();

  ASSERT_TRUE(response);
  grpc_api::GetEcPropertyResponse expected_response;
  expected_response.set_status(grpc_api::GetEcPropertyResponse::STATUS_OK);
  expected_response.set_payload(kFakeFileContents);
  EXPECT_THAT(*response, ProtobufEquals(expected_response))
      << "Actual: {" << response->ShortDebugString() << "}";
}

// Test that PerformWebRequest() method exposed by the daemon's gRPC returns a
// Web request response from the browser.
// TODO(crbug.com/946330): Disabled due to flakiness.
TEST_F(BootstrappedWilcoDtcSupportdCoreTest,
       DISABLED_PerformWebRequestToBrowser) {
  constexpr char kHttpsUrl[] = "https://www.google.com";
  constexpr int kHttpStatusOk = 200;

  grpc_api::PerformWebRequestParameter request;
  request.set_http_method(
      grpc_api::PerformWebRequestParameter::HTTP_METHOD_GET);
  request.set_url(kHttpsUrl);

  std::unique_ptr<grpc_api::PerformWebRequestResponse> response;
  {
    base::RunLoop run_loop;
    fake_wilco_dtc()->PerformWebRequest(
        request, MakeAsyncResponseWriter(&response, &run_loop));
    run_loop.Run();
  }

  ASSERT_TRUE(response);
  grpc_api::PerformWebRequestResponse expected_response;
  expected_response.set_status(grpc_api::PerformWebRequestResponse::STATUS_OK);
  expected_response.set_http_status(kHttpStatusOk);
  EXPECT_THAT(*response, ProtobufEquals(expected_response))
      << "Actual: {" << response->ShortDebugString() << "}";
}

// Test that GetConfigurationData() method exposed by the daemon's gRPC returns
// a response from the browser.
TEST_F(BootstrappedWilcoDtcSupportdCoreTest, GetConfigurationDataFromBrowser) {
  constexpr char kFakeJsonConfigurationData[] =
      "{\"fake-message\": \"Fake JSON configuration data\"}";
  EXPECT_CALL(*wilco_dtc_supportd_client(), GetConfigurationData(_))
      .WillOnce(
          Invoke([kFakeJsonConfigurationData](
                     const base::Callback<void(const std::string&)>& callback) {
            callback.Run(kFakeJsonConfigurationData);
          }));
  std::unique_ptr<grpc_api::GetConfigurationDataResponse> response;
  {
    base::RunLoop run_loop;
    grpc_api::GetConfigurationDataRequest request;
    fake_wilco_dtc()->GetConfigurationData(
        request, MakeAsyncResponseWriter(&response, &run_loop));
    run_loop.Run();
  }

  ASSERT_TRUE(response);
  grpc_api::GetConfigurationDataResponse expected_response;
  expected_response.set_json_configuration_data(kFakeJsonConfigurationData);
  EXPECT_THAT(*response, ProtobufEquals(expected_response))
      << "Actual: {" << response->ShortDebugString() << "}";
}

namespace {

// Fake types to be used to emulate EC events.
const uint16_t kFakeEcEventType1 = 0xabcd;
const uint16_t kFakeEcEventType2 = 0x1234;

// Tests for EC event service.
class EcEventServiceBootstrappedWilcoDtcSupportdCoreTest
    : public BootstrappedWilcoDtcSupportdCoreTest {
 protected:
  void EmulateEcEvent(uint16_t size, uint16_t type) const {
    WriteEcEventToEcEventFile(GetEcEvent(size, type));
  }

  void ExpectFakeWilcoDtcEcEventCalled(FakeWilcoDtc* fake_wilco_dtc,
                                       uint16_t expected_size,
                                       uint16_t type) {
    const std::string payload =
        GetPayload(expected_size *
                   sizeof(WilcoDtcSupportdEcEventService::EcEvent::data[0]));
    base::RunLoop run_loop;
    fake_wilco_dtc->set_handle_ec_event_request_callback(base::BindRepeating(
        [](const base::Closure& callback, int32_t expected_type,
           const std::string& expected_payload, int32_t type,
           const std::string& payload) {
          ASSERT_EQ(type, expected_type);
          ASSERT_EQ(payload, expected_payload);
          callback.Run();
        },
        run_loop.QuitClosure(), type, payload));
    run_loop.Run();
  }

 private:
  const uint16_t kData[6]{0x0102, 0x1314, 0x2526, 0x3738, 0x494a, 0x5b5c};
  // |kData| bytes little endian representation.
  const uint8_t kPayload[12]{0x02, 0x01, 0x14, 0x13, 0x26, 0x25,
                             0x38, 0x37, 0x4a, 0x49, 0x5c, 0x5b};

  WilcoDtcSupportdEcEventService::EcEvent GetEcEvent(uint16_t size,
                                                     uint16_t type) const {
    return WilcoDtcSupportdEcEventService::EcEvent(size, type, kData);
  }

  std::string GetPayload(size_t expected_size_in_bytes) const {
    return std::string(reinterpret_cast<const char*>(kPayload),
                       expected_size_in_bytes);
  }
};

}  // namespace

// Test that the method |HandleEcNotification()| exposed by wilco_dtc gRPC is
// called by wilco_dtc support daemon.
// TODO(b/124598866): Disabled due to flakiness.
TEST_F(EcEventServiceBootstrappedWilcoDtcSupportdCoreTest,
       DISABLED_SendGrpcEcEventToWilcoDtcSize0) {
  EmulateEcEvent(0, kFakeEcEventType1);
  ExpectFakeWilcoDtcEcEventCalled(fake_wilco_dtc(), 0, kFakeEcEventType1);
  ExpectFakeWilcoDtcEcEventCalled(fake_ui_message_receiver_wilco_dtc(), 0,
                                  kFakeEcEventType1);
}

// TODO(b/124598866): Disabled due to flakiness.
TEST_F(EcEventServiceBootstrappedWilcoDtcSupportdCoreTest,
       DISABLED_SendGrpcEcEventToWilcoDtcSize5) {
  EmulateEcEvent(5, kFakeEcEventType1);
  ExpectFakeWilcoDtcEcEventCalled(fake_wilco_dtc(), 5, kFakeEcEventType1);
  ExpectFakeWilcoDtcEcEventCalled(fake_ui_message_receiver_wilco_dtc(), 5,
                                  kFakeEcEventType1);
}

// TODO(b/124598866): Disabled due to flakiness.
TEST_F(EcEventServiceBootstrappedWilcoDtcSupportdCoreTest,
       DISABLED_SendGrpcEcEventToDiagnosticsWilcoDtcSize6) {
  EmulateEcEvent(6, kFakeEcEventType1);
  ExpectFakeWilcoDtcEcEventCalled(fake_wilco_dtc(), 6, kFakeEcEventType1);
  ExpectFakeWilcoDtcEcEventCalled(fake_ui_message_receiver_wilco_dtc(), 6,
                                  kFakeEcEventType1);
}

// Test that the method |HandleEcNotification()| exposed by wilco_dtc gRPC is
// called by wilco_dtc support daemon multiple times.
// TODO(b/124598866): Disabled due to flakiness.
TEST_F(EcEventServiceBootstrappedWilcoDtcSupportdCoreTest,
       DISABLED_SendGrpcEcEventToDiagnosticsWilcoDtcMultipleEvents) {
  EmulateEcEvent(3, kFakeEcEventType1);
  EmulateEcEvent(4, kFakeEcEventType2);
  ExpectFakeWilcoDtcEcEventCalled(fake_wilco_dtc(), 3, kFakeEcEventType1);
  ExpectFakeWilcoDtcEcEventCalled(fake_wilco_dtc(), 4, kFakeEcEventType2);
  ExpectFakeWilcoDtcEcEventCalled(fake_ui_message_receiver_wilco_dtc(), 3,
                                  kFakeEcEventType1);
  ExpectFakeWilcoDtcEcEventCalled(fake_ui_message_receiver_wilco_dtc(), 4,
                                  kFakeEcEventType2);
}

// Test that the method |HandleEcNotification()| exposed by wilco_dtc gRPC is
// called by wilco_dtc support daemon even when |ec_event.size| exceeds
// allocated data array.
// TODO(b/124598866): Disabled due to flakiness.
TEST_F(EcEventServiceBootstrappedWilcoDtcSupportdCoreTest,
       DISABLED_SendGrpcEcEventToDiagnosticsWilcoDtcInvalidSize) {
  EmulateEcEvent(7, kFakeEcEventType1);
  ExpectFakeWilcoDtcEcEventCalled(fake_wilco_dtc(), 6, kFakeEcEventType1);
  ExpectFakeWilcoDtcEcEventCalled(fake_ui_message_receiver_wilco_dtc(), 6,
                                  kFakeEcEventType1);
}

}  // namespace diagnostics
