// 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 <set>
#include <string>
#include <tuple>
#include <utility>
#include <vector>

#include <base/barrier_closure.h>
#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/run_loop.h>
#include <base/strings/stringprintf.h>
#include <base/test/task_environment.h>
#include <brillo/dbus/async_event_sequencer.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 <dbus/wilco_dtc_supportd/dbus-constants.h>
#include <gmock/gmock.h>
#include <google/protobuf/util/message_differencer.h>
#include <gtest/gtest.h>
#include <mojo/core/embedder/embedder.h>
#include <mojo/public/cpp/bindings/binding.h>
#include <mojo/public/cpp/bindings/interface_ptr.h>
#include <mojo/public/cpp/bindings/interface_request.h>

#include "diagnostics/common/file_test_utils.h"
#include "diagnostics/common/mojo_test_utils.h"
#include "diagnostics/common/mojo_utils.h"
#include "diagnostics/common/protobuf_test_utils.h"
#include "diagnostics/common/system/fake_bluetooth_client.h"
#include "diagnostics/common/system/fake_powerd_adapter.h"
#include "diagnostics/common/system/mock_debugd_adapter.h"
#include "diagnostics/wilco_dtc_supportd/core.h"
#include "diagnostics/wilco_dtc_supportd/dbus_service.h"
#include "diagnostics/wilco_dtc_supportd/ec_constants.h"
#include "diagnostics/wilco_dtc_supportd/fake_browser.h"
#include "diagnostics/wilco_dtc_supportd/fake_diagnostics_service.h"
#include "diagnostics/wilco_dtc_supportd/fake_probe_service.h"
#include "diagnostics/wilco_dtc_supportd/fake_wilco_dtc.h"
#include "diagnostics/wilco_dtc_supportd/grpc_client_manager.h"
#include "diagnostics/wilco_dtc_supportd/mojo_grpc_adapter.h"
#include "diagnostics/wilco_dtc_supportd/mojo_service_factory.h"
#include "diagnostics/wilco_dtc_supportd/service_util.h"
#include "diagnostics/wilco_dtc_supportd/telemetry/ec_service.h"
#include "diagnostics/wilco_dtc_supportd/telemetry/ec_service_test_utils.h"
#include "diagnostics/wilco_dtc_supportd/telemetry/fake_bluetooth_event_service.h"
#include "diagnostics/wilco_dtc_supportd/telemetry/fake_ec_service.h"
#include "diagnostics/wilco_dtc_supportd/telemetry/fake_powerd_event_service.h"
#include "mojo/wilco_dtc_supportd.mojom.h"
#include "wilco_dtc_supportd.pb.h"  // NOLINT(build/include)

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

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 EcEvent = EcService::EcEvent;
using EcEventReason = EcService::EcEvent::Reason;
using MojoEvent = chromeos::wilco_dtc_supportd::mojom::WilcoDtcSupportdEvent;
using MojomWilcoDtcSupportdService =
    chromeos::wilco_dtc_supportd::mojom::WilcoDtcSupportdService;
using MojomWilcoDtcSupportdServiceFactory =
    chromeos::wilco_dtc_supportd::mojom::WilcoDtcSupportdServiceFactory;
using MojomWilcoDtcSupportdWebRequestHttpMethod =
    chromeos::wilco_dtc_supportd::mojom::WilcoDtcSupportdWebRequestHttpMethod;
using MojomWilcoDtcSupportdWebRequestStatus =
    chromeos::wilco_dtc_supportd::mojom::WilcoDtcSupportdWebRequestStatus;

namespace {

// Returns a callback that, once called, saves its parameter to |*response| and
// quits |*run_loop|.
template <typename ValueType>
base::Callback<void(grpc::Status, std::unique_ptr<ValueType>)>
MakeAsyncResponseWriter(const base::Closure& callback,
                        std::unique_ptr<ValueType>* response) {
  return base::Bind(
      [](const base::Closure& callback, std::unique_ptr<ValueType>* response,
         grpc::Status status, std::unique_ptr<ValueType> received_response) {
        ASSERT_TRUE(received_response);
        ASSERT_FALSE(*response);
        *response = std::move(received_response);
        callback.Run();
      },
      callback, base::Unretained(response));
}

class FakeCoreDelegate : public Core::Delegate {
 public:
  FakeCoreDelegate()
      : passed_bluetooth_client_(std::make_unique<FakeBluetoothClient>()),
        passed_debugd_adapter_(
            std::make_unique<StrictMock<MockDebugdAdapter>>()),
        passed_powerd_adapter_(std::make_unique<FakePowerdAdapter>()),
        passed_bluetooth_event_service_(
            std::make_unique<FakeBluetoothEventService>()),
        passed_ec_service_(std::make_unique<FakeEcService>()),
        passed_powerd_event_service_(
            std::make_unique<FakePowerdEventService>()),
        passed_probe_service_(std::make_unique<FakeProbeService>()),
        bluetooth_client_(passed_bluetooth_client_.get()),
        debugd_adapter_(passed_debugd_adapter_.get()),
        powerd_adapter_(passed_powerd_adapter_.get()),
        bluetooth_event_service_(passed_bluetooth_event_service_.get()),
        ec_service_(passed_ec_service_.get()),
        powerd_event_service_(passed_powerd_event_service_.get()),
        probe_service_(passed_probe_service_.get()) {}

  // Must be called no more than once.
  std::unique_ptr<BluetoothClient> CreateBluetoothClient(
      const scoped_refptr<dbus::Bus>& bus) override {
    DCHECK(bus);
    DCHECK(passed_bluetooth_client_);
    return std::move(passed_bluetooth_client_);
  }

  // Must be called no more than once.
  std::unique_ptr<DebugdAdapter> CreateDebugdAdapter(
      const scoped_refptr<dbus::Bus>& bus) override {
    DCHECK(bus);
    DCHECK(passed_debugd_adapter_);
    return std::move(passed_debugd_adapter_);
  }

