// Copyright 2017 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 "src/connectivity/bluetooth/core/bt-host/transport/command_channel.h"

#include <lib/async/cpp/task.h>
#include <lib/inspect/testing/cpp/inspect.h>

#include <fbl/ref_counted.h>
#include <fbl/ref_ptr.h>

#include "src/connectivity/bluetooth/core/bt-host/common/byte_buffer.h"
#include "src/connectivity/bluetooth/core/bt-host/common/test_helpers.h"
#include "src/connectivity/bluetooth/core/bt-host/hci-spec/protocol.h"
#include "src/connectivity/bluetooth/core/bt-host/testing/controller_test.h"
#include "src/connectivity/bluetooth/core/bt-host/testing/mock_controller.h"
#include "src/connectivity/bluetooth/core/bt-host/transport/control_packets.h"

namespace bt::hci {
namespace {

using namespace inspect::testing;

using bt::LowerBits;
using bt::UpperBits;
using EventCallbackResult = CommandChannel::EventCallbackResult;

using TestingBase = bt::testing::ControllerTest<bt::testing::MockController>;

// A reference counted object used to verify that HCI command completion and
// status callbacks are properly cleaned up after the end of a transaction.
class TestCallbackObject : public fbl::RefCounted<TestCallbackObject> {
 public:
  explicit TestCallbackObject(fit::closure deletion_callback)
      : deletion_cb_(std::move(deletion_callback)) {}

  virtual ~TestCallbackObject() { deletion_cb_(); }

 private:
  fit::closure deletion_cb_;
};

class CommandChannelTest : public TestingBase {
 public:
  CommandChannelTest() = default;
  ~CommandChannelTest() override = default;

