// Copyright 2019 The Fuchsia 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 <fidl/fuchsia.hardware.input/cpp/wire_test_base.h>
#include <lib/driver/testing/cpp/driver_test.h>
#include <lib/hid/acer12.h>
#include <lib/hid/ambient-light.h>
#include <lib/hid/boot.h>
#include <lib/hid/buttons.h>
#include <lib/hid/gt92xx.h>
#include <lib/hid/paradise.h>
#include <lib/hid/usages.h>

#include <gtest/gtest.h>
#include <sdk/lib/inspect/testing/cpp/inspect.h>
#include <src/lib/testing/predicates/status.h>

#include "src/ui/input/drivers/hid-input-report/driver.h"

namespace hid_input_report_dev {

namespace fhidbus = fuchsia_hardware_hidbus;
namespace finput = fuchsia_hardware_input;

namespace {

template <typename T>
std::vector<uint8_t> ToBinaryVector(T* data, size_t size) {
  const uint8_t* begin = reinterpret_cast<const uint8_t*>(data);
  return std::vector(begin, begin + size);
}

template <typename T, typename = std::enable_if_t<!std::is_pointer_v<T>>>
std::vector<uint8_t> ToBinaryVector(const T& t) {
  const uint8_t* begin = reinterpret_cast<const uint8_t*>(&t);
  return ToBinaryVector(begin, sizeof(T));
}

}  // namespace

class FakeHidDevice : public fidl::WireServer<finput::Controller>,
                      public fidl::testing::WireTestBase<finput::Device> {
 public:
  class DeviceReportsReader : public fidl::WireServer<finput::DeviceReportsReader> {
   public:
    explicit DeviceReportsReader(fidl::ServerEnd<finput::DeviceReportsReader> server,
                                 libsync::Completion& unbound)
        : binding_(fdf::Dispatcher::GetCurrent()->async_dispatcher(), std::move(server), this,
                   [&unbound](fidl::UnbindInfo) { unbound.Signal(); }) {}

    ~DeviceReportsReader() override { binding_.Close(ZX_ERR_PEER_CLOSED); }

    void ReadReports(ReadReportsCompleter::Sync& completer) override {
      ASSERT_FALSE(waiting_read_.has_value());
      waiting_read_.emplace(completer.ToAsync());
      wait_for_read_.Signal();
    }

    void SendReport(std::vector<uint8_t> report, zx::time timestamp) {
      fidl::Arena arena;
      std::vector<fhidbus::wire::Report> reports = {
          fhidbus::wire::Report::Builder(arena)
              .timestamp(timestamp.get())
              .buf(fidl::VectorView<uint8_t>::FromExternal(report.data(), report.size()))
              .Build()};
      waiting_read_->ReplySuccess(
          fidl::VectorView<fhidbus::wire::Report>::FromExternal(reports.data(), reports.size()));
      waiting_read_.reset();
    }

    libsync::Completion wait_for_read_;

   private:
    fidl::ServerBinding<finput::DeviceReportsReader> binding_;
    std::optional<ReadReportsCompleter::Async> waiting_read_;
  };

  static constexpr uint32_t kVendorId = 0xabc;
  static constexpr uint32_t kProductId = 123;
  static constexpr uint32_t kVersion = 5;

  zx_status_t Serve(fdf::OutgoingDirectory& to_driver_vfs) {
    finput::Service::InstanceHandler instance_handler({
        .controller =
            [this](fidl::ServerEnd<finput::Controller> server) {
              EXPECT_FALSE(binding_);
              binding_.emplace(fdf::Dispatcher::GetCurrent()->async_dispatcher(), std::move(server),
                               this, fidl::kIgnoreBindingClosure);
            },
    });
    return to_driver_vfs.AddService<finput::Service>(std::move(instance_handler)).status_value();
  }

  void NotImplemented_(const std::string& name, fidl::CompleterBase& completer) override {
    ASSERT_TRUE(false);
  }

  void Query(QueryCompleter::Sync& completer) override {
    fidl::Arena arena;
    completer.ReplySuccess(fhidbus::wire::HidInfo::Builder(arena)
                               .vendor_id(kVendorId)
                               .product_id(kProductId)
                               .version(kVersion)
                               .Build());
  }

  void OpenSession(OpenSessionRequestView request, OpenSessionCompleter::Sync& completer) override {
    EXPECT_FALSE(device_binding_);
    device_binding_.emplace(fdf::Dispatcher::GetCurrent()->async_dispatcher(),
                            std::move(request->session), this, fidl::kIgnoreBindingClosure);
  }

  void GetDeviceReportsReader(GetDeviceReportsReaderRequestView request,
                              GetDeviceReportsReaderCompleter::Sync& completer) override {
    ASSERT_FALSE(reader_);
    reader_ = std::make_unique<DeviceReportsReader>(std::move(request->reader), unbound_);
    completer.ReplySuccess();
  }

  void GetReportDesc(GetReportDescCompleter::Sync& completer) override {
    completer.Reply(
        fidl::VectorView<uint8_t>::FromExternal(report_desc_.data(), report_desc_.size()));
  }

  void GetReport(GetReportRequestView request, GetReportCompleter::Sync& completer) override {
    // If the client is Getting a report with a specific ID, check that it matches
    // our saved report.
    if ((request->id != 0) && (report_.size() > 0)) {
      if (request->id != report_[0]) {
        completer.ReplyError(ZX_ERR_WRONG_TYPE);
        return;
      }
    }

    completer.ReplySuccess(fidl::VectorView<uint8_t>::FromExternal(report_.data(), report_.size()));
  }
  std::vector<uint8_t>& GetReport() { return report_; }

  void SetReport(SetReportRequestView request, SetReportCompleter::Sync& completer) override {
    report_ = ToBinaryVector(request->report.data(), request->report.size());
    completer.ReplySuccess();
  }
  void SetReport(std::vector<uint8_t> report) { report_ = std::move(report); }

  void SetReportDesc(std::vector<uint8_t> report_desc) { report_desc_ = std::move(report_desc); }

  void SendReport(std::vector<uint8_t> report, zx::time timestamp) const {
    ASSERT_TRUE(reader_);
    reader_->SendReport(std::move(report), timestamp);
  }

  std::unique_ptr<DeviceReportsReader> reader_;
  libsync::Completion unbound_;

 private:
  std::optional<fidl::ServerBinding<finput::Controller>> binding_;
  std::optional<fidl::ServerBinding<finput::Device>> device_binding_;

  std::vector<uint8_t> report_desc_;
  std::vector<uint8_t> report_;
};

class InputReportTestEnvironment : public fdf_testing::Environment {
 public:
  zx::result<> Serve(fdf::OutgoingDirectory& to_driver_vfs) override {
    EXPECT_OK(fake_hid_.Serve(to_driver_vfs));
    return zx::ok();
  }