  // Must be called no more than once.
  std::unique_ptr<PowerdAdapter> CreatePowerdAdapter(
      const scoped_refptr<dbus::Bus>& bus) override {
    DCHECK(bus);
    DCHECK(passed_powerd_adapter_);
    return std::move(passed_powerd_adapter_);
  }

  // Must be called no more than once.
  std::unique_ptr<BluetoothEventService> CreateBluetoothEventService(
      BluetoothClient* bluetooth_client) override {
    DCHECK(bluetooth_client);
    DCHECK(passed_bluetooth_event_service_);
    DCHECK_EQ(bluetooth_client, bluetooth_client_);
    return std::move(passed_bluetooth_event_service_);
  }

  // Must be called no more than once.
  std::unique_ptr<EcService> CreateEcService() override {
    DCHECK(passed_ec_service_);
    return std::move(passed_ec_service_);
  }

  // Must be called no more than once.
  std::unique_ptr<PowerdEventService> CreatePowerdEventService(
      PowerdAdapter* powerd_adapter) override {
    DCHECK(powerd_adapter);
    DCHECK(passed_powerd_event_service_);
    DCHECK_EQ(powerd_adapter, powerd_adapter_);
    return std::move(passed_powerd_event_service_);
  }

  // Must be called no more than once.
  std::unique_ptr<ProbeService> CreateProbeService(
      ProbeService::Delegate* delegate) override {
    DCHECK(delegate);
    DCHECK(passed_probe_service_);
    return std::move(passed_probe_service_);
  }

  StrictMock<MockDebugdAdapter>* debugd_adapter() const {
    return debugd_adapter_;
  }

  FakeBluetoothEventService* bluetooth_event_service() const {
    return bluetooth_event_service_;
  }

  FakeEcService* ec_service() const { return ec_service_; }

  FakePowerdEventService* powerd_event_service() const {
    return powerd_event_service_;
  }

  FakeProbeService* probe_service() const { return probe_service_; }

 private:
  // Mock objects to be transferred by Create* methods.
  std::unique_ptr<FakeBluetoothClient> passed_bluetooth_client_;
  std::unique_ptr<StrictMock<MockDebugdAdapter>> passed_debugd_adapter_;
  std::unique_ptr<FakePowerdAdapter> passed_powerd_adapter_;

  std::unique_ptr<FakeBluetoothEventService> passed_bluetooth_event_service_;
  std::unique_ptr<FakeEcService> passed_ec_service_;
  std::unique_ptr<FakePowerdEventService> passed_powerd_event_service_;
  std::unique_ptr<FakeProbeService> passed_probe_service_;

  // Pointers to objects originally stored in |passed_*| members. These allow
  // continued access by tests even after the corresponding Create* method has
  // been called and ownership has been transferred to |core_|.
  FakeBluetoothClient* bluetooth_client_;
  StrictMock<MockDebugdAdapter>* debugd_adapter_;
  FakePowerdAdapter* powerd_adapter_;

  FakeBluetoothEventService* bluetooth_event_service_;
  FakeEcService* ec_service_;
  FakePowerdEventService* powerd_event_service_;
  FakeProbeService* probe_service_;
};

// Matches gRPC Bluetooth AdapterData and BluetoothEventService AdapterData.
MATCHER_P(BluetoothAdaptersEquals, expected_adapters, "") {
  if (arg.adapters_size() != expected_adapters.size()) {
    return false;
  }
  for (int i = 0; i < arg.adapters_size(); i++) {
    auto expected_carrier_status =
        (expected_adapters[i].powered)
            ? grpc_api::HandleBluetoothDataChangedRequest::AdapterData::
                  STATUS_UP
            : grpc_api::HandleBluetoothDataChangedRequest::AdapterData::
                  STATUS_DOWN;

    const auto& adapter = arg.adapters(i);

    if (adapter.adapter_name() != expected_adapters[i].name ||
        adapter.adapter_mac_address() != expected_adapters[i].address ||
        adapter.carrier_status() != expected_carrier_status ||
        adapter.connected_devices_count() !=
            expected_adapters[i].connected_devices_count) {
      return false;
    }
  }
  return true;
}

class MockDaemon {
 public:
  MOCK_METHOD(void, ShutDown, ());
};

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

  void CreateCore(const std::vector<std::string>& grpc_service_uris) {
    core_ = std::make_unique<Core>(&core_delegate_, grpc_client_manager(),
                                   grpc_service_uris, &mojo_service_factory_);
  }

  Core* core() {
    DCHECK(core_);
    return core_.get();
  }

  FakeCoreDelegate* core_delegate() { return &core_delegate_; }

  // Fake for MojoServiceFactory::BindFactoryCallback that simulates
  // successful Mojo service binding to the given file descriptor. After the
  // mock gets triggered, |mojo_service_factory_interface_ptr_| becomes
  // initialized to point to the tested Mojo service.
  MojoServiceFactory::MojoBindingPtr FakeBindMojoFactory(
      MojomWilcoDtcSupportdServiceFactory* mojo_service_factory,
      base::ScopedFD mojo_pipe_fd) {
    if (simulate_bind_failure_)
      return nullptr;
    // 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<MojoServiceFactory::MojoBinding>(
            mojo_service_factory,
            mojo::MakeRequest(&mojo_service_factory_interface_ptr_));
    DCHECK(mojo_service_factory_interface_ptr_);
    return MojoServiceFactory::MojoBindingPtr(
        mojo_service_factory_binding.release());
  }

  GrpcClientManager* grpc_client_manager() { return &grpc_client_manager_; }

  StrictMock<MockDaemon>* daemon() { return &daemon_; }

  MojoServiceFactory* mojo_service_factory() { return &mojo_service_factory_; }

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

  void SimulateBindFailure() { simulate_bind_failure_ = true; }

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

  base::test::TaskEnvironment task_environment_{
      base::test::TaskEnvironment::ThreadingMode::MAIN_THREAD_ONLY};

  GrpcClientManager grpc_client_manager_;
  MojoGrpcAdapter mojo_grpc_adapter_{&grpc_client_manager_};

  // Mocked daemon (for calling ShutDown()).
  StrictMock<MockDaemon> daemon_;

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

  MojoServiceFactory mojo_service_factory_{
      &mojo_grpc_adapter_,
      base::Bind(&StrictMock<MockDaemon>::ShutDown, base::Unretained(&daemon_)),
      base::BindOnce(&CoreTest::FakeBindMojoFactory, base::Unretained(this))};

  bool simulate_bind_failure_ = false;

  StrictMock<FakeCoreDelegate> core_delegate_;

  std::unique_ptr<Core> core_;
};

