// Copyright 2022 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.fido.report/cpp/wire.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/sys/cpp/component_context.h>
#include <zircon/errors.h>

#include <src/devices/testing/mock-ddk/mock-device.h>
#include <zxtest/zxtest.h>

#include "ctaphid.h"
#include "fidl/fuchsia.fido.report/cpp/markers.h"

namespace ctaphid {
/// Exact report descriptor for a Yubico 5 series security key (note the 0xF1DO near the start).
#define SKEY_DESC_LEN 34
const uint8_t skey_desc[SKEY_DESC_LEN] = {
    0x06, 0xd0, 0xf1,  // Usage Page ( FIDO_USAGE_PAGE )
    0x09, 0x01,        // Usage ( FIDO_USAGE_CTAPHID )
    0xA1, 0x01,        // Collection ( Application )
    0x09, 0x20,        //     HID_Usage ( FIDO_USAGE_DATA_IN )
    0x15, 0x00,        //     Usage Minimum ( 0x00 )
    0x26, 0xff,        //     Usage Maximum ( 0xff )
    0x00, 0x75, 0x08,  //     HID_ReportSize ( 8 ),
    0x95, 0x40,        //     HID_ReportCount ( HID_INPUT_REPORT_BYTES )
    0x81, 0x02,        //     HID_Input ( HID_Data | HID_Absolute | HID_Variable ),
    0x09, 0x21,        //     HID_Usage ( FIDO_USAGE_DATA_OUT ),
    0x15, 0x00,        //     Usage Minimum ( 0x00 )
    0x26, 0xff,        //     Usage Maximum ( 0xff )
    0x00, 0x75, 0x08,  //     HID_ReportSize ( 8 ),
    0x95, 0x40,        //     HID_ReportCount ( HID_INPUT_REPORT_BYTES )
    0x91, 0x02,        //     HID_Output ( HID_Data | HID_Absolute | HID_Variable ),
    0xc0,              // End Collection
};

class FakeCtapHidDevice : public ddk::HidDeviceProtocol<FakeCtapHidDevice> {
 public:
  FakeCtapHidDevice() : proto_({&hid_device_protocol_ops_, this}) {}

  zx_status_t HidDeviceRegisterListener(const hid_report_listener_protocol_t* listener) {
    listener_ = *listener;
    return ZX_OK;
  }

  void HidDeviceUnregisterListener() { listener_.reset(); }

  zx_status_t HidDeviceGetDescriptor(uint8_t* out_descriptor_list, size_t descriptor_count,
                                     size_t* out_descriptor_actual) {
    if (descriptor_count < report_desc_.size()) {
      return ZX_ERR_BUFFER_TOO_SMALL;
    }
    memcpy(out_descriptor_list, report_desc_.data(), report_desc_.size());
    *out_descriptor_actual = report_desc_.size();
    return ZX_OK;
  }

  zx_status_t HidDeviceGetReport(hid_report_type_t rpt_type, uint8_t rpt_id,
                                 uint8_t* out_report_list, size_t report_count,
                                 size_t* out_report_actual) {
    // If the client is Getting a report with a specific ID, check that it matches
    // our saved report.
    if ((rpt_id != 0) && (report_.size() > 0)) {
      if (rpt_id != report_[0]) {
        return ZX_ERR_WRONG_TYPE;
      }
    }

    if (report_count < report_.size()) {
      return ZX_ERR_BUFFER_TOO_SMALL;
    }
    memcpy(out_report_list, report_.data(), report_.size());
    *out_report_actual = report_.size();

    return ZX_OK;
  }

  void HidDeviceGetHidDeviceInfo(hid_device_info_t* out_info) {
    out_info->vendor_id = 0xabc;
    out_info->product_id = 123;
    out_info->version = 5;
  }

  zx_status_t HidDeviceSetReport(hid_report_type_t rpt_type, uint8_t rpt_id,
                                 const uint8_t* report_list, size_t report_count) {
    report_ = std::vector<uint8_t>(report_list, report_list + report_count);
    n_set_reports_received++;
    return ZX_OK;
  }

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

  void SendReport(const std::vector<uint8_t>& report, zx_time_t timestamp = ZX_TIME_INFINITE) {
    if (timestamp == ZX_TIME_INFINITE) {
      timestamp = zx_clock_get_monotonic();
    }
    if (listener_.has_value()) {
      listener_->ops->receive_report(listener_->ctx, report.data(), report.size(), timestamp);
    }
  }

  void reset_set_reports_counter() { n_set_reports_received = 0; }
  void reset_packets_received_counter() { n_packets_received = 0; }

  std::optional<hid_report_listener_protocol_t> listener_;
  hid_device_protocol_t proto_;
  std::vector<uint8_t> report_desc_;

  std::vector<uint8_t> report_;
  uint32_t n_set_reports_received = 0;
  uint32_t n_packets_received = 0;
};

class CtapHidDevTest : public zxtest::Test {
 public:
  CtapHidDevTest()
      : loop_(&kAsyncLoopConfigNeverAttachToThread), mock_parent_(MockDevice::FakeRootParent()) {}
  void SetUp() override {
    hid_client_ = ddk::HidDeviceProtocolClient(&fake_hid_device_.proto_);
    ctap_driver_device_ = new CtapHidDriver(mock_parent_.get(), hid_client_);
    // Each test is responsible for calling |ctap_driver_device_->Bind()|.
  }

