// 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 <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/async/default.h>
#include <lib/async_patterns/testing/cpp/dispatcher_bound.h>
#include <lib/ddk/platform-defs.h>
#include <lib/fit/defer.h>

#include <set>

#include <virtio/input.h>
#include <zxtest/zxtest.h>

#include "input_kbd.h"
#include "input_mouse.h"
#include "input_touch.h"

#define CHECK_AXIS(axis, name, range_min, range_max, unit_type, uint_exponent) \
  ASSERT_TRUE((axis).has_##name());                                            \
  EXPECT_EQ((axis).name().range.min, (range_min));                             \
  EXPECT_EQ((axis).name().range.max, (range_max));                             \
  EXPECT_EQ((axis).name().unit.type, (unit_type));                             \
  EXPECT_EQ((axis).name().unit.exponent, (uint_exponent));

namespace virtio {

namespace {

void SendTouchEvent(async_patterns::TestDispatcherBound<HidTouch>& touch, uint16_t type,
                    uint16_t code, uint32_t value) {
  virtio_input_event_t event = {};
  event.type = type;
  event.code = code;
  event.value = value;

  touch.SyncCall([&](HidDeviceBase* device) { device->ReceiveEvent(&event); });
}

}  // namespace

class VirtioInputTest : public zxtest::Test {
 public:
  VirtioInputTest()
      : loop_(&kAsyncLoopConfigNoAttachToCurrentThread),
        input_report_loop_(&kAsyncLoopConfigNoAttachToCurrentThread) {}

  void SetUp() override { loop_.StartThread("virtio-input-test-loop"); }

  class ReaderV2EventHandler
      : public fidl::WireAsyncEventHandler<fuchsia_input_report::InputReportsReaderV2> {
   public:
    explicit ReaderV2EventHandler(
        fit::function<
            void(fidl::WireEvent<fuchsia_input_report::InputReportsReaderV2::OnInputReports>*)>
            callback)
        : callback_(std::move(callback)) {}

    void SetCallback(
        fit::function<
            void(fidl::WireEvent<fuchsia_input_report::InputReportsReaderV2::OnInputReports>*)>
            callback) {
      callback_ = std::move(callback);
    }

    void OnInputReports(fidl::WireEvent<fuchsia_input_report::InputReportsReaderV2::OnInputReports>*
                            event) override {
      if (callback_) {
        callback_(event);
      }
    }

    void handle_unknown_event(
        fidl::UnknownEventMetadata<fuchsia_input_report::InputReportsReaderV2> metadata) override {}

   private:
    fit::function<void(
        fidl::WireEvent<fuchsia_input_report::InputReportsReaderV2::OnInputReports>*)>
        callback_;
  };

  template <typename HidDeviceType>
  fidl::WireClient<fuchsia_input_report::InputReportsReaderV2> GetReader(
      HidDeviceType& device, std::shared_ptr<ReaderV2EventHandler> event_handler) {
    fidl::Endpoints<fuchsia_input_report::InputReportsReaderV2> reader_endpoints =
        fidl::Endpoints<fuchsia_input_report::InputReportsReaderV2>::Create();

    device.SyncCall([&](HidDeviceBase* device) {
      EXPECT_EQ(ZX_OK, device->GetInputReportsReaderV2(async_get_default_dispatcher(),
                                                       std::move(reader_endpoints.server), 50));
    });
    fidl::WireClient<fuchsia_input_report::InputReportsReaderV2> reader(
        std::move(reader_endpoints.client), input_report_loop_.dispatcher(), event_handler.get());
    EXPECT_OK(input_report_loop_.RunUntilIdle());

    return reader;
  }

 protected:
  async::Loop loop_;
  async::Loop input_report_loop_;
};

TEST_F(VirtioInputTest, MultiTouchReportDescriptor) {
  virtio_input_absinfo_t x_info = {};
  virtio_input_absinfo_t y_info = {};
  HidTouch touch(x_info, y_info, std::string("test_product"), std::string("test_serial"));

  fidl::Arena<> allocator;
  auto descriptor = touch.GetDescriptor(allocator);

  // Assert that the report descriptor is correct.
  EXPECT_FALSE(descriptor.has_consumer_control());
  EXPECT_FALSE(descriptor.has_keyboard());
  EXPECT_FALSE(descriptor.has_mouse());
  EXPECT_FALSE(descriptor.has_sensor());

  ASSERT_TRUE(descriptor.has_device_information());
  EXPECT_EQ(descriptor.device_information().vendor_id(),
            static_cast<uint32_t>(fuchsia_input_report::wire::VendorId::kGoogle));
  EXPECT_EQ(
      descriptor.device_information().product_id(),
      static_cast<uint32_t>(fuchsia_input_report::wire::VendorGoogleProductId::kVirtioTouchscreen));

  ASSERT_TRUE(descriptor.has_touch());
  EXPECT_FALSE(descriptor.touch().has_feature());
  ASSERT_TRUE(descriptor.touch().has_input());
  ASSERT_TRUE(descriptor.touch().input().has_touch_type());
  EXPECT_EQ(descriptor.touch().input().touch_type(), fuchsia_input_report::TouchType::kTouchscreen);
  EXPECT_FALSE(descriptor.touch().input().has_buttons());
  ASSERT_TRUE(descriptor.touch().input().has_contacts());
  ASSERT_EQ(descriptor.touch().input().contacts().size(), kMaxTouchPoints);
  for (const auto& contact : descriptor.touch().input().contacts()) {
    EXPECT_FALSE(contact.has_contact_height());
    EXPECT_FALSE(contact.has_contact_width());
    EXPECT_FALSE(contact.has_pressure());

    CHECK_AXIS(contact, position_x, 0L, 259200L, fuchsia_input::wire::UnitType::kMeters, -6)
    CHECK_AXIS(contact, position_y, 0L, 172800L, fuchsia_input::wire::UnitType::kMeters, -6)
  }
}

TEST_F(VirtioInputTest, MultiTouchFingerEvents) {
  constexpr int VAL_MAX = 100;
  constexpr int X_VAL = 50;
  constexpr int Y_VAL = 100;
  virtio_input_absinfo_t x_info = {};
  x_info.min = 0;
  x_info.max = static_cast<uint16_t>(VAL_MAX);
  virtio_input_absinfo_t y_info = {};
  y_info.min = 0;
  y_info.max = static_cast<uint16_t>(VAL_MAX);
  async_patterns::TestDispatcherBound<HidTouch> touch{
      loop_.dispatcher(),        std::in_place, x_info, y_info, std::string{"test_product"},
      std::string{"test_serial"}};
  std::shared_ptr<ReaderV2EventHandler> event_handler =
      std::make_shared<ReaderV2EventHandler>(nullptr);
  fidl::WireClient<fuchsia_input_report::InputReportsReaderV2> reader =
      GetReader(touch, event_handler);

  // Assert that a single finger works.
  SendTouchEvent(touch, VIRTIO_INPUT_EV_ABS, VIRTIO_INPUT_EV_MT_SLOT, 0);
  SendTouchEvent(touch, VIRTIO_INPUT_EV_ABS, VIRTIO_INPUT_EV_MT_TRACKING_ID, 1);
  SendTouchEvent(touch, VIRTIO_INPUT_EV_ABS, VIRTIO_INPUT_EV_MT_POSITION_X,
                 static_cast<uint16_t>(X_VAL));
  SendTouchEvent(touch, VIRTIO_INPUT_EV_ABS, VIRTIO_INPUT_EV_MT_POSITION_Y,
                 static_cast<uint16_t>(Y_VAL));

  event_handler->SetCallback(
      [&](fidl::WireEvent<fuchsia_input_report::InputReportsReaderV2::OnInputReports>* event) {
        const fidl::VectorView<fuchsia_input_report::wire::InputReport>& reports = event->reports;

        ASSERT_EQ(reports.size(), 1u);
        const fuchsia_input_report::wire::InputReport& report = reports[0];

        ASSERT_TRUE(report.has_event_time());
        ASSERT_TRUE(report.has_touch());
        const fuchsia_input_report::wire::TouchInputReport& touch_report = report.touch();

        ASSERT_TRUE(touch_report.has_contacts());
        ASSERT_EQ(touch_report.contacts().size(), 1u);
        EXPECT_EQ(touch_report.contacts()[0].contact_id(), 0u);
        EXPECT_EQ(touch_report.contacts()[0].position_x(),
                  X_VAL * HidTouch::kXPhysicalMaxMicrometer / VAL_MAX);
        EXPECT_EQ(touch_report.contacts()[0].position_y(),
                  Y_VAL * HidTouch::kYPhysicalMaxMicrometer / VAL_MAX);

        input_report_loop_.Quit();
      });

  touch.SyncCall(&HidDeviceBase::SendReportToAllReaders);
  EXPECT_EQ(input_report_loop_.Run(), ZX_ERR_CANCELED);
  EXPECT_OK(input_report_loop_.ResetQuit());

  // Assert that a second finger tracks.
  SendTouchEvent(touch, VIRTIO_INPUT_EV_ABS, VIRTIO_INPUT_EV_MT_SLOT, 1);
  SendTouchEvent(touch, VIRTIO_INPUT_EV_ABS, VIRTIO_INPUT_EV_MT_TRACKING_ID, 2);

  event_handler->SetCallback(
      [&](fidl::WireEvent<fuchsia_input_report::InputReportsReaderV2::OnInputReports>* event) {
        const fidl::VectorView<fuchsia_input_report::wire::InputReport>& reports = event->reports;

        ASSERT_EQ(reports.size(), 1u);
        const fuchsia_input_report::wire::InputReport& report = reports[0];

        ASSERT_TRUE(report.has_event_time());
        ASSERT_TRUE(report.has_touch());
        const fuchsia_input_report::wire::TouchInputReport& touch_report = report.touch();

        ASSERT_TRUE(touch_report.has_contacts());
        ASSERT_EQ(touch_report.contacts().size(), 2u);
        EXPECT_EQ(touch_report.contacts()[0].contact_id(), 0u);
        EXPECT_EQ(touch_report.contacts()[0].position_x(),
                  X_VAL * HidTouch::kXPhysicalMaxMicrometer / VAL_MAX);
        EXPECT_EQ(touch_report.contacts()[0].position_y(),
                  Y_VAL * HidTouch::kYPhysicalMaxMicrometer / VAL_MAX);
        EXPECT_EQ(touch_report.contacts()[1].contact_id(), 1u);

        input_report_loop_.Quit();
      });

  touch.SyncCall(&HidDeviceBase::SendReportToAllReaders);
  EXPECT_EQ(input_report_loop_.Run(), ZX_ERR_CANCELED);
  EXPECT_OK(input_report_loop_.ResetQuit());

  // Pick up the second finger.

  // We don't send another SLOT event because we will rely on the slot already
  // being 1.
  SendTouchEvent(touch, VIRTIO_INPUT_EV_ABS, VIRTIO_INPUT_EV_MT_TRACKING_ID, -1);

  event_handler->SetCallback(
      [&](fidl::WireEvent<fuchsia_input_report::InputReportsReaderV2::OnInputReports>* event) {
        const fidl::VectorView<fuchsia_input_report::wire::InputReport>& reports = event->reports;

        ASSERT_EQ(reports.size(), 1u);
        const fuchsia_input_report::wire::InputReport& report = reports[0];

        ASSERT_TRUE(report.has_event_time());
        ASSERT_TRUE(report.has_touch());
        const fuchsia_input_report::wire::TouchInputReport& touch_report = report.touch();

        ASSERT_TRUE(touch_report.has_contacts());
        ASSERT_EQ(touch_report.contacts().size(), 1u);
        EXPECT_EQ(touch_report.contacts()[0].contact_id(), 0u);
        EXPECT_EQ(touch_report.contacts()[0].position_x(),
                  X_VAL * HidTouch::kXPhysicalMaxMicrometer / VAL_MAX);
        EXPECT_EQ(touch_report.contacts()[0].position_y(),
                  Y_VAL * HidTouch::kYPhysicalMaxMicrometer / VAL_MAX);

        input_report_loop_.Quit();
      });

  touch.SyncCall(&HidDeviceBase::SendReportToAllReaders);
  EXPECT_EQ(input_report_loop_.Run(), ZX_ERR_CANCELED);
  EXPECT_OK(input_report_loop_.ResetQuit());

  // Out of bounds slot. GetReport values shouldn't change.
  int NEW_X_VAL = 100;
  int NEW_Y_VAL = 50;
  SendTouchEvent(touch, VIRTIO_INPUT_EV_ABS, VIRTIO_INPUT_EV_MT_SLOT, 5);
  SendTouchEvent(touch, VIRTIO_INPUT_EV_ABS, VIRTIO_INPUT_EV_MT_TRACKING_ID, 1);
  SendTouchEvent(touch, VIRTIO_INPUT_EV_ABS, VIRTIO_INPUT_EV_MT_POSITION_X,
                 static_cast<uint16_t>(NEW_X_VAL));
  SendTouchEvent(touch, VIRTIO_INPUT_EV_ABS, VIRTIO_INPUT_EV_MT_POSITION_Y,
                 static_cast<uint16_t>(NEW_Y_VAL));

  event_handler->SetCallback(
      [&](fidl::WireEvent<fuchsia_input_report::InputReportsReaderV2::OnInputReports>* event) {
        const fidl::VectorView<fuchsia_input_report::wire::InputReport>& reports = event->reports;

        ASSERT_EQ(reports.size(), 1u);
        const fuchsia_input_report::wire::InputReport& report = reports[0];

        ASSERT_TRUE(report.has_event_time());
        ASSERT_TRUE(report.has_touch());
        const fuchsia_input_report::wire::TouchInputReport& touch_report = report.touch();

        ASSERT_TRUE(touch_report.has_contacts());
        ASSERT_EQ(touch_report.contacts().size(), 1u);
        EXPECT_EQ(touch_report.contacts()[0].contact_id(), 0u);
        EXPECT_EQ(touch_report.contacts()[0].position_x(),
                  X_VAL * HidTouch::kXPhysicalMaxMicrometer / VAL_MAX);
        EXPECT_EQ(touch_report.contacts()[0].position_y(),
                  Y_VAL * HidTouch::kYPhysicalMaxMicrometer / VAL_MAX);

        input_report_loop_.Quit();
      });

  touch.SyncCall(&HidDeviceBase::SendReportToAllReaders);
  EXPECT_EQ(input_report_loop_.Run(), ZX_ERR_CANCELED);
}

TEST_F(VirtioInputTest, MouseReportDescriptor) {
  HidMouse hid_mouse(std::string("test_product"), std::string("test_serial"));
  fidl::Arena<> allocator;
  auto descriptor = hid_mouse.GetDescriptor(allocator);

  // Assert that the report descriptor is correct.
  EXPECT_FALSE(descriptor.has_consumer_control());
  EXPECT_FALSE(descriptor.has_keyboard());
  EXPECT_FALSE(descriptor.has_sensor());
  EXPECT_FALSE(descriptor.has_touch());

  ASSERT_TRUE(descriptor.has_device_information());
  EXPECT_EQ(descriptor.device_information().vendor_id(),
            static_cast<uint32_t>(fuchsia_input_report::wire::VendorId::kGoogle));
  EXPECT_EQ(descriptor.device_information().product_id(),
            static_cast<uint32_t>(fuchsia_input_report::wire::VendorGoogleProductId::kVirtioMouse));

  ASSERT_TRUE(descriptor.has_mouse());
  ASSERT_TRUE(descriptor.mouse().has_input());
  EXPECT_FALSE(descriptor.mouse().input().has_position_x());
  EXPECT_FALSE(descriptor.mouse().input().has_position_y());
  EXPECT_FALSE(descriptor.mouse().input().has_scroll_h());
  ASSERT_TRUE(descriptor.mouse().input().has_buttons());
  const std::set<uint8_t> kExpectedButtons = {1, 2, 3};
  EXPECT_TRUE(std::set(descriptor.mouse().input().buttons().begin(),
                       descriptor.mouse().input().buttons().end()) == kExpectedButtons);
  CHECK_AXIS(descriptor.mouse().input(), movement_x, -32767L, 32767L,
             fuchsia_input::wire::UnitType::kNone, 0)
  CHECK_AXIS(descriptor.mouse().input(), movement_y, -32767L, 32767L,
             fuchsia_input::wire::UnitType::kNone, 0)
  CHECK_AXIS(descriptor.mouse().input(), scroll_v, -32767L, 32767L,
             fuchsia_input::wire::UnitType::kNone, 0)
}

TEST_F(VirtioInputTest, MouseTest) {
  async_patterns::TestDispatcherBound<HidMouse> hid_mouse{
      loop_.dispatcher(), std::in_place, std::string("test_product"), std::string("test_serial")};
  std::shared_ptr<ReaderV2EventHandler> event_handler =
      std::make_shared<ReaderV2EventHandler>(nullptr);
  fidl::WireClient<fuchsia_input_report::InputReportsReaderV2> reader =
      GetReader(hid_mouse, event_handler);

  // Send the Virtio mouse keys.
  virtio_input_event_t event = {};
  event.type = VIRTIO_INPUT_EV_KEY;
  event.value = VIRTIO_INPUT_EV_KEY_PRESSED;
  event.code = 0x110;  // BTN_LEFT.
  hid_mouse.SyncCall([&](HidDeviceBase* device) { device->ReceiveEvent(&event); });

  event_handler->SetCallback(
      [&](fidl::WireEvent<fuchsia_input_report::InputReportsReaderV2::OnInputReports>* event) {
        const fidl::VectorView<fuchsia_input_report::wire::InputReport>& reports = event->reports;

        ASSERT_EQ(reports.size(), 1u);
        const fuchsia_input_report::wire::InputReport& report = reports[0];

        ASSERT_TRUE(report.has_event_time());
        ASSERT_TRUE(report.has_mouse());
        const fuchsia_input_report::wire::MouseInputReport& mouse_report = report.mouse();

        ASSERT_TRUE(mouse_report.has_pressed_buttons());
        ASSERT_EQ(mouse_report.pressed_buttons().size(), 1u);
        EXPECT_EQ(mouse_report.pressed_buttons()[0], 1);

        input_report_loop_.Quit();
      });

  hid_mouse.SyncCall(&HidDeviceBase::SendReportToAllReaders);
  EXPECT_EQ(input_report_loop_.Run(), ZX_ERR_CANCELED);
  EXPECT_OK(input_report_loop_.ResetQuit());

  // ------------------------------------------------------------------

  // Send another Virtio mouse key event.
  event.type = VIRTIO_INPUT_EV_KEY;
  event.value = VIRTIO_INPUT_EV_KEY_PRESSED;
  event.code = 0x111;  // BTN_RIGHT.
  hid_mouse.SyncCall([&](HidDeviceBase* device) { device->ReceiveEvent(&event); });

  event_handler->SetCallback(
      [&](fidl::WireEvent<fuchsia_input_report::InputReportsReaderV2::OnInputReports>* event) {
        const fidl::VectorView<fuchsia_input_report::wire::InputReport>& reports = event->reports;

        ASSERT_EQ(reports.size(), 1u);
        const fuchsia_input_report::wire::InputReport& report = reports[0];

        ASSERT_TRUE(report.has_event_time());
        ASSERT_TRUE(report.has_mouse());
        const fuchsia_input_report::wire::MouseInputReport& mouse_report = report.mouse();

        ASSERT_TRUE(mouse_report.has_pressed_buttons());
        ASSERT_EQ(mouse_report.pressed_buttons().size(), 2u);
        EXPECT_EQ(mouse_report.pressed_buttons()[0], 1);
        EXPECT_EQ(mouse_report.pressed_buttons()[1], 2);

        input_report_loop_.Quit();
      });

  hid_mouse.SyncCall(&HidDeviceBase::SendReportToAllReaders);
  EXPECT_EQ(input_report_loop_.Run(), ZX_ERR_CANCELED);
  EXPECT_OK(input_report_loop_.ResetQuit());

  // ------------------------------------------------------------------

  // Release one Virtio mouse key.
  event.type = VIRTIO_INPUT_EV_KEY;
  event.value = VIRTIO_INPUT_EV_KEY_RELEASED;
  event.code = 0x110;  // BTN_LEFT.
  hid_mouse.SyncCall([&](HidDeviceBase* device) { device->ReceiveEvent(&event); });

  event_handler->SetCallback(
      [&](fidl::WireEvent<fuchsia_input_report::InputReportsReaderV2::OnInputReports>* event) {
        const fidl::VectorView<fuchsia_input_report::wire::InputReport>& reports = event->reports;

        ASSERT_EQ(reports.size(), 1u);
        const fuchsia_input_report::wire::InputReport& report = reports[0];

        ASSERT_TRUE(report.has_event_time());
        ASSERT_TRUE(report.has_mouse());
        const fuchsia_input_report::wire::MouseInputReport& mouse_report = report.mouse();

        ASSERT_TRUE(mouse_report.has_pressed_buttons());
        ASSERT_EQ(mouse_report.pressed_buttons().size(), 1u);
        EXPECT_EQ(mouse_report.pressed_buttons()[0], 2);

        input_report_loop_.Quit();
      });

  hid_mouse.SyncCall(&HidDeviceBase::SendReportToAllReaders);
  EXPECT_EQ(input_report_loop_.Run(), ZX_ERR_CANCELED);
  EXPECT_OK(input_report_loop_.ResetQuit());

  // ------------------------------------------------------------------

  // Send another Virtio mouse key event.
  event.type = VIRTIO_INPUT_EV_KEY;
  event.value = VIRTIO_INPUT_EV_KEY_PRESSED;
  event.code = 0x112;  // BTN_MID.
  hid_mouse.SyncCall([&](HidDeviceBase* device) { device->ReceiveEvent(&event); });

  event_handler->SetCallback(
      [&](fidl::WireEvent<fuchsia_input_report::InputReportsReaderV2::OnInputReports>* event) {
        const fidl::VectorView<fuchsia_input_report::wire::InputReport>& reports = event->reports;

        ASSERT_EQ(reports.size(), 1u);
        const fuchsia_input_report::wire::InputReport& report = reports[0];

        ASSERT_TRUE(report.has_event_time());
        ASSERT_TRUE(report.has_mouse());
        const fuchsia_input_report::wire::MouseInputReport& mouse_report = report.mouse();

        ASSERT_TRUE(mouse_report.has_pressed_buttons());
        ASSERT_EQ(mouse_report.pressed_buttons().size(), 2u);
        EXPECT_EQ(mouse_report.pressed_buttons()[0], 2);
        EXPECT_EQ(mouse_report.pressed_buttons()[1], 3);

        input_report_loop_.Quit();
      });

  hid_mouse.SyncCall(&HidDeviceBase::SendReportToAllReaders);
  EXPECT_EQ(input_report_loop_.Run(), ZX_ERR_CANCELED);
  EXPECT_OK(input_report_loop_.ResetQuit());

  // ------------------------------------------------------------------

  // Send a Virtio mouse rel event on X axis.
  event.type = VIRTIO_INPUT_EV_REL;
  event.code = VIRTIO_INPUT_EV_REL_X;
  event.value = 0x0abc;
  hid_mouse.SyncCall([&](HidDeviceBase* device) { device->ReceiveEvent(&event); });

  event_handler->SetCallback(
      [&](fidl::WireEvent<fuchsia_input_report::InputReportsReaderV2::OnInputReports>* event) {
        const fidl::VectorView<fuchsia_input_report::wire::InputReport>& reports = event->reports;

        ASSERT_EQ(reports.size(), 1u);
        const fuchsia_input_report::wire::InputReport& report = reports[0];

        ASSERT_TRUE(report.has_event_time());
        ASSERT_TRUE(report.has_mouse());
        const fuchsia_input_report::wire::MouseInputReport& mouse_report = report.mouse();

        ASSERT_TRUE(mouse_report.has_movement_x());
        EXPECT_EQ(mouse_report.movement_x(), 0x0abc);

        input_report_loop_.Quit();
      });

  hid_mouse.SyncCall(&HidDeviceBase::SendReportToAllReaders);
  EXPECT_EQ(input_report_loop_.Run(), ZX_ERR_CANCELED);
  EXPECT_OK(input_report_loop_.ResetQuit());

  // ------------------------------------------------------------------

  // Send a Virtio mouse rel event on Y axis.
  event.type = VIRTIO_INPUT_EV_REL;
  event.code = VIRTIO_INPUT_EV_REL_Y;
  event.value = 0x0123;
  hid_mouse.SyncCall([&](HidDeviceBase* device) { device->ReceiveEvent(&event); });

  event_handler->SetCallback(
      [&](fidl::WireEvent<fuchsia_input_report::InputReportsReaderV2::OnInputReports>* event) {
        const fidl::VectorView<fuchsia_input_report::wire::InputReport>& reports = event->reports;

        ASSERT_EQ(reports.size(), 1u);
        const fuchsia_input_report::wire::InputReport& report = reports[0];

        ASSERT_TRUE(report.has_event_time());
        ASSERT_TRUE(report.has_mouse());
        const fuchsia_input_report::wire::MouseInputReport& mouse_report = report.mouse();

        ASSERT_TRUE(mouse_report.has_movement_y());
        EXPECT_EQ(mouse_report.movement_y(), 0x0123);

        input_report_loop_.Quit();
      });

  hid_mouse.SyncCall(&HidDeviceBase::SendReportToAllReaders);
  EXPECT_EQ(input_report_loop_.Run(), ZX_ERR_CANCELED);
  EXPECT_OK(input_report_loop_.ResetQuit());

  // ------------------------------------------------------------------

  // Send a Virtio mouse rel event on wheel.
  event.type = VIRTIO_INPUT_EV_REL;
  event.code = VIRTIO_INPUT_EV_REL_WHEEL;
  event.value = 0x0345;
  hid_mouse.SyncCall([&](HidDeviceBase* device) { device->ReceiveEvent(&event); });

  event_handler->SetCallback(
      [&](fidl::WireEvent<fuchsia_input_report::InputReportsReaderV2::OnInputReports>* event) {
        const fidl::VectorView<fuchsia_input_report::wire::InputReport>& reports = event->reports;

        ASSERT_EQ(reports.size(), 1u);
        const fuchsia_input_report::wire::InputReport& report = reports[0];

        ASSERT_TRUE(report.has_event_time());
        ASSERT_TRUE(report.has_mouse());
        const fuchsia_input_report::wire::MouseInputReport& mouse_report = report.mouse();

        ASSERT_TRUE(mouse_report.has_scroll_v());
        EXPECT_EQ(mouse_report.scroll_v(), 0x0345);

        input_report_loop_.Quit();
      });

  hid_mouse.SyncCall(&HidDeviceBase::SendReportToAllReaders);
  EXPECT_EQ(input_report_loop_.Run(), ZX_ERR_CANCELED);
}

TEST_F(VirtioInputTest, KeyboardReportDescriptor) {
  HidKeyboard hid_keyboard(std::string("test_product"), std::string("test_serial"));
  fidl::Arena<> allocator;
  auto descriptor = hid_keyboard.GetDescriptor(allocator);

  // Assert that the report descriptor is correct.
  EXPECT_FALSE(descriptor.has_consumer_control());
  EXPECT_FALSE(descriptor.has_mouse());
  EXPECT_FALSE(descriptor.has_sensor());
  EXPECT_FALSE(descriptor.has_touch());

  ASSERT_TRUE(descriptor.has_device_information());
  EXPECT_EQ(descriptor.device_information().vendor_id(),
            static_cast<uint32_t>(fuchsia_input_report::wire::VendorId::kGoogle));
  EXPECT_EQ(
      descriptor.device_information().product_id(),
      static_cast<uint32_t>(fuchsia_input_report::wire::VendorGoogleProductId::kVirtioKeyboard));

  ASSERT_TRUE(descriptor.has_keyboard());
  EXPECT_FALSE(descriptor.keyboard().has_output());
  ASSERT_TRUE(descriptor.keyboard().has_input());
  ASSERT_TRUE(descriptor.keyboard().input().has_keys3());
  std::set<fuchsia_input::Key> kExpectedKeys;
  for (auto k = fuchsia_input::Key::kA; k < fuchsia_input::Key::kNonUsBackslash;
       k = static_cast<fuchsia_input::Key>(static_cast<uint32_t>(k) + 1)) {
    kExpectedKeys.insert(k);
  }
  kExpectedKeys.erase(fuchsia_input::Key::kNonUsHash);
  kExpectedKeys.erase(fuchsia_input::Key::kPrintScreen);
  kExpectedKeys.erase(fuchsia_input::Key::kKeypadSlash);
  kExpectedKeys.erase(fuchsia_input::Key::kKeypadEnter);
  for (auto k = fuchsia_input::Key::kLeftCtrl; k <= fuchsia_input::Key::kRightMeta;
       k = static_cast<fuchsia_input::Key>(static_cast<uint32_t>(k) + 1)) {
    kExpectedKeys.insert(k);
  }
  kExpectedKeys.insert(fuchsia_input::Key::kMute);
  kExpectedKeys.insert(fuchsia_input::Key::kVolumeDown);
  kExpectedKeys.insert(fuchsia_input::Key::kVolumeUp);
  kExpectedKeys.insert(fuchsia_input::Key::kPower);
  EXPECT_TRUE(std::set(descriptor.keyboard().input().keys3().begin(),
                       descriptor.keyboard().input().keys3().end()) == kExpectedKeys);
}

TEST_F(VirtioInputTest, KeyboardTest) {
  async_patterns::TestDispatcherBound<HidKeyboard> hid_keyboard{
      loop_.dispatcher(), std::in_place, std::string("test_product"), std::string("test_serial")};
  std::shared_ptr<ReaderV2EventHandler> event_handler = std::make_shared<ReaderV2EventHandler>(
      [&](fidl::WireEvent<fuchsia_input_report::InputReportsReaderV2::OnInputReports>* event) {
        const fidl::VectorView<fuchsia_input_report::wire::InputReport>& reports = event->reports;

        ASSERT_EQ(reports.size(), 1u);
        const fuchsia_input_report::wire::InputReport& report = reports[0];

        ASSERT_TRUE(report.has_event_time());
        ASSERT_TRUE(report.has_keyboard());
        const fuchsia_input_report::wire::KeyboardInputReport& keyboard_report = report.keyboard();

        ASSERT_TRUE(keyboard_report.has_pressed_keys3());
        ASSERT_EQ(keyboard_report.pressed_keys3().size(), 4u);
        EXPECT_EQ(keyboard_report.pressed_keys3()[0], fuchsia_input::wire::Key::kLeftShift);
        EXPECT_EQ(keyboard_report.pressed_keys3()[1], fuchsia_input::wire::Key::kA);
        EXPECT_EQ(keyboard_report.pressed_keys3()[2], fuchsia_input::wire::Key::kRightAlt);
        EXPECT_EQ(keyboard_report.pressed_keys3()[3], fuchsia_input::wire::Key::kDown);

        input_report_loop_.Quit();
      });
  fidl::WireClient<fuchsia_input_report::InputReportsReaderV2> reader =
      GetReader(hid_keyboard, event_handler);

  // Send the Virtio keys.
  virtio_input_event_t event = {};
  event.type = VIRTIO_INPUT_EV_KEY;
  event.value = VIRTIO_INPUT_EV_KEY_PRESSED;
  event.code = 42;  // LEFTSHIFT.
  hid_keyboard.SyncCall([&](HidDeviceBase* device) { device->ReceiveEvent(&event); });

  event.code = 30;  // KEY_A
  hid_keyboard.SyncCall([&](HidDeviceBase* device) { device->ReceiveEvent(&event); });

  event.code = 100;  // KEY_RIGHTALT
  hid_keyboard.SyncCall([&](HidDeviceBase* device) { device->ReceiveEvent(&event); });

  event.code = 108;  // KEY_DOWN
  hid_keyboard.SyncCall([&](HidDeviceBase* device) { device->ReceiveEvent(&event); });

  hid_keyboard.SyncCall(&HidDeviceBase::SendReportToAllReaders);
  EXPECT_EQ(input_report_loop_.Run(), ZX_ERR_CANCELED);
}

}  // namespace virtio