// Test successful shutdown after failed start.
TEST_F(CoreTest, FailedStartAndSuccessfulShutdown) {
  // Invalid gRPC service URI.
  CreateCore({""});
  EXPECT_FALSE(core()->Start());

  ShutDownServicesInRunLoop(core());
}

// Tests for the Core class which started successfully.
class StartedCoreTest : public CoreTest {
 protected:
  void SetUp() override {
    ASSERT_NO_FATAL_FAILURE(CoreTest::SetUp());

    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());

    CreateCore({wilco_dtc_supportd_grpc_uri_});
    core()->set_root_dir_for_testing(temp_dir_.GetPath());

    SetUpEcService();

    ASSERT_TRUE(core()->Start());
    grpc_client_manager()->Start(ui_message_receiver_wilco_dtc_grpc_uri_,
                                 {wilco_dtc_grpc_uri_});

    SetUpEcServiceFifoWriteEnd();

    SetUpDBus();

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

  void TearDown() override {
    SetDBusShutdownExpectations();

    dbus_service_.ShutDown();

    ShutDownServicesInRunLoop(core(), grpc_client_manager());

    CoreTest::TearDown();
  }

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

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

  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_;
  }

  void BootstrapMojoConnection(FakeMojoFdGenerator* fake_mojo_fd_generator) {
    base::RunLoop run_loop;
    ASSERT_TRUE(fake_browser()->BootstrapMojoConnection(
        fake_mojo_fd_generator, run_loop.QuitClosure()));
    run_loop.Run();
  }

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

    // Expect that the /org/chromium/WilcoDtcSupportd 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.WilcoDtcSupportdInterface
    // interface are exported.
    EXPECT_CALL(
        *wilco_dtc_supportd_dbus_object_,
        ExportMethod(kWilcoDtcSupportdServiceInterface,
                     kWilcoDtcSupportdBootstrapMojoConnectionMethod, _, _))
        .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());
    dbus_service_.RegisterDBusObjectsAsync(dbus_bus_, dbus_sequencer.get());
    core()->CreateDbusAdapters(dbus_bus_);

    // 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 SetUpEcService() {
    core_delegate()->ec_service()->set_event_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_service_fd_| FIFO file descriptor. Must be called only
  // after |Core::Start()| call. Otherwise, it will block
  // thread.
  void SetUpEcServiceFifoWriteEnd() {
    ASSERT_FALSE(ec_service_fd_.is_valid());
    ec_service_fd_.reset(open(ec_event_file_path().value().c_str(), O_WRONLY));
    ASSERT_TRUE(ec_service_fd_.is_valid());
  }

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

  base::ScopedTempDir temp_dir_;

  // gRPC URI on which the tested "WilcoDtcSupportd" gRPC service (owned by
  // Core) 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());

  DBusService dbus_service_{mojo_service_factory()};

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

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

  // 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_;
};

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

// Test failure to bootstrap the Mojo service due to an error returned by
// MojoServiceFactory::BootstrapMojoConnection().
TEST_F(StartedCoreTest, MojoBootstrapErrorToBind) {
  FakeMojoFdGenerator fake_mojo_fd_generator;
  EXPECT_CALL(*daemon(), ShutDown());

  SimulateBindFailure();

  base::RunLoop run_loop;
  EXPECT_FALSE(fake_browser()->BootstrapMojoConnection(&fake_mojo_fd_generator,
                                                       run_loop.QuitClosure()));
  run_loop.Run();
}

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

  FakeMojoFdGenerator second_fake_mojo_fd_generator;
  EXPECT_CALL(*daemon(), ShutDown());

  base::RunLoop run_loop;
  EXPECT_FALSE(fake_browser()->BootstrapMojoConnection(
      &second_fake_mojo_fd_generator, run_loop.QuitClosure()));
  run_loop.Run();
}

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

  EXPECT_CALL(*daemon(), ShutDown());

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

// Test that the method |ProbeTelemetryInfo()| calls into
// ProbeService
TEST_F(StartedCoreTest, ProbeTelemetryInfo) {
  using ProbeTelemetryInfoCallback =
      base::OnceCallback<void(chromeos::cros_healthd::mojom::TelemetryInfoPtr)>;
  const auto kCategories =
      std::vector<chromeos::cros_healthd::mojom::ProbeCategoryEnum>{
          chromeos::cros_healthd::mojom::ProbeCategoryEnum::kFan,
          chromeos::cros_healthd::mojom::ProbeCategoryEnum::kCpu,
          chromeos::cros_healthd::mojom::ProbeCategoryEnum::kStatefulPartition};

  core_delegate()->probe_service()->SetProbeTelemetryInfoCallback(base::Bind(
      [](std::vector<chromeos::cros_healthd::mojom::ProbeCategoryEnum>
             expected_categories,
         std::vector<chromeos::cros_healthd::mojom::ProbeCategoryEnum>
             received_categories,
         ProbeTelemetryInfoCallback received_callback) {
        EXPECT_EQ(expected_categories, received_categories);
        std::move(received_callback).Run(nullptr);
      },
      kCategories));

  base::RunLoop run_loop;
  static_cast<GrpcService::Delegate*>(core())->ProbeTelemetryInfo(
      kCategories, base::Bind(
                       [](base::Closure loop_closure,
                          chromeos::cros_healthd::mojom::TelemetryInfoPtr) {
                         loop_closure.Run();
                       },
                       run_loop.QuitClosure()));
  run_loop.Run();
}