 protected:
  static constexpr size_t kFidlReportBufferSize = 8192;

  void SetupSyncClient() {
    ASSERT_OK(loop_.StartThread("test-loop-thread"));
    auto endpoints = fidl::Endpoints<fuchsia_fido_report::SecurityKeyDevice>::Create();
    binding_ =
        fidl::BindServer(loop_.dispatcher(), std::move(endpoints.server), ctap_driver_device_);
    sync_client_.Bind(std::move(endpoints.client));
  }

  void SetupAsyncClient() {
    auto endpoints = fidl::CreateEndpoints<fuchsia_fido_report::SecurityKeyDevice>();
    async_client_.Bind(std::move(endpoints->client), loop_.dispatcher());
    fidl::BindServer(loop_.dispatcher(), std::move(endpoints->server), ctap_driver_device_);
  }

  fuchsia_fido_report::wire::Message BuildRequest(fidl::Arena<kFidlReportBufferSize>& allocator,
                                                  uint32_t channel,
                                                  fuchsia_fido_report::CtapHidCommand command,
                                                  std::vector<uint8_t>& data) {
    auto fidl_skey_request_builder_ = fuchsia_fido_report::wire::Message::Builder(allocator);
    fidl_skey_request_builder_.channel_id(channel);
    fidl_skey_request_builder_.command_id(command);
    fidl_skey_request_builder_.data(fidl::VectorView<uint8_t>::FromExternal(data));
    fidl_skey_request_builder_.payload_len(static_cast<uint16_t>(data.size()));
    auto result = fidl_skey_request_builder_.Build();
    return result;
  }

  async::Loop loop_;

  std::shared_ptr<MockDevice> mock_parent_;
  FakeCtapHidDevice fake_hid_device_;
  ddk::HidDeviceProtocolClient hid_client_;
  CtapHidDriver* ctap_driver_device_;