  FakeHidDevice& fake_hid() { return fake_hid_; }

 private:
  FakeHidDevice fake_hid_;
};

class FixtureConfig final {
 public:
  using DriverType = InputReportDriver;
  using EnvironmentType = InputReportTestEnvironment;
};

class HidDevTest : public ::testing::Test {
 public:
  void TearDown() override {
    zx::result<> result = driver_test().StopDriver();
    ASSERT_EQ(ZX_OK, result.status_value());
  }
  fidl::WireSyncClient<fuchsia_input_report::InputDevice> GetSyncClient() {
    auto connect_result =
        driver_test().RunInNodeContext<zx::result<zx::channel>>([](fdf_testing::TestNode& node) {
          return node.children().at("InputReport").ConnectToDevice();
        });
    EXPECT_TRUE(connect_result.is_ok());
    return fidl::WireSyncClient(
        fidl::ClientEnd<fuchsia_input_report::InputDevice>(std::move(connect_result.value())));
  }

  fidl::ClientEnd<fuchsia_input_report::InputReportsReader> GetReader() {
    return GetReader(GetSyncClient());
  }
  fidl::ClientEnd<fuchsia_input_report::InputReportsReader> GetReader(
      const fidl::WireSyncClient<fuchsia_input_report::InputDevice>& sync_client) {
    auto endpoints = fidl::Endpoints<fuchsia_input_report::InputReportsReader>::Create();
    auto result = sync_client->GetInputReportsReader(std::move(endpoints.server));
    EXPECT_OK(result.status());
    sync_completion_t* next_reader_wait;
    driver_test().RunInDriverContext([&next_reader_wait](InputReportDriver& driver) {
      next_reader_wait = &driver.input_report_for_testing().next_reader_wait();
    });
    EXPECT_OK(sync_completion_wait(next_reader_wait, ZX_TIME_INFINITE));
    sync_completion_reset(next_reader_wait);
    return std::move(endpoints.client);
  }

  void SendReport(std::vector<uint8_t> report, zx::time timestamp = zx::time::infinite()) {
    if (timestamp == zx::time::infinite()) {
      timestamp = zx::clock::get_monotonic();
    }

    libsync::Completion* wait_for_read;
    driver_test().RunInEnvironmentTypeContext([&wait_for_read](InputReportTestEnvironment& env) {
      ASSERT_TRUE(env.fake_hid().reader_);
      wait_for_read = &env.fake_hid().reader_->wait_for_read_;
    });
    wait_for_read->Wait();
    wait_for_read->Reset();
    driver_test().RunInEnvironmentTypeContext(
        [&report, &timestamp](InputReportTestEnvironment& env) {
          ASSERT_TRUE(env.fake_hid().reader_);
          env.fake_hid().reader_->SendReport(std::move(report), timestamp);
        });
    wait_for_read->Wait();
  }

  fdf_testing::BackgroundDriverTest<FixtureConfig>& driver_test() { return driver_test_; }

 private:
  fdf_testing::BackgroundDriverTest<FixtureConfig> driver_test_;
};

TEST_F(HidDevTest, HidLifetimeTest) {
  driver_test().RunInEnvironmentTypeContext([](InputReportTestEnvironment& env) {
    size_t boot_mouse_desc_size;
    const uint8_t* boot_mouse_desc = get_boot_mouse_report_desc(&boot_mouse_desc_size);
    env.fake_hid().SetReportDesc(ToBinaryVector(boot_mouse_desc, boot_mouse_desc_size));
  });
  ASSERT_TRUE(driver_test().StartDriver().is_ok());
}

class UnregisterHidDevTest : public ::testing::Test {
 public:
  fdf_testing::ForegroundDriverTest<FixtureConfig>& driver_test() { return driver_test_; }