// Test that the method |RequestBluetoothDataNotification()| exposed by
// wilco_dtc_supportd gRPC calls clients with the updated data
TEST_F(StartedCoreTest, HandleRequestBluetoothDataNotification) {
  std::vector<BluetoothEventService::AdapterData> adapters(2);
  adapters[0].name = "sarien-laptop";
  adapters[0].address = "aa:bb:cc:dd:ee:ff";
  adapters[0].powered = true;
  adapters[0].connected_devices_count = 0;
  adapters[1].name = "usb-bluetooth";
  adapters[1].address = "00:11:22:33:44:55";
  adapters[1].powered = false;
  adapters[1].connected_devices_count = 2;

  FakeWilcoDtc fake_wilco_dtc(wilco_dtc_grpc_uri(),
                              wilco_dtc_supportd_grpc_uri());
  FakeWilcoDtc fake_ui_message_receiver_wilco_dtc(
      ui_message_receiver_wilco_dtc_grpc_uri(), wilco_dtc_supportd_grpc_uri());

  {
    base::RunLoop run_loop;
    auto barrier_closure = base::BarrierClosure(2, run_loop.QuitClosure());

    auto update_callback = base::BindRepeating(
        [](const base::Closure& callback,
           const grpc_api::HandleBluetoothDataChangedRequest&) {
          callback.Run();
        },
        barrier_closure);

    fake_wilco_dtc.set_bluetooth_data_changed_callback(update_callback);
    fake_ui_message_receiver_wilco_dtc.set_bluetooth_data_changed_callback(
        update_callback);

    core_delegate()->bluetooth_event_service()->EmitBluetoothAdapterDataChanged(
        adapters);

    run_loop.Run();
  }

  {
    auto bluetooth_callback =
        [](const base::Closure& callback,
           grpc_api::HandleBluetoothDataChangedRequest* request_out,
           const grpc_api::HandleBluetoothDataChangedRequest& request) {
          DCHECK(request_out);
          *request_out = request;
          callback.Run();
        };

    base::RunLoop run_loop;
    auto barrier_closure = base::BarrierClosure(3, run_loop.QuitClosure());

    grpc_api::HandleBluetoothDataChangedRequest
        fake_wilco_dtc_bluetooth_grpc_request;
    grpc_api::HandleBluetoothDataChangedRequest
        fake_ui_message_receiver_wilco_dtc_bluetooth_grpc_request;
    fake_wilco_dtc.set_bluetooth_data_changed_callback(
        base::BindRepeating(bluetooth_callback, barrier_closure,
                            &fake_wilco_dtc_bluetooth_grpc_request));
    fake_ui_message_receiver_wilco_dtc.set_bluetooth_data_changed_callback(
        base::BindRepeating(
            bluetooth_callback, barrier_closure,
            &fake_ui_message_receiver_wilco_dtc_bluetooth_grpc_request));

    fake_wilco_dtc.RequestBluetoothDataNotification(
        grpc_api::RequestBluetoothDataNotificationRequest{},
        base::Bind(
            [](base::Closure barrier_closure, grpc::Status status,
               std::unique_ptr<
                   grpc_api::RequestBluetoothDataNotificationResponse>) {
              barrier_closure.Run();
            },
            barrier_closure));

    run_loop.Run();

    EXPECT_THAT(fake_wilco_dtc_bluetooth_grpc_request,
                BluetoothAdaptersEquals(adapters));
    EXPECT_THAT(fake_ui_message_receiver_wilco_dtc_bluetooth_grpc_request,
                BluetoothAdaptersEquals(adapters));
  }
}

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

    FakeMojoFdGenerator fake_mojo_fd_generator;
    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();
    StartedCoreTest::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) {
          auto shm_mapping = GetReadOnlySharedMemoryMappingFromMojoHandle(
              std::move(response_json_message_handle));
          ASSERT_TRUE(shm_mapping.IsValid());
          ASSERT_EQ(expected_response_json_message,
                    std::string(shm_mapping.GetMemoryAs<const char>(),
                                shm_mapping.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);
  }

  MockMojoClient* 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_;
};