  inspect::Inspector inspector_;
};

std::unique_ptr<CommandPacket> MakeReadRemoteSupportedFeatures(uint16_t connection_handle) {
  auto packet = CommandPacket::New(hci_spec::kReadRemoteSupportedFeatures,
                                   sizeof(hci_spec::ReadRemoteSupportedFeaturesCommandParams));
  auto params =
      packet->mutable_view()->mutable_payload<hci_spec::ReadRemoteSupportedFeaturesCommandParams>();
  params->connection_handle = connection_handle;
  return packet;
}

TEST_F(CommandChannelTest, SingleRequestResponse) {
  // Set up expectations:
  // clang-format off
  // HCI_Reset
  StaticByteBuffer req(
      LowerBits(hci_spec::kReset), UpperBits(hci_spec::kReset),  // HCI_Reset opcode
      0x00                                   // parameter_total_size
      );
  // HCI_CommandComplete
 StaticByteBuffer rsp(
      hci_spec::kCommandCompleteEventCode,
      0x04,  // parameter_total_size (4 byte payload)
      0x01,  // num_hci_command_packets (1 can be sent)
      LowerBits(hci_spec::kReset), UpperBits(hci_spec::kReset),  // HCI_Reset opcode
      hci_spec::StatusCode::kHardwareFailure);
  // clang-format on
  EXPECT_CMD_PACKET_OUT(test_device(), req, &rsp);
  StartTestDevice();

  // Send a HCI_Reset command. We attach an instance of TestCallbackObject to the callbacks to
  // verify that it gets cleaned up as expected.
  bool test_obj_deleted = false;
  auto test_obj =
      fbl::MakeRefCounted<TestCallbackObject>([&test_obj_deleted] { test_obj_deleted = true; });

  auto reset = CommandPacket::New(hci_spec::kReset);
  CommandChannel::TransactionId id = cmd_channel()->SendCommand(
      std::move(reset),
      [&id, test_obj](CommandChannel::TransactionId callback_id, const EventPacket& event) {
        EXPECT_EQ(id, callback_id);
        EXPECT_EQ(hci_spec::kCommandCompleteEventCode, event.event_code());
        EXPECT_EQ(4, event.view().header().parameter_total_size);
        EXPECT_EQ(
            1,
            event.view().payload<hci_spec::CommandCompleteEventParams>().num_hci_command_packets);
        EXPECT_EQ(
            hci_spec::kReset,
            le16toh(event.view().payload<hci_spec::CommandCompleteEventParams>().command_opcode));
        EXPECT_EQ(hci_spec::StatusCode::kHardwareFailure,
                  event.return_params<hci_spec::SimpleReturnParams>()->status);
      });

  test_obj = nullptr;
  EXPECT_FALSE(test_obj_deleted);
  RunLoopUntilIdle();

  // Make sure that the I/O thread is no longer holding on to |test_obj|.
  TearDown();

  EXPECT_TRUE(test_obj_deleted);
}

TEST_F(CommandChannelTest, SingleAsynchronousRequest) {
  // Set up expectations:
  // clang-format off
  // HCI_Inquiry (general, unlimited, 1s)
 StaticByteBuffer req(
      LowerBits(hci_spec::kInquiry), UpperBits(hci_spec::kInquiry),  // HCI_Inquiry opcode
      0x05,                                      // parameter_total_size
      0x33, 0x8B, 0x9E,                          // General Inquiry
      0x01,                                      // 1.28s
      0x00                                       // Unlimited responses
      );
  // HCI_CommandStatus
  auto rsp0 = StaticByteBuffer(
       hci_spec::kCommandStatusEventCode,
      0x04,  // parameter_total_size (4 byte payload)
      hci_spec::StatusCode::kSuccess, 0x01, // status, num_hci_command_packets (1 can be sent)
      LowerBits(hci_spec::kInquiry), UpperBits(hci_spec::kInquiry)  // HCI_Inquiry opcode
      );
  // HCI_InquiryComplete
  auto rsp1 = StaticByteBuffer(
      hci_spec::kInquiryCompleteEventCode,
      0x01,  // parameter_total_size (1 byte payload)
      hci_spec::StatusCode::kSuccess);
  // clang-format on
  EXPECT_CMD_PACKET_OUT(test_device(), req, &rsp0, &rsp1);
  StartTestDevice();

  // Send HCI_Inquiry
  CommandChannel::TransactionId id;
  int cb_count = 0;
  auto cb = [&cb_count, &id](CommandChannel::TransactionId callback_id, const EventPacket& event) {
    cb_count++;
    EXPECT_EQ(callback_id, id);
    if (cb_count == 1) {
      ASSERT_EQ(hci_spec::kCommandStatusEventCode, event.event_code());
      const auto params = event.params<hci_spec::CommandStatusEventParams>();
      EXPECT_EQ(hci_spec::StatusCode::kSuccess, params.status);
      EXPECT_EQ(hci_spec::kInquiry, params.command_opcode);
    } else {
      EXPECT_EQ(hci_spec::kInquiryCompleteEventCode, event.event_code());
      EXPECT_EQ(fitx::ok(), event.ToResult());
    }
  };

  constexpr size_t kPayloadSize = sizeof(hci_spec::InquiryCommandParams);
  auto packet = CommandPacket::New(hci_spec::kInquiry, kPayloadSize);
  auto params = packet->mutable_payload<hci_spec::InquiryCommandParams>();
  params->lap = hci_spec::kGIAC;
  params->inquiry_length = 1;
  params->num_responses = 0;
  id = cmd_channel()->SendCommand(std::move(packet), cb, hci_spec::kInquiryCompleteEventCode);
  RunLoopUntilIdle();
  EXPECT_EQ(2, cb_count);
}

TEST_F(CommandChannelTest, SingleRequestWithStatusResponse) {
  // Set up expectations
  // clang-format off
  // HCI_Reset for the sake of testing
  auto req = StaticByteBuffer(
      LowerBits(hci_spec::kReset), UpperBits(hci_spec::kReset),  // HCI_Reset opcode
      0x00                                   // parameter_total_size
      );
  // HCI_CommandStatus
  auto rsp = StaticByteBuffer(
       hci_spec::kCommandStatusEventCode,
      0x04,  // parameter_total_size (4 byte payload)
      hci_spec::StatusCode::kSuccess, 0x01, // status, num_hci_command_packets (1 can be sent)
      LowerBits(hci_spec::kReset), UpperBits(hci_spec::kReset)  // HCI_Reset opcode
      );
  // clang-format on
  EXPECT_CMD_PACKET_OUT(test_device(), req, &rsp);
  StartTestDevice();

  // Send HCI_Reset
  CommandChannel::TransactionId id;
  auto complete_cb = [&id](CommandChannel::TransactionId callback_id, const EventPacket& event) {
    EXPECT_EQ(callback_id, id);
    EXPECT_EQ(hci_spec::kCommandStatusEventCode, event.event_code());
    EXPECT_EQ(hci_spec::StatusCode::kSuccess,
              event.params<hci_spec::CommandStatusEventParams>().status);
    EXPECT_EQ(1,
              event.view().payload<hci_spec::CommandStatusEventParams>().num_hci_command_packets);
    EXPECT_EQ(hci_spec::kReset,
              le16toh(event.params<hci_spec::CommandStatusEventParams>().command_opcode));
  };

  auto reset = CommandPacket::New(hci_spec::kReset);
  id = cmd_channel()->SendCommand(std::move(reset), complete_cb, hci_spec::kCommandStatusEventCode);
  RunLoopUntilIdle();
}

// Tests:
//  - Only one HCI command sent until a status is received.
//  - Receiving a status update with a new number of packets available works.
TEST_F(CommandChannelTest, OneSentUntilStatus) {
  // Set up expectations
  // clang-format off
  // HCI_Reset for the sake of testing
  auto req1 = StaticByteBuffer(
      LowerBits(hci_spec::kReset), UpperBits(hci_spec::kReset),  // HCI_Reset opcode
      0x00                                   // parameter_total_size
      );
  auto rsp1 = StaticByteBuffer(
      hci_spec::kCommandCompleteEventCode,
      0x03,  // parameter_total_size (4 byte payload)
      0x00,  // num_hci_command_packets (None can be sent)
      LowerBits(hci_spec::kReset), UpperBits(hci_spec::kReset)  // HCI_Reset opcode
      );
  auto req2 = StaticByteBuffer(
      LowerBits(hci_spec::kInquiryCancel), UpperBits(hci_spec::kInquiryCancel),  // HCI_InquiryCancel opcode
      0x00                                   // parameter_total_size
      );
  auto rsp2 = StaticByteBuffer(
      hci_spec::kCommandCompleteEventCode,
      0x03,  // parameter_total_size (4 byte payload)
      0x01,  // num_hci_command_packets (1 can be sent)
      LowerBits(hci_spec::kInquiryCancel), UpperBits(hci_spec::kInquiryCancel)  // HCI_InquiryCancel opcode
      );
  auto rsp_commandsavail = StaticByteBuffer(
       hci_spec::kCommandStatusEventCode,
      0x04,  // parameter_total_size (3 byte payload)
      hci_spec::StatusCode::kSuccess, 0x01, // status, num_hci_command_packets (1 can be sent)
      0x00, 0x00 // No associated opcode.
      );
  // clang-format on
  EXPECT_CMD_PACKET_OUT(test_device(), req1, &rsp1);
  EXPECT_CMD_PACKET_OUT(test_device(), req2, &rsp2);
  StartTestDevice();

  size_t cb_event_count = 0u;
  size_t transaction_count = 0u;

  test_device()->SetTransactionCallback([&transaction_count]() { transaction_count++; },
                                        dispatcher());

  auto cb = [&cb_event_count](CommandChannel::TransactionId, const EventPacket& event) {
    EXPECT_EQ(hci_spec::kCommandCompleteEventCode, event.event_code());
    hci_spec::OpCode expected_opcode;
    if (cb_event_count == 0u) {
      expected_opcode = hci_spec::kReset;
    } else {
      expected_opcode = hci_spec::kInquiryCancel;
    }
    EXPECT_EQ(expected_opcode,
              le16toh(event.params<hci_spec::CommandCompleteEventParams>().command_opcode));
    cb_event_count++;
  };

  auto reset = CommandPacket::New(hci_spec::kReset);
  [[maybe_unused]] auto reset_id = cmd_channel()->SendCommand(std::move(reset), cb);
  auto inquiry = CommandPacket::New(hci_spec::kInquiryCancel);
  [[maybe_unused]] auto inquiry_id = cmd_channel()->SendCommand(std::move(inquiry), cb);

  RunLoopUntilIdle();

  EXPECT_EQ(1u, transaction_count);
  EXPECT_EQ(1u, cb_event_count);

  test_device()->SendCommandChannelPacket(rsp_commandsavail);

  RunLoopUntilIdle();

  EXPECT_EQ(2u, transaction_count);
  EXPECT_EQ(2u, cb_event_count);
}

// Tests:
//  - Different opcodes can be sent concurrently
//  - Same opcodes are queued until a status opcode is sent.
TEST_F(CommandChannelTest, QueuedCommands) {
  // Set up expectations
  // clang-format off
  // HCI_Reset for the sake of testing
  auto req_reset = StaticByteBuffer(
      LowerBits(hci_spec::kReset), UpperBits(hci_spec::kReset),  // HCI_Reset opcode
      0x00                                   // parameter_total_size
      );
  auto rsp_reset = StaticByteBuffer(
      hci_spec::kCommandCompleteEventCode,
      0x03,  // parameter_total_size (4 byte payload)
      0xFF,  // num_hci_command_packets (255 can be sent)
      LowerBits(hci_spec::kReset), UpperBits(hci_spec::kReset)  // HCI_Reset opcode
      );
  auto req_inqcancel = StaticByteBuffer(
      LowerBits(hci_spec::kInquiryCancel), UpperBits(hci_spec::kInquiryCancel),  // HCI_InquiryCancel opcode
      0x00                                   // parameter_total_size
      );
  auto rsp_inqcancel = StaticByteBuffer(
      hci_spec::kCommandCompleteEventCode,
      0x03,  // parameter_total_size (4 byte payload)
      0xFF,  // num_hci_command_packets (255 can be sent)
      LowerBits(hci_spec::kInquiryCancel), UpperBits(hci_spec::kInquiryCancel)  // HCI_Reset opcode
      );
  auto rsp_commandsavail = StaticByteBuffer(
       hci_spec::kCommandStatusEventCode,
      0x04,  // parameter_total_size (3 byte payload)
      hci_spec::StatusCode::kSuccess, 0xFA, // status, num_hci_command_packets (250 can be sent)
      0x00, 0x00 // No associated opcode.
      );
  // clang-format on

  // We handle our own responses to make sure commands are queued.
  EXPECT_CMD_PACKET_OUT(test_device(), req_reset, );
  EXPECT_CMD_PACKET_OUT(test_device(), req_inqcancel, );
  EXPECT_CMD_PACKET_OUT(test_device(), req_reset, &rsp_reset);
  StartTestDevice();

  size_t transaction_count = 0u;
  size_t reset_count = 0u;
  size_t cancel_count = 0u;

  test_device()->SetTransactionCallback([&transaction_count]() { transaction_count++; },
                                        dispatcher());

  auto cb = [&reset_count, &cancel_count](CommandChannel::TransactionId id,
                                          const EventPacket& event) {
    EXPECT_EQ(hci_spec::kCommandCompleteEventCode, event.event_code());
    auto opcode = le16toh(event.params<hci_spec::CommandCompleteEventParams>().command_opcode);
    if (opcode == hci_spec::kReset) {
      reset_count++;
    } else if (opcode == hci_spec::kInquiryCancel) {
      cancel_count++;
    } else {
      EXPECT_TRUE(false) << "Unexpected opcode in command callback!";
    }
  };

  // CommandChannel only one can be sent - update num_hci_command_packets
  test_device()->SendCommandChannelPacket(rsp_commandsavail);

  auto packet = CommandPacket::New(hci_spec::kReset);
  cmd_channel()->SendCommand(std::move(packet), cb);
  packet = CommandPacket::New(hci_spec::kInquiryCancel);
  cmd_channel()->SendCommand(std::move(packet), cb);
  packet = CommandPacket::New(hci_spec::kReset);
  cmd_channel()->SendCommand(std::move(packet), cb);

  RunLoopUntilIdle();

  // Different opcodes can be sent without a reply
  EXPECT_EQ(2u, transaction_count);

  // Even if we get a response to one, the duplicate opcode is still queued.
  test_device()->SendCommandChannelPacket(rsp_inqcancel);
  RunLoopUntilIdle();

  EXPECT_EQ(2u, transaction_count);
  EXPECT_EQ(1u, cancel_count);
  EXPECT_EQ(0u, reset_count);

  // Once we get a reset back, the second can be sent (and replied to)
  test_device()->SendCommandChannelPacket(rsp_reset);
  RunLoopUntilIdle();

  EXPECT_EQ(3u, transaction_count);
  EXPECT_EQ(1u, cancel_count);
  EXPECT_EQ(2u, reset_count);
}

// Tests:
//  - Asynchronous commands are handled correctly (two callbacks, one for
//    status, one for complete)
//  - Asynchronous commands with the same event result are queued even if they
//    have different opcodes.
//  - Can't register an event handler when an asynchronous command is waiting.
TEST_F(CommandChannelTest, AsynchronousCommands) {
  constexpr hci_spec::EventCode kTestEventCode0 = 0xFE;
  // Set up expectations
  // clang-format off
  // Using HCI_Reset for testing.
  auto req_reset = StaticByteBuffer(
      LowerBits(hci_spec::kReset), UpperBits(hci_spec::kReset),  // HCI_Reset opcode
      0x00                                   // parameter_total_size
      );
  auto rsp_resetstatus = StaticByteBuffer(
       hci_spec::kCommandStatusEventCode,
      0x04,  // parameter_total_size (4 byte payload)
      hci_spec::StatusCode::kSuccess, 0xFA, // status, num_hci_command_packets (250 can be sent)
      LowerBits(hci_spec::kReset), UpperBits(hci_spec::kReset)  // HCI_Reset opcode
      );
  auto req_inqcancel = StaticByteBuffer(
      LowerBits(hci_spec::kInquiryCancel), UpperBits(hci_spec::kInquiryCancel),  // HCI_InquiryCancel opcode
      0x00                                   // parameter_total_size
      );
  auto rsp_inqstatus = StaticByteBuffer(
       hci_spec::kCommandStatusEventCode,
      0x04,  // parameter_total_size (4 byte payload)
      hci_spec::StatusCode::kSuccess, 0xFA, // status, num_hci_command_packets (250 can be sent)
      LowerBits(hci_spec::kInquiryCancel), UpperBits(hci_spec::kInquiryCancel)  // HCI_Reset opcode
      );
  auto rsp_bogocomplete = StaticByteBuffer(
      kTestEventCode0,
      0x00 // parameter_total_size (no payload)
      );
  // clang-format on

  EXPECT_CMD_PACKET_OUT(test_device(), req_reset, &rsp_resetstatus);
  EXPECT_CMD_PACKET_OUT(test_device(), req_inqcancel, &rsp_inqstatus);
  StartTestDevice();

  CommandChannel::TransactionId id1, id2;
  size_t cb_count = 0u;

  auto cb = [&id1, &id2, &cb_count, kTestEventCode0](CommandChannel::TransactionId callback_id,
                                                     const EventPacket& event) {
    if (cb_count < 2) {
      EXPECT_EQ(id1, callback_id);
    } else {
      EXPECT_EQ(id2, callback_id);
    }
    if ((cb_count % 2) == 0) {
      EXPECT_EQ(hci_spec::kCommandStatusEventCode, event.event_code());
      auto params = event.params<hci_spec::CommandStatusEventParams>();
      EXPECT_EQ(hci_spec::StatusCode::kSuccess, params.status);
    } else if ((cb_count % 2) == 1) {
      EXPECT_EQ(kTestEventCode0, event.event_code());
    }
    cb_count++;
  };

  auto packet = CommandPacket::New(hci_spec::kReset);
  id1 = cmd_channel()->SendCommand(std::move(packet), cb, kTestEventCode0);

  RunLoopUntilIdle();

  // Should have received the Status but not the result.
  EXPECT_EQ(1u, cb_count);

  // Setting another event up with different opcode will still queue the command because we don't
  // want to have two commands waiting on an event.
  packet = CommandPacket::New(hci_spec::kInquiryCancel);
  id2 = cmd_channel()->SendCommand(std::move(packet), cb, kTestEventCode0);
  RunLoopUntilIdle();

  EXPECT_EQ(1u, cb_count);

  // Sending the complete will release the queue and send the next command.
  test_device()->SendCommandChannelPacket(rsp_bogocomplete);
  RunLoopUntilIdle();

  EXPECT_EQ(3u, cb_count);

  // Should not be able to register an event handler now, we're still waiting on the asynchronous
  // command.
  auto event_id0 = cmd_channel()->AddEventHandler(
      kTestEventCode0, [](const auto&) { return EventCallbackResult::kContinue; });
  EXPECT_EQ(0u, event_id0);

  // Finish out the commands.
  test_device()->SendCommandChannelPacket(rsp_bogocomplete);
  RunLoopUntilIdle();

  EXPECT_EQ(4u, cb_count);
}

// Tests:
//  - Updating to say no commands can be sent works. (commands are queued)
//  - Can't add an event handler once a SendCommand() succeeds watiing on
//    the same event code. (even if they are queued)
TEST_F(CommandChannelTest, AsyncQueueWhenBlocked) {
  constexpr hci_spec::EventCode kTestEventCode0 = 0xF0;
  // Set up expectations
  // clang-format off
  // Using HCI_Reset for testing.
  auto req_reset = StaticByteBuffer(
      LowerBits(hci_spec::kReset), UpperBits(hci_spec::kReset),  // HCI_Reset opcode
      0x00                                   // parameter_total_size
      );
  auto rsp_resetstatus = StaticByteBuffer(
       hci_spec::kCommandStatusEventCode,
      0x04,  // parameter_total_size (4 byte payload)
      hci_spec::StatusCode::kSuccess, 0xFA, // status, num_hci_command_packets (250 can be sent)
      LowerBits(hci_spec::kReset), UpperBits(hci_spec::kReset)  // HCI_Reset opcode
      );
  auto rsp_bogocomplete = StaticByteBuffer(
      kTestEventCode0,
      0x00 // parameter_total_size (no payload)
      );
  auto rsp_nocommandsavail = StaticByteBuffer(
       hci_spec::kCommandStatusEventCode,
      0x04,  // parameter_total_size (3 byte payload)
      hci_spec::StatusCode::kSuccess, 0x00, // status, num_hci_command_packets (none can be sent)
      0x00, 0x00 // No associated opcode.
      );
  auto rsp_commandsavail = StaticByteBuffer(
       hci_spec::kCommandStatusEventCode,
      0x04,  // parameter_total_size (3 byte payload)
      hci_spec::StatusCode::kSuccess, 0x01, // status, num_hci_command_packets (one can be sent)
      0x00, 0x00 // No associated opcode.
      );
  // clang-format on

  size_t transaction_count = 0u;

  test_device()->SetTransactionCallback([&transaction_count]() { transaction_count++; },
                                        dispatcher());

  EXPECT_CMD_PACKET_OUT(test_device(), req_reset, &rsp_resetstatus, &rsp_bogocomplete);
  StartTestDevice();

  test_device()->SendCommandChannelPacket(rsp_nocommandsavail);

  RunLoopUntilIdle();

  CommandChannel::TransactionId id;
  size_t cb_count = 0;
  auto cb = [&cb_count, &id, kTestEventCode0](CommandChannel::TransactionId callback_id,
                                              const EventPacket& event) {
    cb_count++;
    EXPECT_EQ(callback_id, id);
    if (cb_count == 1) {
      ASSERT_EQ(hci_spec::kCommandStatusEventCode, event.event_code());
      const auto params = event.params<hci_spec::CommandStatusEventParams>();
      EXPECT_EQ(hci_spec::StatusCode::kSuccess, params.status);
      EXPECT_EQ(hci_spec::kReset, params.command_opcode);
    } else {
      EXPECT_EQ(kTestEventCode0, event.event_code());
    }
  };

  auto packet = CommandPacket::New(hci_spec::kReset);
  id = cmd_channel()->SendCommand(std::move(packet), cb, kTestEventCode0);

  RunLoopUntilIdle();

  ASSERT_NE(0u, id);
  ASSERT_EQ(0u, transaction_count);

  // This returns invalid because an async command is registered.
  auto invalid_id = cmd_channel()->AddEventHandler(
      kTestEventCode0, [](const auto&) { return EventCallbackResult::kContinue; });

  RunLoopUntilIdle();

  ASSERT_EQ(0u, invalid_id);

  // Commands become available and the whole transaction finishes.
  test_device()->SendCommandChannelPacket(rsp_commandsavail);

  RunLoopUntilIdle();

  ASSERT_EQ(1u, transaction_count);
  ASSERT_EQ(2u, cb_count);
}

// Tests:
//  - Events are routed to the event handler.
//  - Can't queue a command on the same event that is already in an event handler.
TEST_F(CommandChannelTest, EventHandlerBasic) {
  constexpr hci_spec::EventCode kTestEventCode0 = 0xFD;
  constexpr hci_spec::EventCode kTestEventCode1 = 0xFE;
  StaticByteBuffer cmd_status(hci_spec::kCommandStatusEventCode, 0x04, 0x00, 0x01, 0x00, 0x00);
  auto cmd_complete = StaticByteBuffer(hci_spec::kCommandCompleteEventCode, 0x03, 0x01, 0x00, 0x00);
  auto event0 = StaticByteBuffer(kTestEventCode0, 0x00);
  auto event1 = StaticByteBuffer(kTestEventCode1, 0x00);

  int event_count0 = 0;
  auto event_cb0 = [&event_count0, kTestEventCode0](const EventPacket& event) {
    event_count0++;
    EXPECT_EQ(kTestEventCode0, event.event_code());
    return EventCallbackResult::kContinue;
  };

  int event_count1 = 0;
  auto event_cb1 = [&event_count1, kTestEventCode0](const EventPacket& event) {
    event_count1++;
    EXPECT_EQ(kTestEventCode0, event.event_code());
    return EventCallbackResult::kContinue;
  };

  int event_count2 = 0;
  auto event_cb2 = [&event_count2, kTestEventCode1](const EventPacket& event) {
    event_count2++;
    EXPECT_EQ(kTestEventCode1, event.event_code());
    return EventCallbackResult::kContinue;
  };
  auto id0 = cmd_channel()->AddEventHandler(kTestEventCode0, event_cb0);
  EXPECT_NE(0u, id0);

  // Can register a handler for the same event code more than once.
  auto id1 = cmd_channel()->AddEventHandler(kTestEventCode0, event_cb1);
  EXPECT_NE(0u, id1);
  EXPECT_NE(id0, id1);

  // Add a handler for a different event code.
  auto id2 = cmd_channel()->AddEventHandler(kTestEventCode1, event_cb2);
  EXPECT_NE(0u, id2);

  auto reset = CommandPacket::New(hci_spec::kReset);
  auto transaction_id = cmd_channel()->SendCommand(
      std::move(reset), [](auto, const auto&) {}, kTestEventCode0);

  EXPECT_EQ(0u, transaction_id);

  StartTestDevice();
  test_device()->SendCommandChannelPacket(cmd_status);
  test_device()->SendCommandChannelPacket(cmd_complete);
  test_device()->SendCommandChannelPacket(event1);
  test_device()->SendCommandChannelPacket(event0);
  test_device()->SendCommandChannelPacket(cmd_complete);
  test_device()->SendCommandChannelPacket(event0);
  test_device()->SendCommandChannelPacket(event0);
  test_device()->SendCommandChannelPacket(cmd_status);
  test_device()->SendCommandChannelPacket(event1);

  RunLoopUntilIdle();

  EXPECT_EQ(3, event_count0);
  EXPECT_EQ(3, event_count1);
  EXPECT_EQ(2, event_count2);

  event_count0 = 0;
  event_count1 = 0;
  event_count2 = 0;

  // Remove the first event handler.
  cmd_channel()->RemoveEventHandler(id0);
  test_device()->SendCommandChannelPacket(event0);
  test_device()->SendCommandChannelPacket(event0);
  test_device()->SendCommandChannelPacket(event0);
  test_device()->SendCommandChannelPacket(event1);
  test_device()->SendCommandChannelPacket(event0);
  test_device()->SendCommandChannelPacket(event0);
  test_device()->SendCommandChannelPacket(event0);
  test_device()->SendCommandChannelPacket(event0);
  test_device()->SendCommandChannelPacket(event1);

  RunLoopUntilIdle();

  EXPECT_EQ(0, event_count0);
  EXPECT_EQ(7, event_count1);
  EXPECT_EQ(2, event_count2);

  event_count0 = 0;
  event_count1 = 0;
  event_count2 = 0;

  // Remove the second event handler.
  cmd_channel()->RemoveEventHandler(id1);
  test_device()->SendCommandChannelPacket(event0);
  test_device()->SendCommandChannelPacket(event0);
  test_device()->SendCommandChannelPacket(event1);
  test_device()->SendCommandChannelPacket(event0);
  test_device()->SendCommandChannelPacket(event1);
  test_device()->SendCommandChannelPacket(event1);

  RunLoopUntilIdle();

  EXPECT_EQ(0, event_count0);
  EXPECT_EQ(0, event_count1);
  EXPECT_EQ(3, event_count2);
}

// Tests:
//  - can't send a command that masks an event handler.
//  - can send a command without a callback.
TEST_F(CommandChannelTest, EventHandlerEventWhileTransactionPending) {
  // clang-format off
  // HCI_Reset
  auto req = StaticByteBuffer(
      LowerBits(hci_spec::kReset), UpperBits(hci_spec::kReset),  // HCI_Reset opcode
      0x00                                   // parameter_total_size
      );

  auto req_complete = StaticByteBuffer(
      hci_spec::kCommandCompleteEventCode,
      0x03,  // parameter_total_size (3 byte payload)
      0x01, // num_hci_command_packets (1 can be sent)
      LowerBits(hci_spec::kReset), UpperBits(hci_spec::kReset)  // HCI_Reset opcode
      );
  // clang-format on

  constexpr hci_spec::EventCode kTestEventCode = 0xFE;
  auto event = StaticByteBuffer(kTestEventCode, 0x01, 0x00);

  // We will send the HCI_Reset command with kTestEventCode as the completion event. The event
  // handler we register below should only get invoked once and after the pending transaction
  // completes.
  EXPECT_CMD_PACKET_OUT(test_device(), req, &req_complete, &event, &event);
  StartTestDevice();

  int event_count = 0;
  auto event_cb = [&event_count, kTestEventCode](const EventPacket& event) {
    event_count++;
    EXPECT_EQ(kTestEventCode, event.event_code());
    EXPECT_EQ(1u, event.view().header().parameter_total_size);
    EXPECT_EQ(1u, event.view().payload_size());
    return EventCallbackResult::kContinue;
  };

  cmd_channel()->AddEventHandler(kTestEventCode, event_cb);

  auto reset = CommandPacket::New(hci_spec::kReset);
  CommandChannel::TransactionId id =
      cmd_channel()->SendCommand(std::move(reset), nullptr, kTestEventCode);
  EXPECT_EQ(0u, id);

  reset = CommandPacket::New(hci_spec::kReset);
  id = cmd_channel()->SendCommand(std::move(reset), nullptr);
  EXPECT_NE(0u, id);

  RunLoopUntilIdle();

  EXPECT_EQ(2, event_count);
}

// Tests:
//  - Calling RemoveQueuedCommand on a synchronous command that has already been sent to the
//    controller returns false.
//  - The command still completes and notifies the callback.
TEST_F(CommandChannelTest, RemoveQueuedSyncCommandPendingStatus) {
  auto req_reset = StaticByteBuffer(LowerBits(hci_spec::kReset),
                                    UpperBits(hci_spec::kReset),  // HCI_Reset opcode
                                    0x00                          // parameter_total_size
  );
  auto rsp_reset = StaticByteBuffer(hci_spec::kCommandCompleteEventCode,
                                    0x03,  // parameter_total_size (3 byte payload)
                                    0xFF,  // num_hci_command_packets (255 can be sent)
                                    LowerBits(hci_spec::kReset),
                                    UpperBits(hci_spec::kReset)  // HCI_Reset opcode
  );
  EXPECT_CMD_PACKET_OUT(test_device(), req_reset, );
  StartTestDevice();

  int transaction_count = 0u;
  test_device()->SetTransactionCallback([&transaction_count]() { transaction_count++; },
                                        dispatcher());

  auto cmd = CommandPacket::New(hci_spec::kReset);
  int cmd_cb_count = 0;
  auto cmd_cb = [&cmd_cb_count](auto, auto&) { cmd_cb_count++; };
  auto cmd_id = cmd_channel()->SendCommand(std::move(cmd), std::move(cmd_cb));
  EXPECT_NE(0u, cmd_id);

  RunLoopUntilIdle();

  EXPECT_EQ(1, transaction_count);
  EXPECT_FALSE(cmd_channel()->RemoveQueuedCommand(cmd_id));
  test_device()->SendCommandChannelPacket(rsp_reset);

  RunLoopUntilIdle();

  EXPECT_EQ(1, transaction_count);
  EXPECT_EQ(1, cmd_cb_count);
}

// Tests:
//  - Remove a synchronous command that is queued up behind another command with the same opcode.
//  - The first command (after removal) does not receive the update event for the second command.
TEST_F(CommandChannelTest, RemoveQueuedQueuedSyncCommand) {
  using namespace std::placeholders;
  auto req_reset = StaticByteBuffer(LowerBits(hci_spec::kReset),
                                    UpperBits(hci_spec::kReset),  // HCI_Reset opcode
                                    0x00                          // parameter_total_size
  );
  auto rsp_reset = StaticByteBuffer(hci_spec::kCommandCompleteEventCode,
                                    0x03,  // parameter_total_size (4 byte payload)
                                    0xFF,  // num_hci_command_packets (255 can be sent)
                                    LowerBits(hci_spec::kReset),
                                    UpperBits(hci_spec::kReset)  // HCI_Reset opcode
  );
  EXPECT_CMD_PACKET_OUT(test_device(), req_reset, );
  StartTestDevice();

  int transaction_count = 0u;
  test_device()->SetTransactionCallback([&transaction_count]() { transaction_count++; },
                                        dispatcher());

  auto event_cb = [](CommandChannel::TransactionId id, const EventPacket& event, int* event_count) {
    EXPECT_EQ(hci_spec::kCommandCompleteEventCode, event.event_code());
    (*event_count)++;
  };

  // Send two reset commands so that the second one is queued up.
  auto reset = CommandPacket::New(hci_spec::kReset);
  int event_count0 = 0;
  auto id0 =
      cmd_channel()->SendCommand(std::move(reset), std::bind(event_cb, _1, _2, &event_count0));
  EXPECT_NE(0u, id0);
  reset = CommandPacket::New(hci_spec::kReset);
  int event_count1 = 0;
  auto id1 =
      cmd_channel()->SendCommand(std::move(reset), std::bind(event_cb, _1, _2, &event_count1));
  EXPECT_NE(0u, id1);

  RunLoopUntilIdle();

  EXPECT_EQ(1, transaction_count);
  EXPECT_TRUE(cmd_channel()->RemoveQueuedCommand(id1));

  RunLoopUntilIdle();

  EXPECT_EQ(0, event_count0);
  test_device()->SendCommandChannelPacket(rsp_reset);

  RunLoopUntilIdle();

  // Only one command should have been sent.
  EXPECT_EQ(1, transaction_count);
  // The queued (then canceled) command should never have gotten an event.
  EXPECT_EQ(0, event_count1);
  // The sent command should have gotten one event (CommandComplete).
  EXPECT_EQ(1, event_count0);
}

// Read Remote Supported Features
const StaticByteBuffer kReadRemoteSupportedFeaturesCmd(
    LowerBits(hci_spec::kReadRemoteSupportedFeatures),
    UpperBits(hci_spec::kReadRemoteSupportedFeatures),
    0x02,       // parameter_total_size
    0x01, 0x00  // connection_handle
);

// Command Status for Read Remote Supported Features
const auto kReadRemoteSupportedFeaturesRsp =
    StaticByteBuffer(hci_spec::kCommandStatusEventCode,
                     0x04,                            // parameter_total_size (4 byte payload)
                     hci_spec::StatusCode::kSuccess,  // status
                     0xFF,                            // num_hci_command_packets
                     LowerBits(hci_spec::kReadRemoteSupportedFeatures),
                     UpperBits(hci_spec::kReadRemoteSupportedFeatures)  // opcode
    );

// Read Remote Supported Features Complete
const auto kReadRemoteSupportedFeaturesComplete =
    StaticByteBuffer(hci_spec::kReadRemoteSupportedFeaturesCompleteEventCode,
                     0x0B,                            // parameter_total_size (11 bytes)
                     hci_spec::StatusCode::kSuccess,  // status
                     0x01, 0x00,                      // connection_handle
                     0xFF, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x80  // lmp_features
                     // Set: 3 slot packets, 5 slot packets, Encryption, Timing Accuracy,
                     // Role Switch, Hold Mode, Sniff Mode, LE Supported, Extended Features
    );

// Tests:
//  - Remove an asynchronous command that is queued up behind another command with the same opcode.
//  - The first command (after removal) does not receive the update event for the second command.
TEST_F(CommandChannelTest, RemoveQueuedQueuedAsyncCommand) {
  using namespace std::placeholders;
  EXPECT_CMD_PACKET_OUT(test_device(), kReadRemoteSupportedFeaturesCmd, );
  StartTestDevice();

  int transaction_count = 0u;
  test_device()->SetTransactionCallback([&transaction_count]() { transaction_count++; },
                                        dispatcher());

  auto event_cb = [](CommandChannel::TransactionId id, const EventPacket& event, int* event_count) {
    (*event_count)++;
  };

  // Send two read commands so that the second one is queued up.
  auto packet = MakeReadRemoteSupportedFeatures(0x0001);
  int event_count0 = 0;
  auto id0 =
      cmd_channel()->SendCommand(std::move(packet), std::bind(event_cb, _1, _2, &event_count0),
                                 hci_spec::kReadRemoteSupportedFeaturesCompleteEventCode);
  EXPECT_NE(0u, id0);
  packet = MakeReadRemoteSupportedFeatures(0x0001);
  int event_count1 = 0;
  auto id1 =
      cmd_channel()->SendCommand(std::move(packet), std::bind(event_cb, _1, _2, &event_count1),
                                 hci_spec::kReadRemoteSupportedFeaturesCompleteEventCode);
  EXPECT_NE(0u, id1);

  RunLoopUntilIdle();

  EXPECT_EQ(1, transaction_count);
  EXPECT_TRUE(cmd_channel()->RemoveQueuedCommand(id1));

  RunLoopUntilIdle();

  EXPECT_EQ(0, event_count0);
  test_device()->SendCommandChannelPacket(kReadRemoteSupportedFeaturesRsp);
  test_device()->SendCommandChannelPacket(kReadRemoteSupportedFeaturesComplete);

  RunLoopUntilIdle();

  // Only one command should have been sent.
  EXPECT_EQ(1, transaction_count);
  // The queued (then canceled) command should never have gotten an event.
  EXPECT_EQ(0, event_count1);
  // The sent command should have gotten two events (Command Status, Read Remote Supported Features
  // Complete).
  EXPECT_EQ(2, event_count0);
}

// Tests:
//  - Calling RemoveQueuedCommand on an asynchronous command that has received both Command Status
//    and command completion events returns false and has no effect.
TEST_F(CommandChannelTest, RemoveQueuedCompletedAsyncCommand) {
  EXPECT_CMD_PACKET_OUT(test_device(), kReadRemoteSupportedFeaturesCmd,
                        &kReadRemoteSupportedFeaturesRsp, &kReadRemoteSupportedFeaturesComplete);
  StartTestDevice();

  int transaction_count = 0;
  test_device()->SetTransactionCallback([&transaction_count] { transaction_count++; },
                                        dispatcher());

  int event_count = 0;
  auto event_cb = [&event_count](CommandChannel::TransactionId id, const EventPacket& event) {
    event_count++;
  };

  auto packet = MakeReadRemoteSupportedFeatures(0x0001);
  auto id = cmd_channel()->SendCommand(std::move(packet), std::move(event_cb),
                                       hci_spec::kReadRemoteSupportedFeaturesCompleteEventCode);
  EXPECT_NE(0u, id);

  RunLoopUntilIdle();

  EXPECT_EQ(2, event_count);
  EXPECT_FALSE(cmd_channel()->RemoveQueuedCommand(id));

  RunLoopUntilIdle();

  // Only one command should have been sent.
  EXPECT_EQ(1, transaction_count);
  // The sent command should have received CommandStatus and InquiryComplete.
  EXPECT_EQ(2, event_count);
}

// Tests:
//  - Calling RemoveQueuedCommand on an asynchronous command that has already been sent to the
//    controller returns false.
//  - The command still notifies the callback for update and completion events.
TEST_F(CommandChannelTest, RemoveQueuedAsyncCommandPendingUpdate) {
  EXPECT_CMD_PACKET_OUT(test_device(), kReadRemoteSupportedFeaturesCmd, );
  StartTestDevice();

  int transaction_count = 0;
  test_device()->SetTransactionCallback([&transaction_count] { transaction_count++; },
                                        dispatcher());

  CommandChannel::TransactionId cmd_id;
  int cmd_events = 0;
  auto cmd_cb = [&cmd_id, &cmd_events](CommandChannel::TransactionId id, const EventPacket& event) {
    EXPECT_EQ(cmd_id, id);
    if (cmd_events == 0) {
      EXPECT_EQ(hci_spec::kCommandStatusEventCode, event.event_code());
    }
    cmd_events++;
  };

  auto cmd_packet = MakeReadRemoteSupportedFeatures(0x0001);
  cmd_id = cmd_channel()->SendCommand(std::move(cmd_packet), std::move(cmd_cb),
                                      hci_spec::kReadRemoteSupportedFeaturesCompleteEventCode);
  EXPECT_NE(0u, cmd_id);

  RunLoopUntilIdle();

  EXPECT_EQ(0, cmd_events);
  EXPECT_FALSE(cmd_channel()->RemoveQueuedCommand(cmd_id));

  RunLoopUntilIdle();

  test_device()->SendCommandChannelPacket(kReadRemoteSupportedFeaturesRsp);
  test_device()->SendCommandChannelPacket(kReadRemoteSupportedFeaturesComplete);

  RunLoopUntilIdle();

  EXPECT_EQ(1, transaction_count);
  // The command should have gotten update and complete events.
  EXPECT_EQ(2, cmd_events);
}

// Tests:
//  - Calling RemoveQueuedCommand on an asynchronous command that has already been sent to the
//    controller and gotten Command Status returns false.
//  - The command still notifies the callback for completion event.
TEST_F(CommandChannelTest, RemoveQueuedAsyncCommandPendingCompletion) {
  EXPECT_CMD_PACKET_OUT(test_device(), kReadRemoteSupportedFeaturesCmd,
                        &kReadRemoteSupportedFeaturesRsp);
  StartTestDevice();

  int transaction_count = 0;
  test_device()->SetTransactionCallback([&transaction_count] { transaction_count++; },
                                        dispatcher());

  CommandChannel::TransactionId cmd_id;
  int cmd_events = 0;
  auto cmd_cb = [&cmd_id, &cmd_events](CommandChannel::TransactionId id, const EventPacket& event) {
    EXPECT_EQ(cmd_id, id);
    if (cmd_events == 0) {
      EXPECT_EQ(hci_spec::kCommandStatusEventCode, event.event_code());
    }
    cmd_events++;
  };

  auto cmd_packet = MakeReadRemoteSupportedFeatures(0x0001);
  cmd_id = cmd_channel()->SendCommand(std::move(cmd_packet), std::move(cmd_cb),
                                      hci_spec::kReadRemoteSupportedFeaturesCompleteEventCode);
  EXPECT_NE(0u, cmd_id);

  RunLoopUntilIdle();

  EXPECT_EQ(1, cmd_events);
  EXPECT_FALSE(cmd_channel()->RemoveQueuedCommand(cmd_id));

  RunLoopUntilIdle();

  test_device()->SendCommandChannelPacket(kReadRemoteSupportedFeaturesComplete);

  RunLoopUntilIdle();

  EXPECT_EQ(1, transaction_count);
  // The command should have gotten update and complete events.
  EXPECT_EQ(2, cmd_events);
}

TEST_F(CommandChannelTest, VendorEventHandler) {
  constexpr hci_spec::EventCode kTestSubeventCode0 = 0x10;
  constexpr hci_spec::EventCode kTestSubeventCode1 = 0x12;
  StaticByteBuffer vendor_event_bytes0(hci_spec::kVendorDebugEventCode, 0x01, kTestSubeventCode0);
  auto vendor_event_bytes1 =
      StaticByteBuffer(hci_spec::kVendorDebugEventCode, 0x01, kTestSubeventCode1);

  int event_count0 = 0;
  auto event_cb0 = [&event_count0, kTestSubeventCode0](const EventPacket& event) {
    event_count0++;
    EXPECT_EQ(hci_spec::kVendorDebugEventCode, event.event_code());
    EXPECT_EQ(kTestSubeventCode0, event.params<hci_spec::VendorEventParams>().subevent_code);
    return EventCallbackResult::kContinue;
  };

  int event_count1 = 0;
  auto event_cb1 = [&event_count1, kTestSubeventCode1](const EventPacket& event) {
    event_count1++;
    EXPECT_EQ(hci_spec::kVendorDebugEventCode, event.event_code());
    EXPECT_EQ(kTestSubeventCode1, event.params<hci_spec::VendorEventParams>().subevent_code);
    return EventCallbackResult::kContinue;
  };

  auto id0 = cmd_channel()->AddVendorEventHandler(kTestSubeventCode0, event_cb0);
  EXPECT_NE(0u, id0);

  // Can register a handler for the same event code more than once.
  auto id1 = cmd_channel()->AddVendorEventHandler(kTestSubeventCode0, event_cb0);
  EXPECT_NE(0u, id1);
  EXPECT_NE(id0, id1);

  // Add a handler for a different event code.
  auto id2 = cmd_channel()->AddVendorEventHandler(kTestSubeventCode1, event_cb1);
  EXPECT_NE(0u, id2);

  StartTestDevice();

  test_device()->SendCommandChannelPacket(vendor_event_bytes0);
  RunLoopUntilIdle();
  EXPECT_EQ(2, event_count0);
  EXPECT_EQ(0, event_count1);

  test_device()->SendCommandChannelPacket(vendor_event_bytes0);
  RunLoopUntilIdle();
  EXPECT_EQ(4, event_count0);
  EXPECT_EQ(0, event_count1);

  test_device()->SendCommandChannelPacket(vendor_event_bytes1);
  RunLoopUntilIdle();
  EXPECT_EQ(4, event_count0);
  EXPECT_EQ(1, event_count1);

  // Remove the first event handler.
  cmd_channel()->RemoveEventHandler(id0);
  test_device()->SendCommandChannelPacket(vendor_event_bytes0);
  test_device()->SendCommandChannelPacket(vendor_event_bytes1);
  RunLoopUntilIdle();
  EXPECT_EQ(5, event_count0);
  EXPECT_EQ(2, event_count1);
}

TEST_F(CommandChannelTest, LEMetaEventHandler) {
  constexpr hci_spec::EventCode kTestSubeventCode0 = 0xFE;
  constexpr hci_spec::EventCode kTestSubeventCode1 = 0xFF;
  auto le_meta_event_bytes0 =
      StaticByteBuffer(hci_spec::kLEMetaEventCode, 0x01, kTestSubeventCode0);
  auto le_meta_event_bytes1 =
      StaticByteBuffer(hci_spec::kLEMetaEventCode, 0x01, kTestSubeventCode1);

  int event_count0 = 0;
  auto event_cb0 = [&event_count0, kTestSubeventCode0](const EventPacket& event) {
    event_count0++;
    EXPECT_EQ(hci_spec::kLEMetaEventCode, event.event_code());
    EXPECT_EQ(kTestSubeventCode0, event.params<hci_spec::LEMetaEventParams>().subevent_code);
    return EventCallbackResult::kContinue;
  };

  int event_count1 = 0;
  auto event_cb1 = [&event_count1, kTestSubeventCode1](const EventPacket& event) {
    event_count1++;
    EXPECT_EQ(hci_spec::kLEMetaEventCode, event.event_code());
    EXPECT_EQ(kTestSubeventCode1, event.params<hci_spec::LEMetaEventParams>().subevent_code);
    return EventCallbackResult::kContinue;
  };

  auto id0 = cmd_channel()->AddLEMetaEventHandler(kTestSubeventCode0, event_cb0);
  EXPECT_NE(0u, id0);

  // Can register a handler for the same event code more than once.
  auto id1 = cmd_channel()->AddLEMetaEventHandler(kTestSubeventCode0, event_cb0);
  EXPECT_NE(0u, id1);
  EXPECT_NE(id0, id1);

  // Add a handler for a different event code.
  auto id2 = cmd_channel()->AddLEMetaEventHandler(kTestSubeventCode1, event_cb1);
  EXPECT_NE(0u, id2);

  StartTestDevice();

  test_device()->SendCommandChannelPacket(le_meta_event_bytes0);
  RunLoopUntilIdle();
  EXPECT_EQ(2, event_count0);
  EXPECT_EQ(0, event_count1);

  test_device()->SendCommandChannelPacket(le_meta_event_bytes0);
  RunLoopUntilIdle();
  EXPECT_EQ(4, event_count0);
  EXPECT_EQ(0, event_count1);

  test_device()->SendCommandChannelPacket(le_meta_event_bytes1);
  RunLoopUntilIdle();
  EXPECT_EQ(4, event_count0);
  EXPECT_EQ(1, event_count1);

  // Remove the first event handler.
  cmd_channel()->RemoveEventHandler(id0);
  test_device()->SendCommandChannelPacket(le_meta_event_bytes0);
  test_device()->SendCommandChannelPacket(le_meta_event_bytes1);
  RunLoopUntilIdle();
  EXPECT_EQ(5, event_count0);
  EXPECT_EQ(2, event_count1);
}

TEST_F(CommandChannelTest, EventHandlerIdsDontCollide) {
  // Add a LE Meta event handler and a event handler and make sure that IDs are generated correctly
  // across the two methods.
  EXPECT_EQ(1u, cmd_channel()->AddLEMetaEventHandler(
                    hci_spec::kLEConnectionCompleteSubeventCode,
                    [](const auto&) { return EventCallbackResult::kContinue; }));
  EXPECT_EQ(2u, cmd_channel()->AddEventHandler(
                    hci_spec::kDisconnectionCompleteEventCode,
                    [](const auto&) { return EventCallbackResult::kContinue; }));
}

// Tests:
//  - Can't register an event handler for CommandStatus or CommandComplete
TEST_F(CommandChannelTest, EventHandlerRestrictions) {
  auto id0 = cmd_channel()->AddEventHandler(hci_spec::kCommandStatusEventCode, [](const auto&) {
    return EventCallbackResult::kContinue;
  });
  EXPECT_EQ(0u, id0);
  id0 = cmd_channel()->AddEventHandler(hci_spec::kCommandCompleteEventCode,
                                       [](const auto&) { return EventCallbackResult::kContinue; });
  EXPECT_EQ(0u, id0);
}

// Tests that an asynchronous command with a completion event code does not remove an existing
// handler for colliding LE meta subevent code.
TEST_F(CommandChannelTest, AsyncEventHandlersAndLeMetaEventHandlersDoNotInterfere) {
  // Set up expectations for the asynchronous command and its corresponding command status event.
  // clang-format off
  auto cmd = StaticByteBuffer(
      LowerBits(hci_spec::kInquiry), UpperBits(hci_spec::kInquiry),  // HCI_Inquiry opcode
      0x00                                       // parameter_total_size
  );
  auto cmd_status = StaticByteBuffer(
       hci_spec::kCommandStatusEventCode,
      0x04,  // parameter_total_size (4 byte payload)
      hci_spec::StatusCode::kSuccess, 0x01, // status, num_hci_command_packets (1 can be sent)
      LowerBits(hci_spec::kInquiry), UpperBits(hci_spec::kInquiry)  // HCI_Inquiry opcode
  );
  // clang-format on

  EXPECT_CMD_PACKET_OUT(test_device(), cmd, &cmd_status);
  StartTestDevice();

  constexpr hci_spec::EventCode kTestEventCode = 0x01;

  // Add LE event handler for kTestEventCode
  int le_event_count = 0;
  auto le_event_cb = [&](const EventPacket& event) {
    EXPECT_EQ(hci_spec::kLEMetaEventCode, event.event_code());
    EXPECT_EQ(kTestEventCode, event.params<hci_spec::LEMetaEventParams>().subevent_code);
    le_event_count++;
    return EventCallbackResult::kContinue;
  };
  cmd_channel()->AddLEMetaEventHandler(hci_spec::kLEConnectionCompleteSubeventCode,
                                       std::move(le_event_cb));

  // Initiate the async transaction with kTestEventCode as its completion code (we use
  // hci_spec::kInquiry as a dummy opcode).
  int async_cmd_cb_count = 0;
  auto async_cmd_cb = [&](auto id, const EventPacket& event) {
    if (async_cmd_cb_count == 0) {
      EXPECT_EQ(hci_spec::kCommandStatusEventCode, event.event_code());
    } else {
      EXPECT_EQ(kTestEventCode, event.event_code());
    }
    async_cmd_cb_count++;
  };
  auto packet = CommandPacket::New(hci_spec::kInquiry, 0);
  cmd_channel()->SendCommand(std::move(packet), std::move(async_cmd_cb), kTestEventCode);

  // clang-format off
  auto event_bytes = StaticByteBuffer(
      kTestEventCode,
      0x01,  // parameter_total_size
      hci_spec::StatusCode::kSuccess);
  auto le_event_bytes = StaticByteBuffer(
      hci_spec::kLEMetaEventCode,
      0x01,  // parameter_total_size
      kTestEventCode);
  // clang-format on

  // Send a spurious LE event before processing the Command Status event. This should get routed to
  // the correct event handler.
  test_device()->SendCommandChannelPacket(le_event_bytes);

  // Process the async command expectation.
  RunLoopUntilIdle();

  // End the asynchronous transaction. This should NOT unregister the LE event handler.
  test_device()->SendCommandChannelPacket(event_bytes);

  // Send more LE events. These should get routed to the LE event handler.
  test_device()->SendCommandChannelPacket(le_event_bytes);
  test_device()->SendCommandChannelPacket(le_event_bytes);

  RunLoopUntilIdle();

  // Should have received 3 LE events.
  EXPECT_EQ(3, le_event_count);

  // The async command handler should have been called twice: once for Command Status and once for
  // the completion event.
  EXPECT_EQ(2, async_cmd_cb_count);
}

TEST_F(CommandChannelTest, TransportClosedCallback) {
  StartTestDevice();

  bool closed_cb_called = false;
  auto closed_cb = [&closed_cb_called] { closed_cb_called = true; };
  transport()->SetTransportClosedCallback(closed_cb);

  async::PostTask(dispatcher(), [this] { test_device()->Stop(); });
  RunLoopUntilIdle();
  EXPECT_TRUE(closed_cb_called);
}

TEST_F(CommandChannelTest, CommandTimeoutCallback) {
  constexpr zx::duration kCommandTimeout = zx::sec(12);

  auto req_reset = StaticByteBuffer(LowerBits(hci_spec::kReset),
                                    UpperBits(hci_spec::kReset),  // HCI_Reset opcode
                                    0x00                          // parameter_total_size
  );

  // Expect the HCI_Reset command but dont send a reply back to make the command time out.
  EXPECT_CMD_PACKET_OUT(test_device(), req_reset, );
  StartTestDevice();

  size_t timeout_cb_count = 0;
  auto timeout_cb = [&] { timeout_cb_count++; };
  cmd_channel()->set_channel_timeout_cb(timeout_cb);

  size_t cmd_cb_count = 0;
  auto cb = [&](auto, auto&) { cmd_cb_count++; };

  auto packet = CommandPacket::New(hci_spec::kReset);
  CommandChannel::TransactionId id1 = cmd_channel()->SendCommand(std::move(packet), cb);
  ASSERT_NE(0u, id1);

  packet = CommandPacket::New(hci_spec::kReset);
  CommandChannel::TransactionId id2 = cmd_channel()->SendCommand(std::move(packet), cb);
  ASSERT_NE(0u, id2);

  // Run the loop until the command timeout task gets scheduled.
  RunLoopUntilIdle();
  EXPECT_EQ(0u, timeout_cb_count);
  EXPECT_EQ(0u, cmd_cb_count);

  RunLoopFor(kCommandTimeout);

  EXPECT_EQ(1u, timeout_cb_count);
  EXPECT_EQ(0u, cmd_cb_count);

  DeleteTransport();
  EXPECT_EQ(2u, cmd_cb_count);
}

TEST_F(CommandChannelTest, DestroyChannelInTimeoutCallback) {
  constexpr zx::duration kCommandTimeout = zx::sec(12);

  auto req_reset = StaticByteBuffer(LowerBits(hci_spec::kReset),
                                    UpperBits(hci_spec::kReset),  // HCI_Reset opcode
                                    0x00                          // parameter_total_size
  );

  // Expect the HCI_Reset command but dont send a reply back to make the command time out.
  EXPECT_CMD_PACKET_OUT(test_device(), req_reset, );
  StartTestDevice();

  size_t timeout_cb_count = 0;
  auto timeout_cb = [&] {
    timeout_cb_count++;
    DeleteTransport();
  };
  cmd_channel()->set_channel_timeout_cb(timeout_cb);

  size_t cmd_cb_count = 0;
  auto cb = [&](auto, auto&) { cmd_cb_count++; };

  auto packet = CommandPacket::New(hci_spec::kReset);
  CommandChannel::TransactionId id1 = cmd_channel()->SendCommand(std::move(packet), cb);
  ASSERT_NE(0u, id1);

  packet = CommandPacket::New(hci_spec::kReset);
  CommandChannel::TransactionId id2 = cmd_channel()->SendCommand(std::move(packet), cb);
  ASSERT_NE(0u, id2);

  RunLoopFor(kCommandTimeout);
  EXPECT_EQ(1u, timeout_cb_count);
}

// Tests:
//  - Asynchronous commands should be able to schedule another asynchronous
//    command in their callback.
TEST_F(CommandChannelTest, AsynchronousCommandChaining) {
  constexpr size_t kExpectedCallbacksPerCommand = 2;
  constexpr hci_spec::EventCode kTestEventCode0 = 0xFE;
  // Set up expectations
  // clang-format off
  // Using HCI_Reset for testing.
  auto req_reset = StaticByteBuffer(
      LowerBits(hci_spec::kReset), UpperBits(hci_spec::kReset), // HCI_Reset opcode
      0x00                                  // parameter_total_size (no payload)
      );
  auto rsp_resetstatus = StaticByteBuffer(
       hci_spec::kCommandStatusEventCode,
      0x04,                        // parameter_total_size (4 byte payload)
      hci_spec::StatusCode::kSuccess, 0xFA,  // status, num_hci_command_packets (250)
      LowerBits(hci_spec::kReset), UpperBits(hci_spec::kReset)  // HCI_Reset opcode
  );
  auto req_inqcancel = StaticByteBuffer(
      LowerBits(hci_spec::kInquiryCancel), UpperBits(hci_spec::kInquiryCancel), // HCI_InquiryCancel
      0x00                        // parameter_total_size (no payload)
  );
  auto rsp_inqstatus = StaticByteBuffer(
       hci_spec::kCommandStatusEventCode,
      0x04,                        // parameter_total_size (4 byte payload)
      hci_spec::StatusCode::kSuccess, 0xFA,  // status, num_hci_command_packets (250)
      LowerBits(hci_spec::kInquiryCancel), UpperBits(hci_spec::kInquiryCancel) // HCI_InquiryCanacel
  );
  auto rsp_bogocomplete = StaticByteBuffer(
      kTestEventCode0,
      0x00 // parameter_total_size (no payload)
      );
  // clang-format on

  EXPECT_CMD_PACKET_OUT(test_device(), req_reset, &rsp_resetstatus);
  EXPECT_CMD_PACKET_OUT(test_device(), req_reset, &rsp_resetstatus);
  StartTestDevice();

  CommandChannel::TransactionId id1, id2;
  CommandChannel::CommandCallback cb;
  size_t cb_count = 0u;

  cb = [&cb, cmd_channel = cmd_channel(), &id1, &id2, &cb_count, kTestEventCode0](
           CommandChannel::TransactionId callback_id, const EventPacket& event) {
    if (cb_count < kExpectedCallbacksPerCommand) {
      EXPECT_EQ(id1, callback_id);
    } else {
      EXPECT_EQ(id2, callback_id);
    }
    if ((cb_count % 2) == 0) {
      // First event from each command - CommandStatus
      EXPECT_EQ(hci_spec::kCommandStatusEventCode, event.event_code());
      auto params = event.params<hci_spec::CommandStatusEventParams>();
      EXPECT_EQ(hci_spec::StatusCode::kSuccess, params.status);
    } else {
      // Second event from each command - completion event
      EXPECT_EQ(kTestEventCode0, event.event_code());
      if (cb_count < 2) {
        // Add the second command when the first one completes.
        auto packet = CommandPacket::New(hci_spec::kReset);
        id2 = cmd_channel->SendCommand(std::move(packet), cb.share(), kTestEventCode0);
      }
    }
    cb_count++;
  };

  auto packet = CommandPacket::New(hci_spec::kReset);
  id1 = cmd_channel()->SendCommand(std::move(packet), cb.share(), kTestEventCode0);

  RunLoopUntilIdle();

  // Should have received the Status but not the result.
  EXPECT_EQ(1u, cb_count);

  // Sending the complete will finish the command and add the next command.
  test_device()->SendCommandChannelPacket(rsp_bogocomplete);
  RunLoopUntilIdle();

  EXPECT_EQ(3u, cb_count);

  // Finish out the command.
  test_device()->SendCommandChannelPacket(rsp_bogocomplete);
  RunLoopUntilIdle();

  EXPECT_EQ(4u, cb_count);
}

// Tests:
//  - Commands that are exclusive of other commands cannot run together, and
//    instead wait until the exclusive commands finish.
//  - Exclusive Commands in the queue still get started in order
//  - Commands that aren't exclusive run as normal even when an exclusive one is
//    waiting.
TEST_F(CommandChannelTest, ExclusiveCommands) {
  constexpr hci_spec::EventCode kExclOneCompleteEvent = 0xFE;
  constexpr hci_spec::EventCode kExclTwoCompleteEvent = 0xFD;
  constexpr hci_spec::OpCode kExclusiveOne = hci_spec::DefineOpCode(0x01, 0x01);
  constexpr hci_spec::OpCode kExclusiveTwo = hci_spec::DefineOpCode(0x01, 0x02);
  constexpr hci_spec::OpCode kNonExclusive = hci_spec::DefineOpCode(0x01, 0x03);

  // Set up expectations
  //  - kExclusiveOne can't run at the same time as kExclusiveTwo, and
  //  vice-versa.
  //  - kExclusiveOne finishes with kExclOneCompleteEvent
  //  - kExclusiveTwo finishes with kExclTwoCompleteEvent
  //  - kNonExclusive can run whenever it wants.
  //  - For testing, we omit the payloads of all commands.
  auto excl_one_cmd =
      StaticByteBuffer(LowerBits(kExclusiveOne), UpperBits(kExclusiveOne), 0x00  // (no payload)
      );
  auto rsp_excl_one_status = StaticByteBuffer(hci_spec::kCommandStatusEventCode,
                                              0x04,  // parameter_total_size (4 byte payload)
                                              hci_spec::StatusCode::kSuccess,
                                              0xFA,  // status, num_hci_command_packets (250)
                                              LowerBits(kExclusiveOne),
                                              UpperBits(kExclusiveOne)  // HCI opcode
  );
  auto rsp_one_complete =
      StaticByteBuffer(kExclOneCompleteEvent, 0x00  // parameter_total_size (no payload)
      );

  auto excl_two_cmd =
      StaticByteBuffer(LowerBits(kExclusiveTwo), UpperBits(kExclusiveTwo), 0x00  // (no payload)
      );
  auto rsp_excl_two_status = StaticByteBuffer(hci_spec::kCommandStatusEventCode,
                                              0x04,  // parameter_total_size (4 byte payload)
                                              hci_spec::StatusCode::kSuccess,
                                              0xFA,  // status, num_hci_command_packets (250)
                                              LowerBits(kExclusiveTwo),
                                              UpperBits(kExclusiveTwo)  // HCI opcode
  );
  auto rsp_two_complete =
      StaticByteBuffer(kExclTwoCompleteEvent, 0x00  // parameter_total_size (no payload)
      );

  auto nonexclusive_cmd =
      StaticByteBuffer(LowerBits(kNonExclusive), UpperBits(kNonExclusive),  // HCI opcode
                       0x00  // parameter_total_size (no payload)
      );
  auto nonexclusive_complete =
      StaticByteBuffer(hci_spec::kCommandCompleteEventCode,
                       0x04,  // parameter_total_size (4 byte payload)
                       0xFA,  // num_hci_command_packets (250)
                       LowerBits(kNonExclusive), UpperBits(kNonExclusive),  // HCI opcode
                       hci_spec::StatusCode::kSuccess                       // Command succeeded
      );

  StartTestDevice();

  CommandChannel::TransactionId id1, id2, id3;
  CommandChannel::CommandCallback exclusive_cb;
  size_t exclusive_cb_count = 0u;

  size_t nonexclusive_cb_count = 0;
  CommandChannel::CommandCallback nonexclusive_cb =
      [&nonexclusive_cb_count](auto callback_id, const EventPacket& event) {
        EXPECT_EQ(hci_spec::kCommandCompleteEventCode, event.event_code());
        nonexclusive_cb_count++;
      };

  exclusive_cb = [&exclusive_cb, &nonexclusive_cb, cmd_channel = cmd_channel(), &id1, &id2, &id3,
                  &exclusive_cb_count, kExclOneCompleteEvent, kExclTwoCompleteEvent](
                     CommandChannel::TransactionId callback_id, const EventPacket& event) {
    // Expected event -> Action in response
    // 0. Status for kExclusiveOne -> Send a kExclusiveTwo
    // 1. Complete for kExclusiveOne -> Send Another kExclusiveOne and kNonExclusive
    // 2. Status for kExclusiveTwo -> Nothing
    // 3. Complete for kExclusiveTwo -> Nothing
    // 4. Status for kExclusiveOne -> Nothing
    // 5. Complete for kExclusiveOne -> Nothing
    switch (exclusive_cb_count) {
      case 0: {
        // Status for kExclusiveOne -> Send kExclusiveTwo (queued)
        EXPECT_EQ(id1, callback_id);
        EXPECT_EQ(hci_spec::kCommandStatusEventCode, event.event_code());
        auto params = event.params<hci_spec::CommandStatusEventParams>();
        EXPECT_EQ(hci_spec::StatusCode::kSuccess, params.status);
        auto packet = CommandPacket::New(kExclusiveTwo);
        id2 = cmd_channel->SendExclusiveCommand(std::move(packet), exclusive_cb.share(),
                                                kExclTwoCompleteEvent, {kExclusiveOne});
        std::cout << "queued Exclusive Two: " << id2 << std::endl;
        break;
      }
      case 1: {
        // Complete for kExclusiveOne -> Resend kExclusiveOne
        EXPECT_EQ(id1, callback_id);
        EXPECT_EQ(kExclOneCompleteEvent, event.event_code());
        // Add the second command when the first one completes.
        auto packet = CommandPacket::New(kExclusiveOne);
        id3 = cmd_channel->SendExclusiveCommand(std::move(packet), exclusive_cb.share(),
                                                kExclOneCompleteEvent, {kExclusiveTwo});
        std::cout << "queued Second Exclusive One: " << id3 << std::endl;
        packet = CommandPacket::New(kNonExclusive);
        cmd_channel->SendCommand(std::move(packet), nonexclusive_cb.share());

        break;
      }
      case 2: {  // Status for kExclusiveTwo
        EXPECT_EQ(id2, callback_id);
        EXPECT_EQ(hci_spec::kCommandStatusEventCode, event.event_code());
        auto params = event.params<hci_spec::CommandStatusEventParams>();
        EXPECT_EQ(hci_spec::StatusCode::kSuccess, params.status);
        break;
      }
      case 3: {  // Complete for kExclusiveTwo
        EXPECT_EQ(id2, callback_id);
        EXPECT_EQ(kExclTwoCompleteEvent, event.event_code());
        break;
      }
      case 4: {  // Status for Second kExclusiveOne
        EXPECT_EQ(id3, callback_id);
        EXPECT_EQ(hci_spec::kCommandStatusEventCode, event.event_code());
        auto params = event.params<hci_spec::CommandStatusEventParams>();
        EXPECT_EQ(hci_spec::StatusCode::kSuccess, params.status);
        break;
      }
      case 5: {  // Complete for Second kExclusiveOne
        EXPECT_EQ(id3, callback_id);
        EXPECT_EQ(kExclOneCompleteEvent, event.event_code());
        break;
      }
      default: {
        ASSERT_TRUE(false);  // Should never be called more than 6 times.
        break;
      }
    }
    exclusive_cb_count++;
  };

  EXPECT_CMD_PACKET_OUT(test_device(), excl_one_cmd, &rsp_excl_one_status);
  EXPECT_CMD_PACKET_OUT(test_device(), nonexclusive_cmd, &nonexclusive_complete);
  id1 = cmd_channel()->SendExclusiveCommand(CommandPacket::New(kExclusiveOne), exclusive_cb.share(),
                                            kExclOneCompleteEvent, {kExclusiveTwo});
  cmd_channel()->SendCommand(CommandPacket::New(kNonExclusive), nonexclusive_cb.share());
  RunLoopUntilIdle();
  // Should have received the ExclusiveOne status but not the complete. ExclusiveTwo should be
  // queued.
  EXPECT_EQ(1u, exclusive_cb_count);
  // NonExclusive should be completed.
  EXPECT_EQ(1u, nonexclusive_cb_count);

  // Sending the ExclusiveOne complete will send the ExclusiveTwo command, queue another
  // ExclusiveOne command, and send a NonExclusive command.
  EXPECT_CMD_PACKET_OUT(test_device(), excl_two_cmd, &rsp_excl_two_status);
  EXPECT_CMD_PACKET_OUT(test_device(), nonexclusive_cmd, &nonexclusive_complete);
  test_device()->SendCommandChannelPacket(rsp_one_complete);
  RunLoopUntilIdle();
  EXPECT_EQ(3u, exclusive_cb_count);     // +2: rsp_one_complete, rsp_excl_two_status
  EXPECT_EQ(2u, nonexclusive_cb_count);  // +1: nonexclusive_complete

  // Complete ExclusiveTwo and send a NonExclusive. The queued ExclusiveOne should be sent.
  EXPECT_CMD_PACKET_OUT(test_device(), nonexclusive_cmd, &nonexclusive_complete);
  EXPECT_CMD_PACKET_OUT(test_device(), excl_one_cmd, &rsp_excl_one_status);
  test_device()->SendCommandChannelPacket(rsp_two_complete);
  cmd_channel()->SendCommand(CommandPacket::New(kNonExclusive), nonexclusive_cb.share());
  RunLoopUntilIdle();
  EXPECT_EQ(5u, exclusive_cb_count);     // +2: rsp_two_complete, rsp_excl_one_status
  EXPECT_EQ(3u, nonexclusive_cb_count);  // +1: nonexclusive_complete

  // Finish the second ExclusiveOne
  test_device()->SendCommandChannelPacket(rsp_one_complete);
  RunLoopUntilIdle();
  EXPECT_EQ(6u, exclusive_cb_count);  // +1: rsp_one_complete
  EXPECT_EQ(3u, nonexclusive_cb_count);
}

TEST_F(CommandChannelTest, SendCommandFailsIfEventHandlerInstalled) {
  constexpr hci_spec::EventCode kTestEventCode0 = 0xFE;

  // Register event handler for kTestEventCode0.
  auto id0 = cmd_channel()->AddEventHandler(
      kTestEventCode0, [](const EventPacket& event) { return EventCallbackResult::kContinue; });
  EXPECT_NE(0u, id0);

  // Try to send a command for kTestEventCode0. SendCommand should fail for a code already
  // registered with "AddEventHandler".
  auto transaction_id = cmd_channel()->SendCommand(
      CommandPacket::New(hci_spec::kReset), [](auto, const auto&) {}, kTestEventCode0);
  EXPECT_EQ(0u, transaction_id);
}

TEST_F(CommandChannelTest, EventHandlerResults) {
  constexpr hci_spec::EventCode kTestEventCode0 = 0xFE;

  int event_count = 0;
  auto event_cb = [&event_count, kTestEventCode0](const EventPacket& event) {
    event_count++;
    EXPECT_EQ(kTestEventCode0, event.event_code());

    if (event_count == 1) {
      return EventCallbackResult::kContinue;
    }

    return EventCallbackResult::kRemove;
  };

  EXPECT_NE(cmd_channel()->AddEventHandler(kTestEventCode0, event_cb), 0u);

  StartTestDevice();

  // Send three requests, and process the callbacks immediately. The second callback returns
  // "remove" before the third event callback has been called.
  auto event0 = StaticByteBuffer(kTestEventCode0, 0x00);
  test_device()->SendCommandChannelPacket(event0);
  test_device()->SendCommandChannelPacket(event0);
  test_device()->SendCommandChannelPacket(event0);
  RunLoopUntilIdle();
  EXPECT_EQ(2, event_count);
}

TEST_F(CommandChannelTest, SendCommandWithLEMetaEventSubeventRsp) {
  constexpr hci_spec::OpCode kOpCode = hci_spec::kLEReadRemoteFeatures;
  constexpr hci_spec::EventCode kSubeventCode = hci_spec::kLEReadRemoteFeaturesCompleteSubeventCode;

  auto cmd = StaticByteBuffer(LowerBits(kOpCode), UpperBits(kOpCode),
                              // parameter total size (0 byte payload)
                              0x00);

  auto cmd_status_event = StaticByteBuffer(hci_spec::kCommandStatusEventCode,
                                           // parameter total size (4 byte payload)
                                           0x04,
                                           // status, num_hci_command_packets (250)
                                           hci_spec::StatusCode::kSuccess, 0xFA,
                                           // HCI opcode
                                           LowerBits(kOpCode), UpperBits(kOpCode));
  auto cmd_complete_subevent = StaticByteBuffer(hci_spec::kLEMetaEventCode,
                                                0x01,  // parameter total size (1 byte payload)
                                                kSubeventCode);

  EXPECT_CMD_PACKET_OUT(test_device(), cmd, &cmd_status_event);
  StartTestDevice();

  auto cmd_packet = CommandPacket::New(kOpCode);

  size_t event_count = 0;
  auto event_cb = [&event_count](auto, const EventPacket& event) {
    switch (event_count) {
      case 0: {
        EXPECT_EQ(hci_spec::kCommandStatusEventCode, event.event_code());
        break;
      }
      case 1: {
        EXPECT_EQ(hci_spec::kLEMetaEventCode, event.event_code());
        break;
      }
      default: {
        FAIL();
      }
    }
    event_count++;
  };
  auto id =
      cmd_channel()->SendLeAsyncCommand(std::move(cmd_packet), std::move(event_cb), kSubeventCode);
  EXPECT_NE(0u, id);

  RunLoopUntilIdle();
  EXPECT_EQ(1u, event_count);

  // Handler should be removed when subevent received.
  test_device()->SendCommandChannelPacket(cmd_complete_subevent);
  RunLoopUntilIdle();
  EXPECT_EQ(2u, event_count);

  // This seconod complete event should be ignored because the handler should have been removed.
  test_device()->SendCommandChannelPacket(cmd_complete_subevent);
  RunLoopUntilIdle();
  EXPECT_EQ(2u, event_count);
}

TEST_F(
    CommandChannelTest,
    SendingLECommandAfterAddingLEMetaEventHandlerFailsForSameSubeventCodeAndSucceedsForDifferentSubeventCode) {
  constexpr hci_spec::EventCode kSubeventCode = hci_spec::kLEReadRemoteFeaturesCompleteSubeventCode;
  constexpr hci_spec::OpCode kOpCode = hci_spec::kLEReadRemoteFeatures;  // LE Read Remote Features

  StartTestDevice();

  EXPECT_NE(0u, cmd_channel()->AddLEMetaEventHandler(
                    kSubeventCode, [](const auto&) { return EventCallbackResult::kContinue; }));
  EXPECT_EQ(0u, cmd_channel()->SendLeAsyncCommand(
                    CommandPacket::New(kOpCode), [](auto, const auto&) {}, kSubeventCode));

  auto cmd = StaticByteBuffer(LowerBits(kOpCode), UpperBits(kOpCode),
                              // parameter total size (0 byte payload)
                              0x00);
  EXPECT_CMD_PACKET_OUT(test_device(), std::move(cmd), );
  EXPECT_NE(0u, cmd_channel()->SendLeAsyncCommand(
                    CommandPacket::New(kOpCode), [](auto, const auto&) {}, kSubeventCode + 1));
  RunLoopUntilIdle();
}

TEST_F(CommandChannelTest, SendingSecondLECommandWithSameSubeventShouldWaitForFirstToComplete) {
  // Commands have different op codes but same subevent code so that second command is not blocked
  // because of matching op codes (which would not test LE command handling).
  constexpr hci_spec::OpCode kOpCode0 = hci_spec::kLEReadRemoteFeatures;
  constexpr hci_spec::OpCode kOpCode1 = hci_spec::kLEReadBufferSize;
  constexpr hci_spec::EventCode kSubeventCode = hci_spec::kLEReadRemoteFeaturesCompleteSubeventCode;

  auto cmd0 = StaticByteBuffer(LowerBits(kOpCode0), UpperBits(kOpCode0),
                               // parameter total size (0 byte payload)
                               0x00);
  auto cmd0_status_event = StaticByteBuffer(hci_spec::kCommandStatusEventCode,
                                            // parameter total size (4 byte payload)
                                            0x04,
                                            // status, num_hci_command_packets (250)
                                            hci_spec::StatusCode::kSuccess, 0xFA,
                                            // HCI opcode
                                            LowerBits(kOpCode0), UpperBits(kOpCode0));
  auto cmd1 = StaticByteBuffer(LowerBits(kOpCode1), UpperBits(kOpCode1),
                               // parameter total size (0 byte payload)
                               0x00);
  auto cmd1_status_event = StaticByteBuffer(hci_spec::kCommandStatusEventCode,
                                            // parameter total size (4 byte payload)
                                            0x04,
                                            // status, num_hci_command_packets (250)
                                            hci_spec::StatusCode::kSuccess, 0xFA,
                                            // HCI opcode
                                            LowerBits(kOpCode1), UpperBits(kOpCode1));

  auto cmd_complete_subevent = StaticByteBuffer(hci_spec::kLEMetaEventCode,
                                                0x01,  // parameter total size (1 byte payload)
                                                kSubeventCode);

  EXPECT_CMD_PACKET_OUT(test_device(), cmd0, &cmd0_status_event);
  StartTestDevice();

  size_t event_count_0 = 0;
  auto event_cb_0 = [&event_count_0](auto, const EventPacket& event) {
    switch (event_count_0) {
      case 0: {
        EXPECT_EQ(hci_spec::kCommandStatusEventCode, event.event_code());
        break;
      }
      case 1: {
        EXPECT_EQ(hci_spec::kLEMetaEventCode, event.event_code());
        break;
      }
      default: {
        FAIL();
      }
    }
    event_count_0++;
  };
  auto id_0 = cmd_channel()->SendLeAsyncCommand(CommandPacket::New(kOpCode0), std::move(event_cb_0),
                                                kSubeventCode);
  EXPECT_NE(0u, id_0);

  RunLoopUntilIdle();
  EXPECT_EQ(1u, event_count_0);

  size_t event_count_1 = 0;
  auto event_cb_1 = [&event_count_1](auto, const EventPacket& event) {
    switch (event_count_1) {
      case 0: {
        EXPECT_EQ(hci_spec::kCommandStatusEventCode, event.event_code());
        break;
      }
      case 1: {
        EXPECT_EQ(hci_spec::kLEMetaEventCode, event.event_code());
        break;
      }
      default: {
        FAIL();
      }
    }
    event_count_1++;
  };
  // Command should be queued and not sent until after first complete event received.
  auto id_1 = cmd_channel()->SendLeAsyncCommand(CommandPacket::New(kOpCode1), std::move(event_cb_1),
                                                kSubeventCode);
  EXPECT_NE(0u, id_1);
  RunLoopUntilIdle();
  EXPECT_EQ(0u, event_count_1);

  // When first command complete event is received, second command should be sent.
  EXPECT_CMD_PACKET_OUT(test_device(), cmd1, &cmd1_status_event);
  test_device()->SendCommandChannelPacket(cmd_complete_subevent);
  RunLoopUntilIdle();
  EXPECT_EQ(2u, event_count_0);
  EXPECT_EQ(1u, event_count_1);

  // Second complete event should be received by second command event handler only.
  test_device()->SendCommandChannelPacket(cmd_complete_subevent);
  RunLoopUntilIdle();
  EXPECT_EQ(2u, event_count_0);
  EXPECT_EQ(2u, event_count_1);
}

TEST_F(
    CommandChannelTest,
    RegisteringLEMetaEventHandlerWhileLECommandPendingFailsForSameSubeventAndSucceedsForDifferentSubevent) {
  constexpr hci_spec::OpCode kOpCode = hci_spec::kLEReadRemoteFeatures;
  constexpr hci_spec::EventCode kSubeventCode = hci_spec::kLEReadRemoteFeaturesCompleteSubeventCode;

  auto cmd = StaticByteBuffer(LowerBits(kOpCode), UpperBits(kOpCode),
                              // parameter total size (0 byte payload)
                              0x00);

  auto cmd_status_event = StaticByteBuffer(hci_spec::kCommandStatusEventCode,
                                           // parameter total size (4 byte payload)
                                           0x04,
                                           // status, num_hci_command_packets (250)
                                           hci_spec::StatusCode::kSuccess, 0xFA,
                                           // HCI opcode
                                           LowerBits(kOpCode), UpperBits(kOpCode));

  EXPECT_CMD_PACKET_OUT(test_device(), cmd, &cmd_status_event);
  StartTestDevice();

  size_t event_count = 0;
  auto event_cb = [&event_count](auto, const EventPacket& event) {
    EXPECT_EQ(hci_spec::kCommandStatusEventCode, event.event_code());
    event_count++;
  };
  auto id = cmd_channel()->SendLeAsyncCommand(CommandPacket::New(kOpCode), std::move(event_cb),
                                              kSubeventCode);
  EXPECT_NE(0u, id);
  RunLoopUntilIdle();
  EXPECT_EQ(1u, event_count);

  // Async LE command for subevent is already pending, so registering event handler should fail by
  // returning 0.
  id = cmd_channel()->AddLEMetaEventHandler(kSubeventCode,
                                            [](auto&) { return EventCallbackResult::kContinue; });
  EXPECT_EQ(0u, id);

  // Registering event handler for different subevent code should succeed.
  id = cmd_channel()->AddLEMetaEventHandler(kSubeventCode + 1,
                                            [](auto&) { return EventCallbackResult::kContinue; });
  EXPECT_NE(0u, id);
}

TEST_F(CommandChannelTest, InspectHierarchy) {
  cmd_channel()->AttachInspect(inspector_.GetRoot(), "command_channel");

  auto command_channel_matcher = AllOf(
      NodeMatches(AllOf(NameMatches("command_channel"),
                        PropertyList(UnorderedElementsAre(UintIs("allowed_command_packets", 1),
                                                          UintIs("next_event_handler_id", 1),
                                                          UintIs("next_transaction_id", 1))))));

  EXPECT_THAT(inspect::ReadFromVmo(inspector_.DuplicateVmo()).value(),
              ChildrenMatch(ElementsAre(command_channel_matcher)));
}

}  // namespace
}  // namespace bt::hci