 private:
  fdf_testing::ForegroundDriverTest<FixtureConfig> driver_test_;
};

TEST_F(UnregisterHidDevTest, InputReportUnregisterTest) {
  driver_test().RunInEnvironmentTypeContext([](InputReportTestEnvironment& env) {
    size_t boot_mouse_desc_size;
    const uint8_t* boot_mouse_desc = get_boot_mouse_report_desc(&boot_mouse_desc_size);
    env.fake_hid().SetReportDesc(ToBinaryVector(boot_mouse_desc, boot_mouse_desc_size));
  });
  ASSERT_TRUE(driver_test().StartDriver().is_ok());

  zx::result prepare_stop_result = driver_test().StopDriver();
  EXPECT_EQ(ZX_OK, prepare_stop_result.status_value());

  libsync::Completion* unbound;
  driver_test().RunInEnvironmentTypeContext(
      [&unbound](InputReportTestEnvironment& env) { unbound = &env.fake_hid().unbound_; });
  unbound->Wait();
}

TEST_F(HidDevTest, InputReportUnregisterTestBindFailed) {
  // We don't set a input report on `fake_hid` so the bind will fail.
  ASSERT_EQ(driver_test().StartDriver().status_value(), ZX_ERR_INTERNAL);

  // Make sure that the InputReport class is not registered to the HID device.
  driver_test().RunInEnvironmentTypeContext(
      [](InputReportTestEnvironment& env) { ASSERT_FALSE(env.fake_hid().reader_); });
}

TEST_F(HidDevTest, GetReportDescTest) {
  driver_test().RunInEnvironmentTypeContext([](InputReportTestEnvironment& env) {
    size_t boot_mouse_desc_size;
    const uint8_t* boot_mouse_desc = get_boot_mouse_report_desc(&boot_mouse_desc_size);
    env.fake_hid().SetReportDesc(ToBinaryVector(boot_mouse_desc, boot_mouse_desc_size));
  });
  ASSERT_TRUE(driver_test().StartDriver().is_ok());

  auto sync_client = GetSyncClient();
  fidl::WireResult<fuchsia_input_report::InputDevice::GetDescriptor> result =
      sync_client->GetDescriptor();
  ASSERT_OK(result.status());

  auto& desc = result->descriptor;
  ASSERT_TRUE(desc.has_mouse());
  ASSERT_TRUE(desc.mouse().has_input());

  fuchsia_input_report::wire::MouseInputDescriptor& mouse = desc.mouse().input();
  ASSERT_TRUE(mouse.has_movement_x());
  ASSERT_EQ(-127, mouse.movement_x().range.min);
  ASSERT_EQ(127, mouse.movement_x().range.max);

  ASSERT_TRUE(mouse.has_movement_y());
  ASSERT_EQ(-127, mouse.movement_y().range.min);
  ASSERT_EQ(127, mouse.movement_y().range.max);
}

TEST_F(HidDevTest, ReportDescInfoTest) {
  driver_test().RunInEnvironmentTypeContext([](InputReportTestEnvironment& env) {
    size_t boot_mouse_desc_size;
    const uint8_t* boot_mouse_desc = get_boot_mouse_report_desc(&boot_mouse_desc_size);
    env.fake_hid().SetReportDesc(ToBinaryVector(boot_mouse_desc, boot_mouse_desc_size));
  });
  ASSERT_TRUE(driver_test().StartDriver().is_ok());

  auto sync_client = GetSyncClient();
  fidl::WireResult<fuchsia_input_report::InputDevice::GetDescriptor> result =
      sync_client->GetDescriptor();
  ASSERT_OK(result.status());

  auto& desc = result.value().descriptor;
  ASSERT_TRUE(desc.has_device_information());
  ASSERT_EQ(desc.device_information().vendor_id(), FakeHidDevice::kVendorId);
  ASSERT_EQ(desc.device_information().product_id(), FakeHidDevice::kProductId);
  ASSERT_EQ(desc.device_information().version(), FakeHidDevice::kVersion);
}

TEST_F(HidDevTest, ReadInputReportsTest) {
  driver_test().RunInEnvironmentTypeContext([](InputReportTestEnvironment& env) {
    size_t boot_mouse_desc_size;
    const uint8_t* boot_mouse_desc = get_boot_mouse_report_desc(&boot_mouse_desc_size);
    env.fake_hid().SetReportDesc(ToBinaryVector(boot_mouse_desc, boot_mouse_desc_size));
  });
  ASSERT_TRUE(driver_test().StartDriver().is_ok());

  // GetReader() must be called before SendReport() because SendReport() only sends reports to
  // existing readers.
  fidl::WireSyncClient<fuchsia_input_report::InputReportsReader> reader(GetReader());
  SendReport(std::vector<uint8_t>{0xFF, 0x50, 0x70});

  auto result = reader->ReadInputReports();
  ASSERT_OK(result.status());
  ASSERT_FALSE(result->is_error());
  auto& reports = result->value()->reports;

  ASSERT_EQ(1UL, reports.size());

  auto& report = reports[0];
  ASSERT_TRUE(report.has_event_time());
  ASSERT_TRUE(report.has_mouse());
  auto& mouse = report.mouse();

  ASSERT_TRUE(mouse.has_movement_x());
  ASSERT_EQ(0x50, mouse.movement_x());

  ASSERT_TRUE(mouse.has_movement_y());
  ASSERT_EQ(0x70, mouse.movement_y());

  ASSERT_TRUE(mouse.has_pressed_buttons());
  const fidl::VectorView<uint8_t>& pressed_buttons = mouse.pressed_buttons();
  for (size_t i = 0; i < pressed_buttons.size(); i++) {
    ASSERT_EQ(i + 1, pressed_buttons[i]);
  }
}

TEST_F(HidDevTest, ReadInputReportsHangingGetTest) {
  driver_test().RunInEnvironmentTypeContext([](InputReportTestEnvironment& env) {
    size_t boot_mouse_desc_size;
    const uint8_t* boot_mouse_desc = get_boot_mouse_report_desc(&boot_mouse_desc_size);
    env.fake_hid().SetReportDesc(ToBinaryVector(boot_mouse_desc, boot_mouse_desc_size));
  });
  ASSERT_TRUE(driver_test().StartDriver().is_ok());

  fidl::WireClient<fuchsia_input_report::InputReportsReader> reader(
      GetReader(), fdf::Dispatcher::GetCurrent()->async_dispatcher());
  // Read the report. This will hang until a report is sent.
  reader->ReadInputReports().ThenExactlyOnce(
      [&](fidl::WireUnownedResult<fuchsia_input_report::InputReportsReader::ReadInputReports>&
              response) {
        ASSERT_OK(response.status());
        ASSERT_FALSE(response->is_error());
        auto& reports = response->value()->reports;
        ASSERT_EQ(1UL, reports.size());

        auto& report = reports[0];
        ASSERT_TRUE(report.has_event_time());
        ASSERT_TRUE(report.has_mouse());
        auto& mouse = report.mouse();

        ASSERT_TRUE(mouse.has_movement_x());
        ASSERT_EQ(0x50, mouse.movement_x());

        ASSERT_TRUE(mouse.has_movement_y());
        ASSERT_EQ(0x70, mouse.movement_y());
        driver_test().runtime().Quit();
      });
  driver_test().runtime().RunUntilIdle();

  // Send the report.
  SendReport(std::vector<uint8_t>{0xFF, 0x50, 0x70});

  driver_test().runtime().Run();
}

TEST_F(HidDevTest, CloseReaderWithOutstandingRead) {
  driver_test().RunInEnvironmentTypeContext([](InputReportTestEnvironment& env) {
    size_t boot_mouse_desc_size;
    const uint8_t* boot_mouse_desc = get_boot_mouse_report_desc(&boot_mouse_desc_size);
    env.fake_hid().SetReportDesc(ToBinaryVector(boot_mouse_desc, boot_mouse_desc_size));
  });
  ASSERT_TRUE(driver_test().StartDriver().is_ok());

  fidl::WireClient<fuchsia_input_report::InputReportsReader> reader(
      GetReader(), fdf::Dispatcher::GetCurrent()->async_dispatcher());

  // Queue a report.
  reader->ReadInputReports().ThenExactlyOnce(
      [&](fidl::WireUnownedResult<fuchsia_input_report::InputReportsReader::ReadInputReports>&
              result) { ASSERT_TRUE(result.is_canceled()); });
  driver_test().runtime().RunUntilIdle();

  // Unbind the reader now that the report is waiting.
  reader = {};
}

TEST_F(HidDevTest, SensorTest) {
  driver_test().RunInEnvironmentTypeContext([](InputReportTestEnvironment& env) {
    const uint8_t* sensor_desc_ptr;
    size_t sensor_desc_size = get_ambient_light_report_desc(&sensor_desc_ptr);
    env.fake_hid().SetReportDesc(ToBinaryVector(sensor_desc_ptr, sensor_desc_size));
  });
  ASSERT_TRUE(driver_test().StartDriver().is_ok());

  auto sync_client = GetSyncClient();

  // Get the report descriptor.
  fidl::WireResult<fuchsia_input_report::InputDevice::GetDescriptor> result =
      sync_client->GetDescriptor();
  ASSERT_OK(result.status());
  fuchsia_input_report::wire::DeviceDescriptor& desc = result.value().descriptor;
  ASSERT_TRUE(desc.has_sensor());
  ASSERT_TRUE(desc.sensor().has_input());
  ASSERT_EQ(desc.sensor().input().size(), 1UL);
  fuchsia_input_report::wire::SensorInputDescriptor& sensor_desc = desc.sensor().input()[0];
  ASSERT_TRUE(sensor_desc.has_values());
  ASSERT_EQ(4UL, sensor_desc.values().size());

  ASSERT_EQ(sensor_desc.values()[0].type,
            fuchsia_input_report::wire::SensorType::kLightIlluminance);
  ASSERT_EQ(sensor_desc.values()[0].axis.unit.type, fuchsia_input_report::wire::UnitType::kNone);

  ASSERT_EQ(sensor_desc.values()[1].type, fuchsia_input_report::wire::SensorType::kLightRed);
  ASSERT_EQ(sensor_desc.values()[1].axis.unit.type, fuchsia_input_report::wire::UnitType::kNone);

  ASSERT_EQ(sensor_desc.values()[2].type, fuchsia_input_report::wire::SensorType::kLightBlue);
  ASSERT_EQ(sensor_desc.values()[2].axis.unit.type, fuchsia_input_report::wire::UnitType::kNone);

  ASSERT_EQ(sensor_desc.values()[3].type, fuchsia_input_report::wire::SensorType::kLightGreen);
  ASSERT_EQ(sensor_desc.values()[3].axis.unit.type, fuchsia_input_report::wire::UnitType::kNone);

  fidl::WireSyncClient<fuchsia_input_report::InputReportsReader> reader(GetReader(sync_client));

  // Create the report.
  ambient_light_input_rpt_t report_data = {};
  // Values are arbitrarily chosen.
  const int kIlluminanceTestVal = 10;
  const int kRedTestVal = 101;
  const int kBlueTestVal = 5;
  const int kGreenTestVal = 3;
  report_data.rpt_id = AMBIENT_LIGHT_RPT_ID_INPUT;
  report_data.illuminance = kIlluminanceTestVal;
  report_data.red = kRedTestVal;
  report_data.blue = kBlueTestVal;
  report_data.green = kGreenTestVal;

  SendReport(ToBinaryVector(report_data));

  // Get the report.
  auto report_result = reader->ReadInputReports();
  ASSERT_OK(report_result.status());

  const fidl::VectorView<fuchsia_input_report::wire::InputReport>& reports =
      report_result->value()->reports;
  ASSERT_EQ(1UL, reports.size());

  ASSERT_TRUE(reports[0].has_sensor());
  const fuchsia_input_report::wire::SensorInputReport& sensor_report = reports[0].sensor();
  EXPECT_TRUE(sensor_report.has_values());
  EXPECT_EQ(4UL, sensor_report.values().size());

  // Check the report.
  // These will always match the ordering in the descriptor.
  EXPECT_EQ(kIlluminanceTestVal, sensor_report.values()[0]);
  EXPECT_EQ(kRedTestVal, sensor_report.values()[1]);
  EXPECT_EQ(kBlueTestVal, sensor_report.values()[2]);
  EXPECT_EQ(kGreenTestVal, sensor_report.values()[3]);
}

TEST_F(HidDevTest, GetTouchInputReportTest) {
  driver_test().RunInEnvironmentTypeContext([](InputReportTestEnvironment& env) {
    size_t desc_len;
    const uint8_t* report_desc = get_paradise_touch_report_desc(&desc_len);
    env.fake_hid().SetReportDesc(ToBinaryVector(report_desc, desc_len));
  });
  ASSERT_TRUE(driver_test().StartDriver().is_ok());

  // Get an InputReportsReader.
  fidl::WireSyncClient<fuchsia_input_report::InputReportsReader> reader(GetReader());

  // Spoof send a report.
  paradise_touch_t touch_report = {};
  touch_report.rpt_id = PARADISE_RPT_ID_TOUCH;
  touch_report.contact_count = 1;
  touch_report.fingers[0].flags = 0xFF;
  touch_report.fingers[0].x = 100;
  touch_report.fingers[0].y = 200;
  touch_report.fingers[0].finger_id = 1;

  SendReport(ToBinaryVector(touch_report));

  // Get the report.
  auto report_result = reader->ReadInputReports();
  ASSERT_OK(report_result.status());

  const fidl::VectorView<fuchsia_input_report::wire::InputReport>& reports =
      report_result->value()->reports;
  ASSERT_EQ(1UL, reports.size());

  const auto& report = reports[0];
  const auto& touch = report.touch();
  ASSERT_TRUE(touch.has_contacts());
  ASSERT_EQ(1UL, touch.contacts().size());
  const auto& contact = touch.contacts()[0];

  ASSERT_TRUE(contact.has_position_x());
  ASSERT_EQ(2500, contact.position_x());

  ASSERT_TRUE(contact.has_position_y());
  ASSERT_EQ(5000, contact.position_y());
}

TEST_F(HidDevTest, GetTouchPadDescTest) {
  driver_test().RunInEnvironmentTypeContext([](InputReportTestEnvironment& env) {
    size_t desc_len;
    const uint8_t* report_desc = get_paradise_touchpad_v1_report_desc(&desc_len);
    env.fake_hid().SetReportDesc(ToBinaryVector(report_desc, desc_len));
  });
  ASSERT_TRUE(driver_test().StartDriver().is_ok());

  auto sync_client = GetSyncClient();
  fidl::WireResult<fuchsia_input_report::InputDevice::GetDescriptor> result =
      sync_client->GetDescriptor();
  ASSERT_OK(result.status());
  ASSERT_TRUE(result.value().descriptor.has_touch());
  ASSERT_TRUE(result.value().descriptor.touch().has_input());
  fuchsia_input_report::wire::TouchInputDescriptor& touch =
      result.value().descriptor.touch().input();

  ASSERT_EQ(fuchsia_input_report::wire::TouchType::kTouchpad, touch.touch_type());
}

TEST_F(HidDevTest, KeyboardTest) {
  driver_test().RunInEnvironmentTypeContext([](InputReportTestEnvironment& env) {
    size_t keyboard_descriptor_size;
    const uint8_t* keyboard_descriptor = get_boot_kbd_report_desc(&keyboard_descriptor_size);
    env.fake_hid().SetReportDesc(ToBinaryVector(keyboard_descriptor, keyboard_descriptor_size));
  });
  ASSERT_TRUE(driver_test().StartDriver().is_ok());

  // Get an InputReportsReader.
  fidl::WireSyncClient<fuchsia_input_report::InputReportsReader> reader(GetReader());

  // Spoof send a report.
  hid_boot_kbd_report keyboard_report = {};
  keyboard_report.usage[0] = HID_USAGE_KEY_A;
  keyboard_report.usage[1] = HID_USAGE_KEY_UP;
  keyboard_report.usage[2] = HID_USAGE_KEY_B;

  SendReport(ToBinaryVector(keyboard_report));

  // Get the report.
  auto report_result = reader->ReadInputReports();
  ASSERT_OK(report_result.status());

  const fidl::VectorView<fuchsia_input_report::wire::InputReport>& reports =
      report_result->value()->reports;
  ASSERT_EQ(1UL, reports.size());

  const auto& report = reports[0];
  const auto& keyboard = report.keyboard();
  ASSERT_EQ(3UL, keyboard.pressed_keys3().size());
  EXPECT_EQ(fuchsia_input::wire::Key::kA, keyboard.pressed_keys3()[0]);
  EXPECT_EQ(fuchsia_input::wire::Key::kUp, keyboard.pressed_keys3()[1]);
  EXPECT_EQ(fuchsia_input::wire::Key::kB, keyboard.pressed_keys3()[2]);
}

TEST_F(HidDevTest, KeyboardOutputReportTest) {
  driver_test().RunInEnvironmentTypeContext([](InputReportTestEnvironment& env) {
    size_t keyboard_descriptor_size;
    const uint8_t* keyboard_descriptor = get_boot_kbd_report_desc(&keyboard_descriptor_size);
    env.fake_hid().SetReportDesc(ToBinaryVector(keyboard_descriptor, keyboard_descriptor_size));
  });
  ASSERT_TRUE(driver_test().StartDriver().is_ok());

  auto sync_client = GetSyncClient();
  // Make an output report.
  fidl::Arena allocator;
  fidl::VectorView<fuchsia_input_report::wire::LedType> led_view(allocator, 2);
  led_view[0] = fuchsia_input_report::wire::LedType::kNumLock;
  led_view[1] = fuchsia_input_report::wire::LedType::kScrollLock;
  fuchsia_input_report::wire::KeyboardOutputReport fidl_keyboard(allocator);
  fidl_keyboard.set_enabled_leds(allocator, std::move(led_view));

  fuchsia_input_report::wire::OutputReport output_report(allocator);
  output_report.set_keyboard(allocator, std::move(fidl_keyboard));
  // Send the report.
  fidl::WireResult<fuchsia_input_report::InputDevice::SendOutputReport> response =
      sync_client->SendOutputReport(std::move(output_report));
  ASSERT_TRUE(response.ok());
  ASSERT_TRUE(response->is_ok());
  // Check the hid output report.
  driver_test().RunInEnvironmentTypeContext([](InputReportTestEnvironment& env) {
    EXPECT_EQ(env.fake_hid().GetReport(), std::vector<uint8_t>{0b101});
  });
}

TEST_F(HidDevTest, ConsumerControlTest) {
  driver_test().RunInEnvironmentTypeContext([](InputReportTestEnvironment& env) {
    const uint8_t* descriptor;
    size_t descriptor_size = get_buttons_report_desc(&descriptor);
    env.fake_hid().SetReportDesc(ToBinaryVector(descriptor, descriptor_size));

    // Create the initial report that will be queried on OpenSession.
    struct buttons_input_rpt report = {};
    report.rpt_id = BUTTONS_RPT_ID_INPUT;
    env.fake_hid().SetReport(ToBinaryVector(report));
  });
  ASSERT_TRUE(driver_test().StartDriver().is_ok());

  auto sync_client = GetSyncClient();

  // Get the report descriptor.
  fidl::WireResult<fuchsia_input_report::InputDevice::GetDescriptor> result =
      sync_client->GetDescriptor();
  ASSERT_OK(result.status());
  fuchsia_input_report::wire::DeviceDescriptor& desc = result.value().descriptor;
  ASSERT_TRUE(desc.has_consumer_control());
  ASSERT_TRUE(desc.consumer_control().has_input());
  fuchsia_input_report::wire::ConsumerControlInputDescriptor& consumer_control_desc =
      desc.consumer_control().input();
  ASSERT_TRUE(consumer_control_desc.has_buttons());
  ASSERT_EQ(5UL, consumer_control_desc.buttons().size());

  ASSERT_EQ(consumer_control_desc.buttons()[0],
            fuchsia_input_report::wire::ConsumerControlButton::kVolumeUp);
  ASSERT_EQ(consumer_control_desc.buttons()[1],
            fuchsia_input_report::wire::ConsumerControlButton::kVolumeDown);
  ASSERT_EQ(consumer_control_desc.buttons()[2],
            fuchsia_input_report::wire::ConsumerControlButton::kFactoryReset);
  ASSERT_EQ(consumer_control_desc.buttons()[3],
            fuchsia_input_report::wire::ConsumerControlButton::kCameraDisable);
  ASSERT_EQ(consumer_control_desc.buttons()[4],
            fuchsia_input_report::wire::ConsumerControlButton::kMicMute);

  fidl::WireSyncClient<fuchsia_input_report::InputReportsReader> reader(GetReader(sync_client));

  // Create another report.
  struct buttons_input_rpt report = {};
  report.rpt_id = BUTTONS_RPT_ID_INPUT;
  fill_button_in_report(fuchsia_buttons::GpioButtonId::kVolumeUp, true, &report);
  fill_button_in_report(fuchsia_buttons::GpioButtonId::kFdr, true, &report);
  fill_button_in_report(fuchsia_buttons::GpioButtonId::kMicMute, true, &report);

  SendReport(ToBinaryVector(report));

  // Get the report.
  auto report_result = reader->ReadInputReports();
  ASSERT_OK(report_result.status());

  const fidl::VectorView<fuchsia_input_report::wire::InputReport>& reports =
      report_result->value()->reports;
  ASSERT_EQ(2UL, reports.size());

  // Check the initial report.
  {
    ASSERT_TRUE(reports[0].has_consumer_control());
    const auto& report = reports[0].consumer_control();
    EXPECT_TRUE(report.has_pressed_buttons());
    EXPECT_EQ(0UL, report.pressed_buttons().size());
  }

  // Check the second report.
  {
    ASSERT_TRUE(reports[1].has_consumer_control());
    const auto& report = reports[1].consumer_control();
    EXPECT_TRUE(report.has_pressed_buttons());
    EXPECT_EQ(3UL, report.pressed_buttons().size());

    EXPECT_EQ(report.pressed_buttons()[0],
              fuchsia_input_report::wire::ConsumerControlButton::kVolumeUp);
    EXPECT_EQ(report.pressed_buttons()[1],
              fuchsia_input_report::wire::ConsumerControlButton::kFactoryReset);
    EXPECT_EQ(report.pressed_buttons()[2],
              fuchsia_input_report::wire::ConsumerControlButton::kMicMute);
  }
}

TEST_F(HidDevTest, ConsumerControlTwoClientsTest) {
  driver_test().RunInEnvironmentTypeContext([](InputReportTestEnvironment& env) {
    const uint8_t* descriptor;
    size_t descriptor_size = get_buttons_report_desc(&descriptor);
    env.fake_hid().SetReportDesc(ToBinaryVector(descriptor, descriptor_size));

    // Create the initial report that will be queried on OpenSession.
    struct buttons_input_rpt report = {};
    report.rpt_id = BUTTONS_RPT_ID_INPUT;
    env.fake_hid().SetReport(ToBinaryVector(report));
  });
  ASSERT_TRUE(driver_test().StartDriver().is_ok());

  // Open the device.
  auto client = GetSyncClient();

  fidl::WireSyncClient<fuchsia_input_report::InputReportsReader> reader1(GetReader(client));
  {
    auto report_result = reader1->ReadInputReports();
    ASSERT_OK(report_result.status());
    const fidl::VectorView<fuchsia_input_report::wire::InputReport>& reports =
        report_result->value()->reports;
    ASSERT_EQ(1UL, reports.size());

    ASSERT_TRUE(reports[0].has_consumer_control());
    const auto& report = reports[0].consumer_control();
    EXPECT_TRUE(report.has_pressed_buttons());
    EXPECT_EQ(0UL, report.pressed_buttons().size());
  }

  fidl::WireSyncClient<fuchsia_input_report::InputReportsReader> reader2(GetReader(client));
  {
    auto report_result = reader2->ReadInputReports();
    ASSERT_OK(report_result.status());
    const fidl::VectorView<fuchsia_input_report::wire::InputReport>& reports =
        report_result->value()->reports;
    ASSERT_EQ(1UL, reports.size());

    ASSERT_TRUE(reports[0].has_consumer_control());
    const auto& report = reports[0].consumer_control();
    EXPECT_TRUE(report.has_pressed_buttons());
    EXPECT_EQ(0UL, report.pressed_buttons().size());
  }

  // Create another report.
  struct buttons_input_rpt report = {};
  report.rpt_id = BUTTONS_RPT_ID_INPUT;
  fill_button_in_report(fuchsia_buttons::GpioButtonId::kVolumeUp, true, &report);
  fill_button_in_report(fuchsia_buttons::GpioButtonId::kFdr, true, &report);
  fill_button_in_report(fuchsia_buttons::GpioButtonId::kMicMute, true, &report);

  SendReport(std::vector<uint8_t>(reinterpret_cast<uint8_t*>(&report),
                                  reinterpret_cast<uint8_t*>(&report) + sizeof(report)));

  {
    auto report_result = reader1->ReadInputReports();
    ASSERT_OK(report_result.status());
    const fidl::VectorView<fuchsia_input_report::wire::InputReport>& reports =
        report_result->value()->reports;
    ASSERT_EQ(1UL, reports.size());
    ASSERT_TRUE(reports[0].has_consumer_control());
    const auto& report = reports[0].consumer_control();
    EXPECT_TRUE(report.has_pressed_buttons());
    EXPECT_EQ(3UL, report.pressed_buttons().size());

    EXPECT_EQ(report.pressed_buttons()[0],
              fuchsia_input_report::wire::ConsumerControlButton::kVolumeUp);
    EXPECT_EQ(report.pressed_buttons()[1],
              fuchsia_input_report::wire::ConsumerControlButton::kFactoryReset);
    EXPECT_EQ(report.pressed_buttons()[2],
              fuchsia_input_report::wire::ConsumerControlButton::kMicMute);
  }
  {
    auto report_result = reader2->ReadInputReports();
    ASSERT_OK(report_result.status());
    const fidl::VectorView<fuchsia_input_report::wire::InputReport>& reports =
        report_result->value()->reports;
    ASSERT_EQ(1UL, reports.size());
    ASSERT_TRUE(reports[0].has_consumer_control());
    const auto& report = reports[0].consumer_control();
    EXPECT_TRUE(report.has_pressed_buttons());
    EXPECT_EQ(3UL, report.pressed_buttons().size());

    EXPECT_EQ(report.pressed_buttons()[0],
              fuchsia_input_report::wire::ConsumerControlButton::kVolumeUp);
    EXPECT_EQ(report.pressed_buttons()[1],
              fuchsia_input_report::wire::ConsumerControlButton::kFactoryReset);
    EXPECT_EQ(report.pressed_buttons()[2],
              fuchsia_input_report::wire::ConsumerControlButton::kMicMute);
  }
}

TEST_F(HidDevTest, TouchLatencyMeasurements) {
  driver_test().RunInEnvironmentTypeContext([](InputReportTestEnvironment& env) {
    const uint8_t* report_desc;
    const size_t desc_len = get_gt92xx_report_desc(&report_desc);
    env.fake_hid().SetReportDesc(ToBinaryVector(report_desc, desc_len));
  });
  ASSERT_TRUE(driver_test().StartDriver().is_ok());

  using namespace inspect::testing;
  driver_test().RunInDriverContext([](InputReportDriver& driver) {
    auto hierarchy = inspect::ReadFromVmo(driver.input_report_for_testing().InspectVmo());
    EXPECT_TRUE(hierarchy.is_ok());
  });

  // Send five reports, and verify that the inspect stats make sense.
  gt92xx_touch_t report = {};

  // Add some additional computed latency to make the results more realistic.
  const zx::time timestamp = zx::clock::get_monotonic() - zx::msec(15);

  SendReport(ToBinaryVector(report), timestamp);
  SendReport(ToBinaryVector(report), timestamp);
  SendReport(ToBinaryVector(report), timestamp);
  SendReport(ToBinaryVector(report), timestamp);
  SendReport(ToBinaryVector(report), timestamp - zx::msec(5));

  driver_test().RunInDriverContext([](InputReportDriver& driver) {
    auto hierarchy = inspect::ReadFromVmo(driver.input_report_for_testing().InspectVmo());
    EXPECT_TRUE(hierarchy.is_ok());
    const inspect::Hierarchy* root = hierarchy.value().GetByPath({"hid-input-report-touch"});
    ASSERT_TRUE(root);

    const auto* latency_histogram =
        root->node().get_property<inspect::UintArrayValue>("latency_histogram_usecs");
    ASSERT_TRUE(latency_histogram);
    uint64_t latency_bucket_sum = 0;
    for (const inspect::UintArrayValue::HistogramBucket& bucket : latency_histogram->GetBuckets()) {
      latency_bucket_sum += bucket.count;
    }

    EXPECT_EQ(latency_bucket_sum, 5UL);

    const auto* average_latency =
        root->node().get_property<inspect::UintPropertyValue>("average_latency_usecs");
    ASSERT_TRUE(average_latency);

    const auto* max_latency =
        root->node().get_property<inspect::UintPropertyValue>("max_latency_usecs");
    ASSERT_TRUE(max_latency);

    EXPECT_GE(max_latency->value(), average_latency->value());
  });
}

TEST_F(HidDevTest, InspectDeviceTypes) {
  driver_test().RunInEnvironmentTypeContext([](InputReportTestEnvironment& env) {
    size_t desc_len;
    const uint8_t* report_desc = get_paradise_touch_report_desc(&desc_len);
    env.fake_hid().SetReportDesc(ToBinaryVector(report_desc, desc_len));
  });
  ASSERT_TRUE(driver_test().StartDriver().is_ok());

  driver_test().RunInDriverContext([](InputReportDriver& driver) {
    auto hierarchy = inspect::ReadFromVmo(driver.input_report_for_testing().InspectVmo());
    EXPECT_TRUE(hierarchy.is_ok());
    const inspect::Hierarchy* root =
        hierarchy.value().GetByPath({"hid-input-report-touch,touch,mouse"});
    ASSERT_TRUE(root);

    const auto* device_types =
        root->node().get_property<inspect::StringPropertyValue>("device_types");
    ASSERT_TRUE(device_types);

    EXPECT_STREQ(device_types->value().c_str(), "touch,touch,mouse");
  });
}

TEST_F(HidDevTest, GetInputReport) {
  driver_test().RunInEnvironmentTypeContext([](InputReportTestEnvironment& env) {
    const uint8_t* sensor_desc_ptr;
    size_t sensor_desc_size = get_ambient_light_report_desc(&sensor_desc_ptr);
    env.fake_hid().SetReportDesc(ToBinaryVector(sensor_desc_ptr, sensor_desc_size));
  });
  ASSERT_TRUE(driver_test().StartDriver().is_ok());

  auto sync_client = GetSyncClient();

  const int kIlluminanceTestVal = 10;
  const int kRedTestVal = 101;
  const int kBlueTestVal = 5;
  const int kGreenTestVal = 3;
  driver_test().RunInEnvironmentTypeContext([](InputReportTestEnvironment& env) {
    ambient_light_input_rpt_t report_data = {};
    report_data.rpt_id = AMBIENT_LIGHT_RPT_ID_INPUT;
    report_data.illuminance = kIlluminanceTestVal;
    report_data.red = kRedTestVal;
    report_data.blue = kBlueTestVal;
    report_data.green = kGreenTestVal;
    env.fake_hid().SetReport(ToBinaryVector(report_data));
  });

  {
    const auto report_result =
        sync_client->GetInputReport(fuchsia_input_report::wire::DeviceType::kSensor);
    ASSERT_TRUE(report_result.ok());

    ASSERT_TRUE(report_result->is_ok());
    const auto& report = report_result->value()->report;

    ASSERT_TRUE(report.has_sensor());
    const fuchsia_input_report::wire::SensorInputReport& sensor_report = report.sensor();
    EXPECT_TRUE(sensor_report.has_values());
    EXPECT_EQ(4UL, sensor_report.values().size());

    EXPECT_EQ(kIlluminanceTestVal, sensor_report.values()[0]);
    EXPECT_EQ(kRedTestVal, sensor_report.values()[1]);
    EXPECT_EQ(kBlueTestVal, sensor_report.values()[2]);
    EXPECT_EQ(kGreenTestVal, sensor_report.values()[3]);
  }

  {
    // Requesting a different device type should fail.
    const auto result = sync_client->GetInputReport(fuchsia_input_report::wire::DeviceType::kTouch);
    ASSERT_TRUE(result.ok());
    EXPECT_TRUE(result->is_error());
  }
}

TEST_F(HidDevTest, GetInputReportMultipleDevices) {
  driver_test().RunInEnvironmentTypeContext([](InputReportTestEnvironment& env) {
    size_t touch_desc_size;
    const uint8_t* touch_desc_ptr = get_acer12_touch_report_desc(&touch_desc_size);
    env.fake_hid().SetReportDesc(ToBinaryVector(touch_desc_ptr, touch_desc_size));
  });
  ASSERT_TRUE(driver_test().StartDriver().is_ok());

  auto sync_client = GetSyncClient();

  driver_test().RunInEnvironmentTypeContext([](InputReportTestEnvironment& env) {
    acer12_stylus_t report_data = {};
    report_data.rpt_id = ACER12_RPT_ID_STYLUS;
    report_data.status = 0;
    report_data.x = 1;
    report_data.y = 2;
    report_data.pressure = 3;
    env.fake_hid().SetReport(ToBinaryVector(report_data));
  });

  // There are two devices with this type (finger and stylus), so this should fail.
  const auto result = sync_client->GetInputReport(fuchsia_input_report::wire::DeviceType::kTouch);
  ASSERT_TRUE(result.ok());
  EXPECT_TRUE(result->is_error());
}

}  // namespace hid_input_report_dev