// Test that the UI message receiver wilco_dtc will receive message from
// browser.
TEST_F(BootstrappedCoreTest, SendGrpcUiMessageToWilcoDtc) {
  constexpr char kJsonMessageRequest[] = "{\"message\": \"ping\"}";
  constexpr char kJsonMessageResponse[] = "{\"message\": \"pong\"}";

  base::RunLoop run_loop;
  const auto barrier_closure = base::BarrierClosure(2, run_loop.QuitClosure());

  fake_ui_message_receiver_wilco_dtc()->set_handle_message_from_ui_callback(
      barrier_closure);
  fake_ui_message_receiver_wilco_dtc()
      ->set_handle_message_from_ui_json_message_response(kJsonMessageResponse);
  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();
  }));

  EXPECT_TRUE(fake_browser()->SendUiMessageToWilcoDtc(
      kJsonMessageRequest, fake_browser_valid_handle_callback(
                               barrier_closure, kJsonMessageResponse)));

  run_loop.Run();

  EXPECT_EQ(kJsonMessageRequest,
            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.
TEST_F(BootstrappedCoreTest, SendGrpcUiMessageToWilcoDtcInvalidJSON) {
  constexpr char kJsonMessage[] = "{'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()->SendUiMessageToWilcoDtc(kJsonMessage, 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.
TEST_F(BootstrappedCoreTest, SendGrpcUiMessageToWilcoDtcInvalidResponseJSON) {
  constexpr char kJsonMessageRequest[] = "{\"some_key\": \"some_value\"}";
  constexpr char kJsonMessageResponse[] = "{'key': 'value'}";

  base::RunLoop run_loop;
  const auto barrier_closure = base::BarrierClosure(2, run_loop.QuitClosure());

  fake_ui_message_receiver_wilco_dtc()->set_handle_message_from_ui_callback(
      barrier_closure);
  fake_ui_message_receiver_wilco_dtc()
      ->set_handle_message_from_ui_json_message_response(kJsonMessageResponse);

  EXPECT_TRUE(fake_browser()->SendUiMessageToWilcoDtc(
      kJsonMessageRequest,
      fake_browser_invalid_handle_callback(barrier_closure)));

  run_loop.Run();

  EXPECT_EQ(kJsonMessageRequest,
            fake_ui_message_receiver_wilco_dtc()
                ->handle_message_from_ui_actual_json_message());
}

// Test that wilco_dtc_supportd can get a CrosHealthdDiagnosticsServicePtr from
// the browser and use it to fulfill a request from wilco_dtc.
TEST_F(BootstrappedCoreTest, GetCrosHealthdDiagnosticsService) {
  FakeDiagnosticsService fake_diagnostics_service;
  EXPECT_CALL(*wilco_dtc_supportd_client(), GetCrosHealthdDiagnosticsService(_))
      .WillOnce(
          WithArg<0>([&](chromeos::cros_healthd::mojom::
                             CrosHealthdDiagnosticsServiceRequest service) {
            fake_diagnostics_service.GetCrosHealthdDiagnosticsService(
                std::move(service));
          }));
  fake_diagnostics_service.SetGetAvailableRoutinesResponse(
      std::vector<chromeos::cros_healthd::mojom::DiagnosticRoutineEnum>{
          chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::
              kBatteryCapacity});

  std::vector<grpc_api::DiagnosticRoutine> received_routines;
  base::RunLoop run_loop;
  fake_wilco_dtc()->GetAvailableRoutines(base::Bind(
      [](base::Closure quit_closure,
         std::vector<grpc_api::DiagnosticRoutine>* unpacked_response_out,
         grpc::Status status,
         std::unique_ptr<grpc_api::GetAvailableRoutinesResponse> response) {
        for (int i = 0; i < response->routines_size(); i++)
          unpacked_response_out->push_back(response->routines(i));
        quit_closure.Run();
      },
      run_loop.QuitClosure(), &received_routines));
  run_loop.Run();

  EXPECT_THAT(received_routines, ElementsAreArray({grpc_api::ROUTINE_BATTERY}));
}

// Test that wilco_dtc will be notified about configuration changes from
// browser.
TEST_F(BootstrappedCoreTest, NotifyConfigurationDataChanged) {
  base::RunLoop run_loop;
  const base::Closure barrier_closure =
      base::BarrierClosure(2, run_loop.QuitClosure());

  fake_ui_message_receiver_wilco_dtc()->set_configuration_data_changed_callback(
      barrier_closure);
  fake_wilco_dtc()->set_configuration_data_changed_callback(barrier_closure);

  fake_browser()->NotifyConfigurationDataChanged();
  run_loop.Run();
}

// Test that a message can be sent from wilco_dtc to browser and
// returns an expected response
TEST_F(BootstrappedCoreTest, SendWilcoDtcMessageToUi) {
  constexpr char kFakeMessageToUi[] = "{\"message\": \"Fake JSON to UI\"}";
  constexpr char kFakeMessageFromUi[] = "{\"message\": \"Fake JSON from UI\"}";
  EXPECT_CALL(*wilco_dtc_supportd_client(),
              SendWilcoDtcMessageToUiImpl(kFakeMessageToUi, _))
      .WillOnce(WithArg<1>(
          Invoke([kFakeMessageFromUi](
                     base::OnceCallback<void(mojo::ScopedHandle)> callback) {
            std::move(callback).Run(
                CreateReadOnlySharedMemoryRegionMojoHandle(kFakeMessageFromUi));
          })));

  std::unique_ptr<grpc_api::SendMessageToUiResponse> response;
  {
    base::RunLoop run_loop;
    grpc_api::SendMessageToUiRequest request;
    request.set_json_message(kFakeMessageToUi);
    fake_wilco_dtc()->SendMessageToUi(
        request, MakeAsyncResponseWriter(run_loop.QuitClosure(), &response));
    run_loop.Run();
  }

  ASSERT_TRUE(response);
  grpc_api::SendMessageToUiResponse expected_response;
  expected_response.set_response_json_message(kFakeMessageFromUi);
  EXPECT_THAT(*response, ProtobufEquals(expected_response))
      << "Actual: {" << response->ShortDebugString() << "}";
}

// Test that the GetProcData() method exposed by the daemon's gRPC server
// returns a dump of the corresponding file from the disk.
TEST_F(BootstrappedCoreTest, GetProcDataGrpcCall) {
  constexpr char 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(run_loop.QuitClosure(), &response));
  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(BootstrappedCoreTest, GetEcTelemetryGrpcCall) {
  const base::FilePath kFilePath =
      temp_dir_path().Append(kEcGetTelemetryFilePath);
  const std::string kRequestPayload = "12345";
  const std::string kResponsePayload = "67890";

  // Write request and response payload because EC telemetry char device is
  // non-seekable.
  ASSERT_TRUE(WriteFileAndCreateParentDirs(kFilePath,
                                           kRequestPayload + kResponsePayload));

  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(run_loop.QuitClosure(), &response));
  run_loop.Run();

  ASSERT_TRUE(response);
  grpc_api::GetEcTelemetryResponse expected_response;
  expected_response.set_status(grpc_api::GetEcTelemetryResponse::STATUS_OK);
  expected_response.set_payload(kResponsePayload);
  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.
TEST_F(BootstrappedCoreTest, PerformWebRequestToBrowser) {
  constexpr char kHttpsUrl[] = "https://www.google.com";
  constexpr char kHeader1[] = "Accept-Language: en-US";
  constexpr char kHeader2[] = "Accept: text/html";
  constexpr char kBodyRequest[] = "<html>Request</html>";

  constexpr int kHttpStatusOk = 200;
  constexpr char kBodyResponse[] = "<html>Response</html>";

  grpc_api::PerformWebRequestParameter request;
  request.set_http_method(
      grpc_api::PerformWebRequestParameter::HTTP_METHOD_POST);
  request.set_url(kHttpsUrl);
  request.set_request_body(kBodyRequest);
  *request.add_headers() = kHeader1;
  *request.add_headers() = kHeader2;

  std::unique_ptr<grpc_api::PerformWebRequestResponse> response;
  {
    base::RunLoop run_loop;
    EXPECT_CALL(
        *fake_browser()->wilco_dtc_supportd_client(),
        PerformWebRequestImpl(
            MojomWilcoDtcSupportdWebRequestHttpMethod::kPost, kHttpsUrl,
            std::vector<std::string>{kHeader1, kHeader2}, kBodyRequest, _))
        .WillOnce(WithArg<4>(
            Invoke([kBodyResponse](
                       MockMojoClient::MojoPerformWebRequestCallback callback) {
              std::move(callback).Run(
                  MojomWilcoDtcSupportdWebRequestStatus::kOk, kHttpStatusOk,
                  CreateReadOnlySharedMemoryRegionMojoHandle(kBodyResponse));
            })));
    fake_wilco_dtc()->PerformWebRequest(
        request, MakeAsyncResponseWriter(run_loop.QuitClosure(), &response));
    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);
  expected_response.set_response_body(kBodyResponse);
  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(BootstrappedCoreTest, GetConfigurationDataFromBrowser) {
  constexpr char kFakeJsonConfigurationData[] =
      "{\"fake-message\": \"Fake JSON configuration data\"}";
  EXPECT_CALL(*wilco_dtc_supportd_client(), GetConfigurationData(_))
      .WillOnce(
          Invoke([kFakeJsonConfigurationData](
                     base::OnceCallback<void(const std::string&)> callback) {
            std::move(callback).Run(kFakeJsonConfigurationData);
          }));
  std::unique_ptr<grpc_api::GetConfigurationDataResponse> response;
  {
    base::RunLoop run_loop;
    grpc_api::GetConfigurationDataRequest request;
    fake_wilco_dtc()->GetConfigurationData(
        request, MakeAsyncResponseWriter(run_loop.QuitClosure(), &response));
    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() << "}";
}

// Test that GetDriveSystemData() method exposed by the daemon's gRPC returns
// a response from the debugd.
TEST_F(BootstrappedCoreTest, GetDriveSystemData) {
  constexpr char kFakeSmartctlData[] = "Fake smartctl data";
  EXPECT_CALL(*core_delegate()->debugd_adapter(), GetSmartAttributes(_))
      .WillOnce(WithArg<0>(
          [kFakeSmartctlData](
              const base::Callback<void(const std::string&, brillo::Error*)>&
                  callback) { callback.Run(kFakeSmartctlData, nullptr); }));
  std::unique_ptr<grpc_api::GetDriveSystemDataResponse> response;
  {
    base::RunLoop run_loop;
    grpc_api::GetDriveSystemDataRequest request;
    request.set_type(grpc_api::GetDriveSystemDataRequest::SMART_ATTRIBUTES);
    fake_wilco_dtc()->GetDriveSystemData(
        request, MakeAsyncResponseWriter(run_loop.QuitClosure(), &response));
    run_loop.Run();
  }

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

// Test that the method |HandleBluetoothDataChanged()| exposed by wilco_dtc gRPC
// is called by wilco_dtc support daemon.
TEST_F(BootstrappedCoreTest, HandleBluetoothDataChanged) {
  std::vector<BluetoothEventService::AdapterData> adapters(2);
  adapters[0].name = "sarien-laptop";
  adapters[0].address = "aa:bb:cc:dd:ee:ff";
  adapters[0].powered = true;
  adapters[0].connected_devices_count = 0;
  adapters[1].name = "usb-bluetooth";
  adapters[1].address = "00:11:22:33:44:55";
  adapters[1].powered = false;
  adapters[1].connected_devices_count = 2;

  auto bluetooth_callback =
      [](const base::Closure& callback,
         grpc_api::HandleBluetoothDataChangedRequest* request_out,
         const grpc_api::HandleBluetoothDataChangedRequest& request) {
        DCHECK(request_out);
        *request_out = request;
        callback.Run();
      };

  base::RunLoop run_loop;
  auto barrier_closure = base::BarrierClosure(2, run_loop.QuitClosure());

  grpc_api::HandleBluetoothDataChangedRequest
      fake_wilco_dtc_bluetooth_grpc_request;
  grpc_api::HandleBluetoothDataChangedRequest
      fake_ui_message_receiver_wilco_dtc_bluetooth_grpc_request;

  fake_wilco_dtc()->set_bluetooth_data_changed_callback(
      base::BindRepeating(bluetooth_callback, barrier_closure,
                          &fake_wilco_dtc_bluetooth_grpc_request));
  fake_ui_message_receiver_wilco_dtc()->set_bluetooth_data_changed_callback(
      base::BindRepeating(
          bluetooth_callback, barrier_closure,
          &fake_ui_message_receiver_wilco_dtc_bluetooth_grpc_request));

  core_delegate()->bluetooth_event_service()->EmitBluetoothAdapterDataChanged(
      adapters);

  run_loop.Run();

  EXPECT_THAT(fake_wilco_dtc_bluetooth_grpc_request,
              BluetoothAdaptersEquals(adapters));
  EXPECT_THAT(fake_ui_message_receiver_wilco_dtc_bluetooth_grpc_request,
              BluetoothAdaptersEquals(adapters));
}

// Tests for EcService::Observer.
//
// This is a parametrized test with the following parameters:
// * |ec_event_reason| - the reason of the EcEvent
// * |expected_mojo_event| - the expected mojo event passed to the
// |wilco_dtc_supportd_client| over mojo
class EcServiceBootstrappedCoreTest
    : public BootstrappedCoreTest,
      public testing::WithParamInterface<
          std::tuple<EcEventReason, base::Optional<MojoEvent>>> {
 protected:
  // Holds EC event type and payload of |grpc_api::HandleEcNotificationResponse|
  using GrpcEvent = std::pair<uint16_t, std::string>;

  void EmulateEcEvent(const EcEvent& ec_event) {
    core_delegate()->ec_service()->EmitEcEvent(ec_event);
  }

  void ExpectAllFakeWilcoDtcReceivedEcEvents(
      const std::multiset<GrpcEvent>& expected_ec_events) {
    base::RunLoop run_loop;
    auto barrier_closure = base::BarrierClosure(2 * expected_ec_events.size(),
                                                run_loop.QuitClosure());

    std::multiset<GrpcEvent> fake_wilco_dtc_ec_events;
    std::multiset<GrpcEvent> fake_ui_message_receiver_wilco_dtc_ec_events;
    SetupFakeWilcoDtcEcEventCallback(barrier_closure, fake_wilco_dtc(),
                                     &fake_wilco_dtc_ec_events);
    SetupFakeWilcoDtcEcEventCallback(
        barrier_closure, fake_ui_message_receiver_wilco_dtc(),
        &fake_ui_message_receiver_wilco_dtc_ec_events);

    run_loop.Run();

    EXPECT_EQ(fake_wilco_dtc_ec_events, expected_ec_events);
    EXPECT_EQ(fake_ui_message_receiver_wilco_dtc_ec_events, expected_ec_events);
  }

  std::string GetPayload(const EcEvent& ec_event) const {
    DCHECK_LE(ec_event.size - 1, 6);
    uint16_t payload[6];
    memcpy(&payload, &ec_event.payload, (ec_event.size - 1) * sizeof(uint16_t));
    return ConvertDataInWordsToString(payload, ec_event.size - 1);
  }

  EcEventReason ec_event_reason() const { return std::get<0>(GetParam()); }

  base::Optional<MojoEvent> expected_mojo_event() const {
    return std::get<1>(GetParam());
  }

 private:
  void SetupFakeWilcoDtcEcEventCallback(const base::Closure& callback,
                                        FakeWilcoDtc* fake_wilco_dtc,
                                        std::multiset<GrpcEvent>* events_out) {
    DCHECK(fake_wilco_dtc);
    DCHECK(events_out);
    fake_wilco_dtc->set_handle_ec_event_request_callback(base::BindRepeating(
        [](const base::Closure& callback, std::multiset<GrpcEvent>* events_out,
           int32_t type, const std::string& payload) {
          DCHECK(events_out);
          events_out->insert({type, payload});
          callback.Run();
        },
        callback, events_out));
  }
};

// Test that the followings are called by the wilco_dtc support daemon:
// 1. |HandleEcNotification|, exposed by wilco_dtc gRPC, is called on valid
// EC events
// 2. |HandleEvent|, exposed by mojo_client, is called on any EcEvent::Reason
// values except |kSysNotification| and |kNonSysNotification|.
TEST_P(EcServiceBootstrappedCoreTest, SingleEvents) {
  if (expected_mojo_event().has_value()) {
    // Set HandleEvent expectations for the triggered mojo events
    EXPECT_CALL(*wilco_dtc_supportd_client(),
                HandleEvent(expected_mojo_event().value()));
  }
  const EcEvent& ec_event = GetEcEventWithReason(ec_event_reason());
  EmulateEcEvent(ec_event);
  ExpectAllFakeWilcoDtcReceivedEcEvents(
      {{ec_event.type, GetPayload(ec_event)}});
}

// Test that both methods |HandleEcNotification()| and |HandleEvent()| exposed
// by wilco_dtc gRPC and mojo_client, respectively, are called multiple times
// by wilco_dtc support daemon.
TEST_F(EcServiceBootstrappedCoreTest, TriggerMultipleMojoEvents) {
  // Set HandleEvent expectations for the triggered mojo events
  EXPECT_CALL(*wilco_dtc_supportd_client(),
              HandleEvent(MojoEvent::kBatteryAuth));
  EXPECT_CALL(*wilco_dtc_supportd_client(),
              HandleEvent(MojoEvent::kDockDisplay));

  const EcEvent& first_ec_event =
      GetEcEventWithReason(EcEventReason::kBatteryAuth);
  const EcEvent& second_ec_event =
      GetEcEventWithReason(EcEventReason::kDockDisplay);
  EmulateEcEvent(first_ec_event);
  EmulateEcEvent(second_ec_event);

  ExpectAllFakeWilcoDtcReceivedEcEvents(
      {{first_ec_event.type, GetPayload(first_ec_event)},
       {second_ec_event.type, GetPayload(second_ec_event)}});
}

// Test that the method |HandleEcNotification()| exposed by wilco_dtc gRPC is
// not called by the wilco_dtc support daemon when |ec_event.size| exceeds
// allocated data array.
// TODO(mgawad): move size validation logic inside EcService and don't emit
// events when the size is invalid.
TEST_F(EcServiceBootstrappedCoreTest, SendGrpcEventToWilcoDtcInvalidSize) {
  const EcEvent& valid_ec_event =
      GetEcEventWithReason(EcEventReason::kNonSysNotification);
  const EcEvent& invalid_ec_event = kEcEventInvalidPayloadSize;

  EmulateEcEvent(valid_ec_event);
  EmulateEcEvent(invalid_ec_event);

  // Expect only EC event with valid payload size.
  ExpectAllFakeWilcoDtcReceivedEcEvents(
      {{valid_ec_event.type, GetPayload(valid_ec_event)}});
}

INSTANTIATE_TEST_SUITE_P(
    _,
    EcServiceBootstrappedCoreTest,
    testing::Values(
        std::make_tuple(
            EcEventReason::kNonWilcoCharger,
            base::make_optional<MojoEvent>(MojoEvent::kNonWilcoCharger)),
        std::make_tuple(
            EcEventReason::kLowPowerCharger,
            base::make_optional<MojoEvent>(MojoEvent::kLowPowerCharger)),
        std::make_tuple(
            EcEventReason::kBatteryAuth,
            base::make_optional<MojoEvent>(MojoEvent::kBatteryAuth)),
        std::make_tuple(
            EcEventReason::kDockDisplay,
            base::make_optional<MojoEvent>(MojoEvent::kDockDisplay)),
        std::make_tuple(
            EcEventReason::kDockThunderbolt,
            base::make_optional<MojoEvent>(MojoEvent::kDockThunderbolt)),
        std::make_tuple(
            EcEventReason::kIncompatibleDock,
            base::make_optional<MojoEvent>(MojoEvent::kIncompatibleDock)),
        std::make_tuple(EcEventReason::kDockError,
                        base::make_optional<MojoEvent>(MojoEvent::kDockError)),
        std::make_tuple(EcEventReason::kNonSysNotification, base::nullopt),
        std::make_tuple(EcEventReason::kSysNotification, base::nullopt)));

// Tests for powerd event service.
//
// This is a parametrized test with the following parameters:
// * |power_event| - the power event.
// * |expected_power_event| - the expected power event passed to fake_wilco_dtc
//                            over gRPC.
class PowerdEventServiceBootstrappedCoreTest
    : public BootstrappedCoreTest,
      public testing::WithParamInterface<std::tuple<
          PowerdEventService::Observer::PowerEventType /* power_event */,
          grpc_api::HandlePowerNotificationRequest::
              PowerEvent /* expected_power_event */>> {
 protected:
  PowerdEventService::Observer::PowerEventType power_event() const {
    return std::get<0>(GetParam());
  }
  grpc_api::HandlePowerNotificationRequest::PowerEvent expected_power_event()
      const {
    return std::get<1>(GetParam());
  }

  void SetupFakeWilcoDtcPowerEventCallback(
      const base::Closure& callback,
      FakeWilcoDtc* fake_wilco_dtc,
      grpc_api::HandlePowerNotificationRequest::PowerEvent* event_out) {
    DCHECK(fake_wilco_dtc);
    DCHECK(event_out);
    fake_wilco_dtc->set_handle_power_event_request_callback(base::BindRepeating(
        [](const base::Closure& callback,
           grpc_api::HandlePowerNotificationRequest::PowerEvent* event_out,
           grpc_api::HandlePowerNotificationRequest::PowerEvent event) {
          DCHECK(event_out);
          *event_out = event;
          callback.Run();
        },
        callback, event_out));
  }
};

// Test that the method |HandlePowerNotification()| exposed by wilco_dtc gRPC is
// called by wilco_dtc support daemon.
TEST_P(PowerdEventServiceBootstrappedCoreTest, PowerEvent) {
  core_delegate()->powerd_event_service()->EmitPowerEvent(power_event());

  base::RunLoop run_loop;
  auto barrier_closure = base::BarrierClosure(2, run_loop.QuitClosure());

  grpc_api::HandlePowerNotificationRequest::PowerEvent
      fake_wilco_dtc_power_event;
  grpc_api::HandlePowerNotificationRequest::PowerEvent
      fake_ui_message_receiver_wilco_dtc_power_event;
  SetupFakeWilcoDtcPowerEventCallback(barrier_closure, fake_wilco_dtc(),
                                      &fake_wilco_dtc_power_event);
  SetupFakeWilcoDtcPowerEventCallback(
      barrier_closure, fake_ui_message_receiver_wilco_dtc(),
      &fake_ui_message_receiver_wilco_dtc_power_event);

  run_loop.Run();

  EXPECT_EQ(fake_wilco_dtc_power_event, expected_power_event());
  EXPECT_EQ(fake_ui_message_receiver_wilco_dtc_power_event,
            expected_power_event());
}

INSTANTIATE_TEST_SUITE_P(
    ,
    PowerdEventServiceBootstrappedCoreTest,
    testing::Values(
        std::make_tuple(PowerdEventService::Observer::PowerEventType::kAcInsert,
                        grpc_api::HandlePowerNotificationRequest::AC_INSERT),
        std::make_tuple(PowerdEventService::Observer::PowerEventType::kAcRemove,
                        grpc_api::HandlePowerNotificationRequest::AC_REMOVE),
        std::make_tuple(
            PowerdEventService::Observer::PowerEventType::kOsSuspend,
            grpc_api::HandlePowerNotificationRequest::OS_SUSPEND),
        std::make_tuple(PowerdEventService::Observer::PowerEventType::kOsResume,
                        grpc_api::HandlePowerNotificationRequest::OS_RESUME)));

}  // namespace

}  // namespace diagnostics