  std::optional<fidl::ServerBindingRef<fuchsia_fido_report::SecurityKeyDevice>> binding_;
  fidl::WireSyncClient<fuchsia_fido_report::SecurityKeyDevice> sync_client_;
  fidl::WireClient<fuchsia_fido_report::SecurityKeyDevice> async_client_;
};

TEST_F(CtapHidDevTest, HidLifetimeTest) {
  std::vector<uint8_t> desc(skey_desc, skey_desc + sizeof(skey_desc));
  fake_hid_device_.SetReportDesc(desc);

  ASSERT_OK(ctap_driver_device_->Bind());
  ASSERT_TRUE(fake_hid_device_.listener_);

  // make sure the child device is there
  ASSERT_EQ(mock_parent_->child_count(), 1);
  auto* child = mock_parent_->GetLatestChild();

  child->ReleaseOp();

  // Make sure that the CtapHidDriver class has unregistered from the HID device.
  ASSERT_FALSE(fake_hid_device_.listener_);
}

TEST_F(CtapHidDevTest, SendMessageWithEmptyPayloadTest) {
  std::vector<uint8_t> desc(skey_desc, skey_desc + SKEY_DESC_LEN);
  fake_hid_device_.SetReportDesc(desc);
  ASSERT_OK(ctap_driver_device_->Bind());

  SetupSyncClient();

  fidl::Arena<kFidlReportBufferSize> allocator;
  std::vector<uint8_t> data_vec{};
  auto message_request =
      BuildRequest(allocator, 0xFFFFFFFF, fuchsia_fido_report::CtapHidCommand::kInit, data_vec);

  // Send the Command.
  fidl::WireResult<fuchsia_fido_report::SecurityKeyDevice::SendMessage> result =
      sync_client_->SendMessage(message_request);
  loop_.RunUntilIdle();

  ASSERT_EQ(result.status(), ZX_OK);
  // Check the hid driver received the correct number of packets.
  ASSERT_EQ(fake_hid_device_.n_set_reports_received, 1);
}

TEST_F(CtapHidDevTest, SendMessageSinglePacketTest) {
  std::vector<uint8_t> desc(skey_desc, skey_desc + SKEY_DESC_LEN);
  fake_hid_device_.SetReportDesc(desc);
  ASSERT_OK(ctap_driver_device_->Bind());

  SetupSyncClient();

  fidl::Arena<kFidlReportBufferSize> allocator;
  std::vector<uint8_t> data_vec{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
  auto message_request =
      BuildRequest(allocator, 0xFFFFFFFF, fuchsia_fido_report::CtapHidCommand::kInit, data_vec);

  // Send the Command.
  fidl::WireResult<fuchsia_fido_report::SecurityKeyDevice::SendMessage> result =
      sync_client_->SendMessage(message_request);
  loop_.RunUntilIdle();

  ASSERT_EQ(result.status(), ZX_OK);
  // Check the hid driver received the correct number of packets.
  ASSERT_EQ(fake_hid_device_.n_set_reports_received, 1);
}

TEST_F(CtapHidDevTest, SendMessageMultiPacketTest) {
  std::vector<uint8_t> desc(skey_desc, skey_desc + SKEY_DESC_LEN);
  fake_hid_device_.SetReportDesc(desc);
  ASSERT_OK(ctap_driver_device_->Bind());

  SetupSyncClient();

  fidl::Arena<kFidlReportBufferSize> allocator;
  std::vector<uint8_t> data_vec(1024, 1);
  auto message_request =
      BuildRequest(allocator, 0xFFFFFFFF, fuchsia_fido_report::CtapHidCommand::kInit, data_vec);

  // Send the Command.
  fidl::WireResult<fuchsia_fido_report::SecurityKeyDevice::SendMessage> result =
      sync_client_->SendMessage(message_request);
  loop_.RunUntilIdle();

  ASSERT_EQ(result.status(), ZX_OK);
  // The Driver should have split this command into multiple packets.
  // The number of packets used to send this message should be:
  // ciel((data_size - (ouput_packet_size-7)) / (output_packet_size - 5)) + 1
  // In this case, the output_packet_size is 64 and the data_size is 1024.
  ASSERT_EQ(fake_hid_device_.n_set_reports_received, 18);
}

TEST_F(CtapHidDevTest, SendMessageChannelAlreadyPendingTest) {
  std::vector<uint8_t> desc(skey_desc, skey_desc + SKEY_DESC_LEN);
  fake_hid_device_.SetReportDesc(desc);
  ASSERT_OK(ctap_driver_device_->Bind());

  SetupSyncClient();

  uint32_t test_channel = 0x01020304;

  // Send a Command on test_channel.
  {
    fidl::Arena<kFidlReportBufferSize> allocator;
    std::vector<uint8_t> data_vec{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
    auto message_request =
        BuildRequest(allocator, test_channel, fuchsia_fido_report::CtapHidCommand::kInit, data_vec);

    // Send the Command.
    fidl::WireResult<fuchsia_fido_report::SecurityKeyDevice::SendMessage> result =
        sync_client_->SendMessage(message_request);
    loop_.RunUntilIdle();

    ASSERT_EQ(result.status(), ZX_OK);
  }

  // Send another Command on the same channel. This should fail since we are pending on a response
  // from the key for the original request.
  {
    fidl::Arena<kFidlReportBufferSize> allocator;
    std::vector<uint8_t> data_vec{0xde, 0xad, 0xbe, 0xef};
    auto message_request =
        BuildRequest(allocator, test_channel, fuchsia_fido_report::CtapHidCommand::kMsg, data_vec);

    // Send the Command.
    fidl::WireResult<fuchsia_fido_report::SecurityKeyDevice::SendMessage> result =
        sync_client_->SendMessage(message_request);
    loop_.RunUntilIdle();

    ASSERT_TRUE(result->is_error());
    ASSERT_EQ(result->error_value(), ZX_ERR_UNAVAILABLE);
  }

  // Have the key reply to the first command.
  {
    std::vector<uint8_t> packet{
        // channel id
        static_cast<uint8_t>((test_channel >> 24) & 0xff),
        static_cast<uint8_t>((test_channel >> 16) & 0xff),
        static_cast<uint8_t>((test_channel >> 8) & 0xff), static_cast<uint8_t>(test_channel & 0xff),
        // command id with init packet bit set
        static_cast<uint8_t>(fuchsia_fido_report::CtapHidCommand::kInit) | (1u << 7),
        // payload len
        0x00, 0x01,
        // payload
        0x0f};
    fake_hid_device_.SendReport(packet);
    loop_.RunUntilIdle();
  }

  // Send another Command on the same channel again. This should still fail since we still need to
  // get the response from the original request.
  {
    fidl::Arena<kFidlReportBufferSize> allocator;
    std::vector<uint8_t> data_vec{0xde, 0xad, 0xbe, 0xef};
    auto message_request =
        BuildRequest(allocator, test_channel, fuchsia_fido_report::CtapHidCommand::kMsg, data_vec);

    // Send the Command.
    fidl::WireResult<fuchsia_fido_report::SecurityKeyDevice::SendMessage> result =
        sync_client_->SendMessage(message_request);
    loop_.RunUntilIdle();

    ASSERT_TRUE(result->is_error());
    ASSERT_EQ(result->error_value(), ZX_ERR_UNAVAILABLE);
  }

  // Get the response to the original command.
  {
    fidl::WireResult<fuchsia_fido_report::SecurityKeyDevice::GetMessage> result =
        sync_client_->GetMessage(test_channel);
    loop_.RunUntilIdle();
  }

  // Retry sending another Command on the same channel. This should now succeed since the first
  // transaction has completed.
  {
    fidl::Arena<kFidlReportBufferSize> allocator;
    std::vector<uint8_t> data_vec{0xde, 0xad, 0xbe, 0xef};
    auto message_request =
        BuildRequest(allocator, test_channel, fuchsia_fido_report::CtapHidCommand::kMsg, data_vec);

    // Send the Command.
    fidl::WireResult<fuchsia_fido_report::SecurityKeyDevice::SendMessage> result =
        sync_client_->SendMessage(message_request);
    loop_.RunUntilIdle();

    ASSERT_FALSE(result->is_error());
    ;
  }
}

TEST_F(CtapHidDevTest, SendMessageDeviceBusyTest) {
  std::vector<uint8_t> desc(skey_desc, skey_desc + SKEY_DESC_LEN);
  fake_hid_device_.SetReportDesc(desc);
  ASSERT_OK(ctap_driver_device_->Bind());

  SetupSyncClient();

  uint32_t test_channel = 0x01020304;
  uint8_t test_payload_byte = 0x0f;
  uint32_t other_test_channel = 0x09080706;

  // Send a Command on test_channel.
  {
    fidl::Arena<kFidlReportBufferSize> allocator;
    std::vector<uint8_t> data_vec{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
    auto message_request =
        BuildRequest(allocator, test_channel, fuchsia_fido_report::CtapHidCommand::kMsg, data_vec);

    // Send the Command.
    fidl::WireResult<fuchsia_fido_report::SecurityKeyDevice::SendMessage> result =
        sync_client_->SendMessage(message_request);
    loop_.RunUntilIdle();

    ASSERT_EQ(result.status(), ZX_OK);
  }

  // Send another Command on a different channel.
  // This should fail as we're still waiting for a response on the first request.
  {
    fidl::Arena<kFidlReportBufferSize> allocator;
    std::vector<uint8_t> data_vec{0x01};
    auto message_request = BuildRequest(allocator, other_test_channel,
                                        fuchsia_fido_report::CtapHidCommand::kMsg, data_vec);

    // Send the Command.
    fidl::WireResult<fuchsia_fido_report::SecurityKeyDevice::SendMessage> result =
        sync_client_->SendMessage(message_request);
    loop_.RunUntilIdle();

    ASSERT_TRUE(result->is_error());
    ASSERT_EQ(result->error_value(), ZX_ERR_UNAVAILABLE);
  }

  // Have the key reply to the first command.
  {
    std::vector<uint8_t> packet{
        // channel id
        static_cast<uint8_t>((test_channel >> 24) & 0xff),
        static_cast<uint8_t>((test_channel >> 16) & 0xff),
        static_cast<uint8_t>((test_channel >> 8) & 0xff), static_cast<uint8_t>(test_channel & 0xff),
        // command id with init packet bit set
        static_cast<uint8_t>(fuchsia_fido_report::CtapHidCommand::kInit) | (1u << 7),
        // payload len
        0x00, 0x01,
        // payload
        test_payload_byte};
    fake_hid_device_.SendReport(packet);
    loop_.RunUntilIdle();
  }

  // Try again to send another Command on a different channel.
  // This should still fail as the first request's response still needs to be retrieved.
  {
    fidl::Arena<kFidlReportBufferSize> allocator;
    std::vector<uint8_t> data_vec{0x01};
    auto message_request = BuildRequest(allocator, other_test_channel,
                                        fuchsia_fido_report::CtapHidCommand::kMsg, data_vec);

    // Send the Command.
    fidl::WireResult<fuchsia_fido_report::SecurityKeyDevice::SendMessage> result =
        sync_client_->SendMessage(message_request);
    loop_.RunUntilIdle();

    ASSERT_TRUE(result->is_error());
    ASSERT_EQ(result->error_value(), ZX_ERR_UNAVAILABLE);
  }

  // Get the response to the first command, on test_channel.
  {
    fidl::WireResult<fuchsia_fido_report::SecurityKeyDevice::GetMessage> result =
        sync_client_->GetMessage(test_channel);
    loop_.RunUntilIdle();
  }

  // Finally try to send another Command on a different channel.
  // This should now succeed as the first transaction is complete.
  {
    fidl::Arena<kFidlReportBufferSize> allocator;
    std::vector<uint8_t> data_vec{0x01};
    auto message_request = BuildRequest(allocator, other_test_channel,
                                        fuchsia_fido_report::CtapHidCommand::kMsg, data_vec);

    // Send the Command.
    fidl::WireResult<fuchsia_fido_report::SecurityKeyDevice::SendMessage> result =
        sync_client_->SendMessage(message_request);
    loop_.RunUntilIdle();

    ASSERT_FALSE(result->is_error());
    ASSERT_OK(result);
  }
}

TEST_F(CtapHidDevTest, ReceiveSinglePacketMessageTest) {
  std::vector<uint8_t> desc(skey_desc, skey_desc + SKEY_DESC_LEN);
  fake_hid_device_.SetReportDesc(desc);
  ASSERT_OK(ctap_driver_device_->Bind());

  SetupSyncClient();

  uint32_t test_channel = 0x01020304;
  auto test_command = fuchsia_fido_report::CtapHidCommand::kInit;
  std::vector<uint8_t> test_payload{0xde, 0xad, 0xbe, 0xef};

  // Send a SendMessage so we are able to call GetMessage.
  {
    fidl::Arena<kFidlReportBufferSize> allocator;
    std::vector<uint8_t> data_vec{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
    auto message_request = BuildRequest(allocator, test_channel, test_command, data_vec);

    // Send the Command.
    fidl::WireResult<fuchsia_fido_report::SecurityKeyDevice::SendMessage> result =
        sync_client_->SendMessage(message_request);
    loop_.RunUntilIdle();
  }

  // Send a packet from the key.
  {
    std::vector<uint8_t> packet{// channel id
                                static_cast<uint8_t>((test_channel >> 24) & 0xff),
                                static_cast<uint8_t>((test_channel >> 16) & 0xff),
                                static_cast<uint8_t>((test_channel >> 8) & 0xff),
                                static_cast<uint8_t>(test_channel & 0xff),
                                // command id with init packet bit set
                                static_cast<uint8_t>(fidl::ToUnderlying(test_command) | (1u << 7)),
                                // payload len
                                0x00, 0x04,
                                // payload
                                0xde, 0xad, 0xbe, 0xef};
    fake_hid_device_.SendReport(packet);
    loop_.RunUntilIdle();
  }

  // Get and check the Message formed from the packet.
  {
    fidl::WireResult<fuchsia_fido_report::SecurityKeyDevice::GetMessage> result =
        sync_client_->GetMessage(test_channel);
    loop_.RunUntilIdle();

    ASSERT_EQ(result.status(), ZX_OK);
    ASSERT_TRUE(result->value()->has_channel_id());
    ASSERT_EQ(result->value()->channel_id(), test_channel);
    ASSERT_EQ(result->value()->command_id(), test_command);
    ASSERT_EQ(result->value()->payload_len(), test_payload.size());
    for (size_t i = 0; i < test_payload.size(); i++) {
      ASSERT_EQ(result->value()->data().at(i), test_payload.at(i));
    }
  }
}

TEST_F(CtapHidDevTest, ReceiveMultiplePacketMessageTest) {
  std::vector<uint8_t> desc(skey_desc, skey_desc + SKEY_DESC_LEN);
  fake_hid_device_.SetReportDesc(desc);
  ASSERT_OK(ctap_driver_device_->Bind());

  SetupSyncClient();

  uint32_t test_channel = 0x01020304;
  auto test_command = fuchsia_fido_report::CtapHidCommand::kInit;

  uint8_t init_payload_len = 64 - 7;
  uint8_t cont_payload1_len = 64 - 5;
  uint8_t cont_payload2_len = 32;
  std::vector<uint8_t> test_init_payload(init_payload_len, 0x0a);
  std::vector<uint8_t> test_cont_payload1(cont_payload1_len, 0x0b);
  std::vector<uint8_t> test_cont_payload2(cont_payload2_len, 0x0c);

  auto total_payload(test_init_payload);
  total_payload.insert(total_payload.end(), test_cont_payload1.begin(), test_cont_payload1.end());
  total_payload.insert(total_payload.end(), test_cont_payload2.begin(), test_cont_payload2.end());
  uint16_t total_payload_len = static_cast<uint16_t>(total_payload.size());

  // Send a SendMessage so we are able to call GetMessage.
  {
    fidl::Arena<kFidlReportBufferSize> allocator;
    std::vector<uint8_t> data_vec{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
    auto message_request = BuildRequest(allocator, test_channel, test_command, data_vec);

    // Send the Command.
    fidl::WireResult<fuchsia_fido_report::SecurityKeyDevice::SendMessage> result =
        sync_client_->SendMessage(message_request);
    loop_.RunUntilIdle();
  }

  // Send the packets from the key.
  {
    // Init Payload
    std::vector<uint8_t> init_packet{
        // channel id
        static_cast<uint8_t>((test_channel >> 24) & 0xff),
        static_cast<uint8_t>((test_channel >> 16) & 0xff),
        static_cast<uint8_t>((test_channel >> 8) & 0xff), static_cast<uint8_t>(test_channel & 0xff),
        // command id with init packet bit set
        static_cast<uint8_t>(fidl::ToUnderlying(test_command) | (1u << 7)),
        // payload len
        static_cast<uint8_t>((total_payload_len >> 8) & 0xff),
        static_cast<uint8_t>(total_payload_len & 0xff)};
    init_packet.insert(init_packet.end(), test_init_payload.begin(), test_init_payload.end());
    fake_hid_device_.SendReport(init_packet);
    loop_.RunUntilIdle();
    // Cont Payload 1
    std::vector<uint8_t> cont_packet1{// channel id
                                      static_cast<uint8_t>((test_channel >> 24) & 0xff),
                                      static_cast<uint8_t>((test_channel >> 16) & 0xff),
                                      static_cast<uint8_t>((test_channel >> 8) & 0xff),
                                      static_cast<uint8_t>(test_channel & 0xff),
                                      // packet sequence number
                                      0x00};
    cont_packet1.insert(cont_packet1.end(), test_cont_payload1.begin(), test_cont_payload1.end());
    fake_hid_device_.SendReport(cont_packet1);
    loop_.RunUntilIdle();
    // Cont Payload 2
    std::vector<uint8_t> cont_packet2{// channel id
                                      static_cast<uint8_t>((test_channel >> 24) & 0xff),
                                      static_cast<uint8_t>((test_channel >> 16) & 0xff),
                                      static_cast<uint8_t>((test_channel >> 8) & 0xff),
                                      static_cast<uint8_t>(test_channel & 0xff),
                                      // packet sequence number
                                      0x01};
    cont_packet2.insert(cont_packet2.end(), test_cont_payload2.begin(), test_cont_payload2.end());
    fake_hid_device_.SendReport(cont_packet2);
    loop_.RunUntilIdle();
  }

  // Get and check the Message formed from the packet.
  {
    fidl::WireResult<fuchsia_fido_report::SecurityKeyDevice::GetMessage> result =
        sync_client_->GetMessage(test_channel);
    loop_.RunUntilIdle();

    ASSERT_EQ(result.status(), ZX_OK);
    ASSERT_EQ(result->value()->channel_id(), test_channel);
    ASSERT_EQ(result->value()->command_id(), test_command);
    for (size_t i = 0; i < total_payload.size(); i++) {
      ASSERT_EQ(result->value()->data().at(i), total_payload.at(i));
    }
  }
}

TEST_F(CtapHidDevTest, ReceivePacketMissingInitTest) {
  std::vector<uint8_t> desc(skey_desc, skey_desc + SKEY_DESC_LEN);
  fake_hid_device_.SetReportDesc(desc);
  ASSERT_OK(ctap_driver_device_->Bind());

  SetupSyncClient();

  uint32_t test_channel = 0x01020304;
  auto test_command = fuchsia_fido_report::CtapHidCommand::kInit;
  std::vector<uint8_t> test_payload{0xde, 0xad, 0xbe, 0xef};

  // Send a SendMessage so we are able to call GetMessage.
  {
    fidl::Arena<kFidlReportBufferSize> allocator;
    std::vector<uint8_t> data_vec{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
    auto message_request = BuildRequest(allocator, test_channel, test_command, data_vec);

    // Send the Command.
    fidl::WireResult<fuchsia_fido_report::SecurityKeyDevice::SendMessage> result =
        sync_client_->SendMessage(message_request);
    loop_.RunUntilIdle();
  }

  // Send a packet from the key.
  {
    std::vector<uint8_t> packet{// channel id
                                static_cast<uint8_t>((test_channel >> 24) & 0xff),
                                static_cast<uint8_t>((test_channel >> 16) & 0xff),
                                static_cast<uint8_t>((test_channel >> 8) & 0xff),
                                static_cast<uint8_t>(test_channel & 0xff),
                                // packet sequence number
                                0x00,
                                // payload
                                0xde, 0xad, 0xbe, 0xef};
    fake_hid_device_.SendReport(packet);
    loop_.RunUntilIdle();
  }

  // Check the response was set to an incorrect packet sequence error.
  {
    fidl::WireResult<fuchsia_fido_report::SecurityKeyDevice::GetMessage> result =
        sync_client_->GetMessage(test_channel);
    loop_.RunUntilIdle();

    ASSERT_EQ(result.status(), ZX_OK);
    ASSERT_EQ(result->value()->channel_id(), test_channel);
    ASSERT_EQ(result->value()->command_id(), fuchsia_fido_report::CtapHidCommand::kError);
    ASSERT_NE(result->value()->payload_len(), test_payload.size());
    ASSERT_EQ(result->value()->payload_len(), 1);
    ASSERT_NE(result->value()->data().at(0), 0x04);
  }
}

TEST_F(CtapHidDevTest, ReceivePacketMissingContTest) {
  std::vector<uint8_t> desc(skey_desc, skey_desc + SKEY_DESC_LEN);
  fake_hid_device_.SetReportDesc(desc);
  ASSERT_OK(ctap_driver_device_->Bind());

  SetupSyncClient();

  uint32_t test_channel = 0x01020304;
  auto test_command = fuchsia_fido_report::CtapHidCommand::kInit;

  uint8_t init_payload_len = 64 - 7;
  uint8_t cont_payload_len = 32;
  uint8_t total_payload_len = init_payload_len + cont_payload_len + (64 - 5);
  std::vector<uint8_t> test_init_payload(init_payload_len, 0x0a);
  std::vector<uint8_t> test_cont_payload(cont_payload_len, 0x0b);

  // Send a SendMessage so we are able to call GetMessage.
  {
    fidl::Arena<kFidlReportBufferSize> allocator;
    std::vector<uint8_t> data_vec{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
    auto message_request = BuildRequest(allocator, test_channel, test_command, data_vec);

    // Send the Command.
    fidl::WireResult<fuchsia_fido_report::SecurityKeyDevice::SendMessage> result =
        sync_client_->SendMessage(message_request);
    loop_.RunUntilIdle();
  }

  // Send an init packet from the key.
  {
    // Init Payload
    std::vector<uint8_t> init_packet{
        // channel id
        static_cast<uint8_t>((test_channel >> 24) & 0xff),
        static_cast<uint8_t>((test_channel >> 16) & 0xff),
        static_cast<uint8_t>((test_channel >> 8) & 0xff), static_cast<uint8_t>(test_channel & 0xff),
        // command id with init packet bit set
        static_cast<uint8_t>(fidl::ToUnderlying(test_command) | (1u << 7)),
        // payload len
        static_cast<uint8_t>((total_payload_len >> 8) & 0xff),
        static_cast<uint8_t>(total_payload_len & 0xff)};
    init_packet.insert(init_packet.end(), test_init_payload.begin(), test_init_payload.end());
    fake_hid_device_.SendReport(init_packet);
    loop_.RunUntilIdle();
  }

  // Send a continuation packet from the key, skipping the first packet.
  {
    std::vector<uint8_t> cont_packet{// channel id
                                     static_cast<uint8_t>((test_channel >> 24) & 0xff),
                                     static_cast<uint8_t>((test_channel >> 16) & 0xff),
                                     static_cast<uint8_t>((test_channel >> 8) & 0xff),
                                     static_cast<uint8_t>(test_channel & 0xff),
                                     // packet sequence number
                                     0x00 + 1};
    cont_packet.insert(cont_packet.end(), test_cont_payload.begin(), test_cont_payload.end());
    fake_hid_device_.SendReport(cont_packet);
    loop_.RunUntilIdle();
  }

  // Check the response was set to an incorrect packet sequence error.
  {
    fidl::WireResult<fuchsia_fido_report::SecurityKeyDevice::GetMessage> result =
        sync_client_->GetMessage(test_channel);
    loop_.RunUntilIdle();

    ASSERT_EQ(result.status(), ZX_OK);
    ASSERT_EQ(result->value()->channel_id(), test_channel);
    ASSERT_EQ(result->value()->command_id(), fuchsia_fido_report::CtapHidCommand::kError);
    ASSERT_EQ(result->value()->payload_len(), 1);
    ASSERT_NE(result->value()->data().at(0), 0x04);
  }
}

TEST_F(CtapHidDevTest, GetMessageChannelTest) {
  std::vector<uint8_t> desc(skey_desc, skey_desc + SKEY_DESC_LEN);
  fake_hid_device_.SetReportDesc(desc);
  ASSERT_OK(ctap_driver_device_->Bind());

  SetupSyncClient();

  uint32_t const test_channel = 0x01020304;
  auto const test_command = fuchsia_fido_report::CtapHidCommand::kMsg;
  uint8_t const test_payload_byte = 0x0f;

  // Send a SendMessage request.
  {
    fidl::Arena<kFidlReportBufferSize> allocator;
    std::vector<uint8_t> data_vec(1024, 1);
    auto message_request = BuildRequest(allocator, test_channel, test_command, data_vec);

    // Send the Command.
    fidl::WireResult<fuchsia_fido_report::SecurityKeyDevice::SendMessage> result =
        sync_client_->SendMessage(message_request);
    loop_.RunUntilIdle();
  }

  // Set up a packet to be sent as a response.
  {
    std::vector<uint8_t> packet{// channel id
                                static_cast<uint8_t>((test_channel >> 24) & 0xff),
                                static_cast<uint8_t>((test_channel >> 16) & 0xff),
                                static_cast<uint8_t>((test_channel >> 8) & 0xff),
                                static_cast<uint8_t>(test_channel & 0xff),
                                // command id with init packet bit set
                                static_cast<uint8_t>(fidl::ToUnderlying(test_command) | (1u << 7)),
                                // payload len
                                0x00, 0x01,
                                // payload
                                test_payload_byte};
    fake_hid_device_.SendReport(packet);
    loop_.RunUntilIdle();
  }

  // Make a Request to get a message with a different channel id.
  {
    fidl::WireResult<fuchsia_fido_report::SecurityKeyDevice::GetMessage> result_1 =
        sync_client_->GetMessage(0xffffffff);
    loop_.RunUntilIdle();

    ASSERT_TRUE(result_1->is_error());
    ASSERT_EQ(result_1->error_value(), ZX_ERR_NOT_FOUND);
  }

  // Make a Request to get a message with the correct channel id.
  {
    fidl::WireResult<fuchsia_fido_report::SecurityKeyDevice::GetMessage> result_2 =
        sync_client_->GetMessage(test_channel);
    loop_.RunUntilIdle();

    ASSERT_FALSE(result_2->is_error());
    ASSERT_TRUE(result_2->value()->has_channel_id());
    ASSERT_TRUE(result_2->value()->has_data());
    ASSERT_EQ(result_2->value()->channel_id(), test_channel);

    ASSERT_EQ(result_2->value()->payload_len(), 1);
    ASSERT_EQ(result_2->value()->data().at(0), test_payload_byte);
  }
}

TEST_F(CtapHidDevTest, GetMessageKeepAliveTest) {
  std::vector<uint8_t> desc(skey_desc, skey_desc + SKEY_DESC_LEN);
  fake_hid_device_.SetReportDesc(desc);
  ASSERT_OK(ctap_driver_device_->Bind());

  SetupSyncClient();

  uint32_t test_channel = 0x01020304;
  auto test_command = fuchsia_fido_report::CtapHidCommand::kInit;
  uint8_t test_payload_byte = 0x0f;

  // Send a command.
  {
    fidl::Arena<kFidlReportBufferSize> allocator;
    std::vector<uint8_t> data_vec{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
    auto message_request = BuildRequest(allocator, test_channel, test_command, data_vec);

    fidl::WireResult<fuchsia_fido_report::SecurityKeyDevice::SendMessage> result =
        sync_client_->SendMessage(message_request);
    loop_.RunUntilIdle();
    ASSERT_EQ(result.status(), ZX_OK);
  }

  // Set up a KEEPALIVE packet to be sent from the device.
  {
    std::vector<uint8_t> packet{
        // channel id
        static_cast<uint8_t>((test_channel >> 24) & 0xff),
        static_cast<uint8_t>((test_channel >> 16) & 0xff),
        static_cast<uint8_t>((test_channel >> 8) & 0xff), static_cast<uint8_t>(test_channel & 0xff),
        // command id with init packet bit set
        static_cast<uint8_t>(fidl::ToUnderlying(fuchsia_fido_report::CtapHidCommand::kKeepalive)) |
            (1u << 7),
        // payload len
        0x00, 0x01,
        // payload
        test_payload_byte};
    fake_hid_device_.SendReport(packet);
    loop_.RunUntilIdle();
  }

  // Make a Request to get a message. This should return the KEEPALIVE message.
  {
    fidl::WireResult<fuchsia_fido_report::SecurityKeyDevice::GetMessage> result =
        sync_client_->GetMessage(test_channel);
    loop_.RunUntilIdle();

    ASSERT_EQ(result.status(), ZX_OK);
    ASSERT_EQ(result->value()->command_id(), fuchsia_fido_report::CtapHidCommand::kKeepalive);
  }

  // Set up the real packet matching the original command to be sent from the device.
  {
    std::vector<uint8_t> packet{// channel id
                                static_cast<uint8_t>((test_channel >> 24) & 0xff),
                                static_cast<uint8_t>((test_channel >> 16) & 0xff),
                                static_cast<uint8_t>((test_channel >> 8) & 0xff),
                                static_cast<uint8_t>(test_channel & 0xff),
                                // command id with init packet bit set
                                static_cast<uint8_t>(fidl::ToUnderlying(test_command) | (1u << 7)),
                                // payload len
                                0x00, 0x01,
                                // payload
                                test_payload_byte};
    fake_hid_device_.SendReport(packet);
    loop_.RunUntilIdle();
  }

  // Make a Request to get a message again. This should return the final message.
  {
    fidl::WireResult<fuchsia_fido_report::SecurityKeyDevice::GetMessage> result =
        sync_client_->GetMessage(test_channel);
    loop_.RunUntilIdle();

    ASSERT_EQ(result.status(), ZX_OK);
    ASSERT_EQ(result->value()->command_id(), test_command);
  }
}

TEST_F(CtapHidDevTest, HangingGetMessageTest) {
  std::vector<uint8_t> desc(skey_desc, skey_desc + SKEY_DESC_LEN);
  fake_hid_device_.SetReportDesc(desc);
  ASSERT_OK(ctap_driver_device_->Bind());

  // Set up an async client to test GetMessage. We'll need to make the fake_hid_device send a packet
  // up to the ctaphid driver after we've sent the GetMessage() request.
  SetupAsyncClient();

  uint32_t test_channel = 0x01020304;
  auto test_command = fuchsia_fido_report::CtapHidCommand::kInit;
  uint8_t test_payload_byte = 0x0f;

  // Send a command.
  {
    fidl::Arena<kFidlReportBufferSize> allocator;
    std::vector<uint8_t> data_vec{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
    auto message_request = BuildRequest(allocator, test_channel, test_command, data_vec);

    async_client_->SendMessage(message_request)
        .ThenExactlyOnce(
            [&](fidl::WireUnownedResult<fuchsia_fido_report::SecurityKeyDevice::SendMessage>&
                    result) {
              ASSERT_OK(result);
              ASSERT_FALSE(result->is_error());
            });
    loop_.RunUntilIdle();
  }

  // Make a Request to get a message. This should hang until a response is sent from the device.
  async_client_->GetMessage(test_channel)
      .ThenExactlyOnce(
          [&](fidl::WireUnownedResult<fuchsia_fido_report::SecurityKeyDevice::GetMessage>& result) {
            ASSERT_OK(result.status());
            ASSERT_FALSE(result->is_error());

            ASSERT_TRUE(result->value()->channel_id());
            ASSERT_EQ(result->value()->channel_id(), test_channel);
            ASSERT_TRUE(fidl::ToUnderlying(result->value()->command_id()));
            ASSERT_EQ(result->value()->command_id(), test_command);
            ASSERT_TRUE(result->value()->payload_len());
            ASSERT_EQ(result->value()->payload_len(), 1);
            ASSERT_TRUE(result->value()->has_data());
            ASSERT_EQ(result->value()->data().at(0), test_payload_byte);

            loop_.Quit();
          });

  // Send a response from the device.
  {
    std::vector<uint8_t> packet{// channel id
                                static_cast<uint8_t>((test_channel >> 24) & 0xff),
                                static_cast<uint8_t>((test_channel >> 16) & 0xff),
                                static_cast<uint8_t>((test_channel >> 8) & 0xff),
                                static_cast<uint8_t>(test_channel & 0xff),
                                // command id with init packet bit set
                                static_cast<uint8_t>(fidl::ToUnderlying(test_command) | (1u << 7)),
                                // payload len
                                0x00, 0x01,
                                // payload
                                test_payload_byte};
    fake_hid_device_.SendReport(packet);
    loop_.RunUntilIdle();
  }
}

}  // namespace ctaphid
