// 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/acl_data_channel.h"

#include <lib/async/cpp/task.h>
#include <lib/fpromise/single_threaded_executor.h>
#include <lib/inspect/testing/cpp/inspect.h>
#include <zircon/assert.h>

#include <unordered_map>

#include <gmock/gmock.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/defaults.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/connection.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/l2cap_defs.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/testing/test_packets.h"
#include "src/connectivity/bluetooth/core/bt-host/transport/link_type.h"
#include "src/connectivity/bluetooth/core/bt-host/transport/transport.h"

namespace bt::hci {
namespace {

constexpr hci_spec::ConnectionHandle kLinkHandle = 0x0001;

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

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

 protected:
  // TestBase overrides:
  void SetUp() override {
    TestingBase::SetUp();
    StartTestDevice();
  }

 private:
  DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(ACLDataChannelTest);
};

using HCI_ACLDataChannelTest = ACLDataChannelTest;

TEST_F(ACLDataChannelTest, VerifyMTUs) {
  const DataBufferInfo kBREDRBufferInfo(1024, 50);
  const DataBufferInfo kLEBufferInfo(64, 16);

  // BR/EDR buffer only.
  InitializeACLDataChannel(kBREDRBufferInfo, DataBufferInfo());
  EXPECT_EQ(kBREDRBufferInfo, acl_data_channel()->GetBufferInfo());
  EXPECT_EQ(kBREDRBufferInfo, acl_data_channel()->GetLeBufferInfo());

  TearDown();
  SetUp();

  // LE buffer only.
  InitializeACLDataChannel(DataBufferInfo(), kLEBufferInfo);
  EXPECT_EQ(DataBufferInfo(), acl_data_channel()->GetBufferInfo());
  EXPECT_EQ(kLEBufferInfo, acl_data_channel()->GetLeBufferInfo());

  TearDown();
  SetUp();

  // Both buffers available.
  InitializeACLDataChannel(kBREDRBufferInfo, kLEBufferInfo);
  EXPECT_EQ(kBREDRBufferInfo, acl_data_channel()->GetBufferInfo());
  EXPECT_EQ(kLEBufferInfo, acl_data_channel()->GetLeBufferInfo());
}

// Test that SendPacket works using only the BR/EDR buffer.
TEST_F(ACLDataChannelTest, SendPacketBREDRBuffer) {
  constexpr size_t kMaxMTU = 5;
  constexpr size_t kMaxNumPackets = 5;
  constexpr hci_spec::ConnectionHandle kHandle0 = 0x0001;
  constexpr hci_spec::ConnectionHandle kHandle1 = 0x0002;

  InitializeACLDataChannel(DataBufferInfo(kMaxMTU, kMaxNumPackets), DataBufferInfo());

  acl_data_channel()->RegisterLink(kHandle0, bt::LinkType::kLE);
  acl_data_channel()->RegisterLink(kHandle1, bt::LinkType::kACL);

  int handle0_packet_count = 0;
  int handle1_packet_count = 0;

  // Callback invoked by TestDevice when it receive a data packet from us.
  auto data_callback = [&](const ByteBuffer& bytes) {
    ZX_DEBUG_ASSERT(bytes.size() >= sizeof(hci_spec::ACLDataHeader));

    PacketView<hci_spec::ACLDataHeader> packet(&bytes,
                                               bytes.size() - sizeof(hci_spec::ACLDataHeader));
    hci_spec::ConnectionHandle connection_handle =
        le16toh(packet.header().handle_and_flags) & 0xFFF;

    if (connection_handle == kHandle0) {
      handle0_packet_count++;
    } else {
      ASSERT_EQ(kHandle1, connection_handle);
      handle1_packet_count++;
    }
  };
  test_device()->SetDataCallback(data_callback, dispatcher());

  // Queue up 10 packets in total, distributed among the two connection handles.
  async::PostTask(dispatcher(), [this] {
    for (int i = 0; i < 10; ++i) {
      hci_spec::ConnectionHandle handle = (i % 2) ? kHandle1 : kHandle0;
      auto packet = ACLDataPacket::New(handle, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                                       hci_spec::ACLBroadcastFlag::kPointToPoint, kMaxMTU);
      EXPECT_TRUE(acl_data_channel()->SendPacket(std::move(packet), l2cap::kInvalidChannelId,
                                                 AclDataChannel::PacketPriority::kLow));
    }
  });

  RunLoopUntilIdle();

  // kMaxNumPackets is 5. The controller should have received 3 packets on
  // kHandle0 and 2 on kHandle1
  EXPECT_EQ(3, handle0_packet_count);
  EXPECT_EQ(2, handle1_packet_count);

  // Notify the processed packets with a Number Of Completed Packet HCI event.
  StaticByteBuffer event_buffer(0x13, 0x09,              // Event header
                                0x02,                    // Number of handles
                                0x01, 0x00, 0x03, 0x00,  // 3 packets on handle 0x0001
                                0x02, 0x00, 0x02, 0x00   // 2 packets on handle 0x0002
  );
  test_device()->SendCommandChannelPacket(event_buffer);

  RunLoopUntilIdle();

  EXPECT_EQ(5, handle0_packet_count);
  EXPECT_EQ(5, handle1_packet_count);
}

inspect::Hierarchy ReadInspect(inspect::Inspector& inspector) {
  fpromise::single_threaded_executor executor;
  fpromise::result<inspect::Hierarchy> hierarchy;
  executor.schedule_task(inspect::ReadFromInspector(inspector).then(
      [&](fpromise::result<inspect::Hierarchy>& res) { hierarchy = std::move(res); }));
  executor.run();
  ZX_ASSERT(hierarchy.is_ok());
  return hierarchy.take_value();
}

// Test that SendPacket works using the LE buffer when no BR/EDR buffer is
// available.
TEST_F(ACLDataChannelTest, SendPacketLEBuffer) {
  constexpr size_t kMaxMTU = 5;
  constexpr size_t kTotalAttempts = 12;
  constexpr size_t kTotalExpected = 6;
  constexpr size_t kBufferNumPackets = 3;
  constexpr hci_spec::ConnectionHandle kHandle0 = 0x0001;
  constexpr hci_spec::ConnectionHandle kHandle1 = 0x0002;

  InitializeACLDataChannel(DataBufferInfo(), DataBufferInfo(kMaxMTU, kBufferNumPackets));

  acl_data_channel()->RegisterLink(kHandle0, bt::LinkType::kLE);
  acl_data_channel()->RegisterLink(kHandle1, bt::LinkType::kACL);

  // This should fail because the payload exceeds the MTU.
  auto packet = ACLDataPacket::New(kHandle1, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                                   hci_spec::ACLBroadcastFlag::kPointToPoint, kMaxMTU + 1);
  EXPECT_FALSE(acl_data_channel()->SendPacket(std::move(packet), l2cap::kInvalidChannelId,
                                              AclDataChannel::PacketPriority::kLow));

  size_t handle0_packet_count = 0;
  size_t handle1_packet_count = 0;
  auto data_callback = [&](const ByteBuffer& bytes) {
    ZX_DEBUG_ASSERT(bytes.size() >= sizeof(hci_spec::ACLDataHeader));

    PacketView<hci_spec::ACLDataHeader> packet(&bytes,
                                               bytes.size() - sizeof(hci_spec::ACLDataHeader));
    hci_spec::ConnectionHandle connection_handle =
        le16toh(packet.header().handle_and_flags) & 0xFFF;

    if (connection_handle == kHandle0) {
      handle0_packet_count++;
    } else {
      ASSERT_EQ(kHandle1, connection_handle);
      handle1_packet_count++;
    }
  };
  test_device()->SetDataCallback(data_callback, dispatcher());

  // Queue up 12 packets in total, distributed among the two connection handles
  // and link types. Since the BR/EDR MTU is zero, we expect to only see LE
  // packets transmitted.
  async::PostTask(dispatcher(), [this] {
    for (size_t i = 0; i < kTotalAttempts; ++i) {
      hci_spec::ConnectionHandle handle = (i % 2) ? kHandle1 : kHandle0;
      auto packet = ACLDataPacket::New(handle, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                                       hci_spec::ACLBroadcastFlag::kPointToPoint, kMaxMTU);
      if (i % 2) {
        // ACL-U packets should fail due to 0 MTU size.
        EXPECT_FALSE(acl_data_channel()->SendPacket(std::move(packet), l2cap::kInvalidChannelId,
                                                    AclDataChannel::PacketPriority::kLow));
      } else {
        EXPECT_TRUE(acl_data_channel()->SendPacket(std::move(packet), l2cap::kInvalidChannelId,
                                                   AclDataChannel::PacketPriority::kLow));
      }
    }
  });

  RunLoopUntilIdle();

  // The controller can buffer 3 packets. Since BR/EDR packets should have
  // failed to go out, the controller should have received 3 packets on handle 0
  // and none on handle 1.
  EXPECT_EQ(kTotalExpected / 2u, handle0_packet_count);
  EXPECT_EQ(0u, handle1_packet_count);

  // Notify the processed packets with a Number Of Completed Packet HCI event.
  StaticByteBuffer event_buffer(0x13, 0x05,  // Event header
                                0x01,        // Number of handles
                                0x01, 0x00, 0x03,
                                0x00  // 3 packets on handle 0x0001
  );
  test_device()->SendCommandChannelPacket(event_buffer);

  RunLoopUntilIdle();

  EXPECT_EQ(kTotalExpected, handle0_packet_count);
  EXPECT_EQ(0u, handle1_packet_count);
}

// Test that SendPacket works for LE packets when both buffer types are
// available.
TEST_F(ACLDataChannelTest, SendLEPacketBothBuffers) {
  constexpr size_t kMaxMTU = 200;
  constexpr size_t kMaxNumPackets = 50;
  constexpr size_t kLEMaxMTU = 5;
  constexpr size_t kLEMaxNumPackets = 5;
  constexpr hci_spec::ConnectionHandle kHandle0 = 0x0001;
  constexpr hci_spec::ConnectionHandle kHandle1 = 0x0002;

  InitializeACLDataChannel(DataBufferInfo(kMaxMTU, kMaxNumPackets),
                           DataBufferInfo(kLEMaxMTU, kLEMaxNumPackets));

  acl_data_channel()->RegisterLink(kHandle0, bt::LinkType::kLE);
  acl_data_channel()->RegisterLink(kHandle1, bt::LinkType::kLE);

  // This should fail because the payload exceeds the LE MTU.
  auto packet = ACLDataPacket::New(kHandle1, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                                   hci_spec::ACLBroadcastFlag::kPointToPoint, kMaxMTU);
  EXPECT_FALSE(acl_data_channel()->SendPacket(std::move(packet), l2cap::kInvalidChannelId,
                                              AclDataChannel::PacketPriority::kLow));

  int handle0_packet_count = 0;
  int handle1_packet_count = 0;
  auto data_callback = [&](const ByteBuffer& bytes) {
    ZX_DEBUG_ASSERT(bytes.size() >= sizeof(hci_spec::ACLDataHeader));

    PacketView<hci_spec::ACLDataHeader> packet(&bytes,
                                               bytes.size() - sizeof(hci_spec::ACLDataHeader));
    hci_spec::ConnectionHandle connection_handle =
        le16toh(packet.header().handle_and_flags) & 0xFFF;

    if (connection_handle == kHandle0) {
      handle0_packet_count++;
    } else {
      ASSERT_EQ(kHandle1, connection_handle);
      handle1_packet_count++;
    }
  };
  test_device()->SetDataCallback(data_callback, dispatcher());

  // Queue up 10 packets in total, distributed among the two connection handles.
  async::PostTask(dispatcher(), [this] {
    for (int i = 0; i < 10; ++i) {
      hci_spec::ConnectionHandle handle = (i % 2) ? kHandle1 : kHandle0;
      auto packet = ACLDataPacket::New(handle, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                                       hci_spec::ACLBroadcastFlag::kPointToPoint, kLEMaxMTU);
      EXPECT_TRUE(acl_data_channel()->SendPacket(std::move(packet), l2cap::kInvalidChannelId,
                                                 AclDataChannel::PacketPriority::kLow));
    }
  });

  RunLoopUntilIdle();

  // ACLDataChannel should be looking at kLEMaxNumPackets, which is 5. The
  // controller should have received 3 packets on kHandle0 and 2 on kHandle1
  EXPECT_EQ(3, handle0_packet_count);
  EXPECT_EQ(2, handle1_packet_count);

  // Notify the processed packets with a Number Of Completed Packet HCI event.
  StaticByteBuffer event_buffer(0x13, 0x09,              // Event header
                                0x02,                    // Number of handles
                                0x01, 0x00, 0x03, 0x00,  // 3 packets on handle 0x0001
                                0x02, 0x00, 0x02, 0x00   // 2 packets on handle 0x0002
  );
  test_device()->SendCommandChannelPacket(event_buffer);

  RunLoopUntilIdle();

  EXPECT_EQ(5, handle0_packet_count);
  EXPECT_EQ(5, handle1_packet_count);
}

// Test that SendPacket works for BR/EDR packets when both buffer types are
// available.
TEST_F(ACLDataChannelTest, SendBREDRPacketBothBuffers) {
  constexpr size_t kLEMaxMTU = 200;
  constexpr size_t kLEMaxNumPackets = 50;
  constexpr size_t kMaxMTU = 5;
  constexpr size_t kMaxNumPackets = 5;
  constexpr hci_spec::ConnectionHandle kHandle0 = 0x0001;
  constexpr hci_spec::ConnectionHandle kHandle1 = 0x0002;

  InitializeACLDataChannel(DataBufferInfo(kMaxMTU, kMaxNumPackets),
                           DataBufferInfo(kLEMaxMTU, kLEMaxNumPackets));

  acl_data_channel()->RegisterLink(kHandle0, bt::LinkType::kACL);
  acl_data_channel()->RegisterLink(kHandle1, bt::LinkType::kACL);

  // This should fail because the payload exceeds the ACL MTU.
  auto packet = ACLDataPacket::New(kHandle1, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                                   hci_spec::ACLBroadcastFlag::kPointToPoint, kLEMaxMTU);
  EXPECT_FALSE(acl_data_channel()->SendPacket(std::move(packet), l2cap::kInvalidChannelId,
                                              AclDataChannel::PacketPriority::kLow));

  int handle0_packet_count = 0;
  int handle1_packet_count = 0;
  auto data_callback = [&](const ByteBuffer& bytes) {
    ZX_DEBUG_ASSERT(bytes.size() >= sizeof(hci_spec::ACLDataHeader));

    PacketView<hci_spec::ACLDataHeader> packet(&bytes,
                                               bytes.size() - sizeof(hci_spec::ACLDataHeader));
    hci_spec::ConnectionHandle connection_handle =
        le16toh(packet.header().handle_and_flags) & 0xFFF;

    if (connection_handle == kHandle0) {
      handle0_packet_count++;
    } else {
      ASSERT_EQ(kHandle1, connection_handle);
      handle1_packet_count++;
    }
  };
  test_device()->SetDataCallback(data_callback, dispatcher());

  // Queue up 10 packets in total, distributed among the two connection handles.
  async::PostTask(dispatcher(), [this] {
    for (int i = 0; i < 10; ++i) {
      hci_spec::ConnectionHandle handle = (i % 2) ? kHandle1 : kHandle0;
      auto packet = ACLDataPacket::New(handle, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                                       hci_spec::ACLBroadcastFlag::kPointToPoint, kMaxMTU);
      EXPECT_TRUE(acl_data_channel()->SendPacket(std::move(packet), l2cap::kInvalidChannelId,
                                                 AclDataChannel::PacketPriority::kLow));
    }
  });

  RunLoopUntilIdle();

  // ACLDataChannel should be looking at kLEMaxNumPackets, which is 5. The
  // controller should have received 3 packets on kHandle0 and 2 on kHandle1
  EXPECT_EQ(3, handle0_packet_count);
  EXPECT_EQ(2, handle1_packet_count);

  // Notify the processed packets with a Number Of Completed Packet HCI event.
  StaticByteBuffer event_buffer(0x13, 0x09,              // Event header
                                0x02,                    // Number of handles
                                0x01, 0x00, 0x03, 0x00,  // 3 packets on handle 0x0001
                                0x02, 0x00, 0x02, 0x00   // 2 packets on handle 0x0002
  );
  test_device()->SendCommandChannelPacket(event_buffer);

  RunLoopUntilIdle();

  EXPECT_EQ(5, handle0_packet_count);
  EXPECT_EQ(5, handle1_packet_count);
}

TEST_F(ACLDataChannelTest, SendPacketsFailure) {
  constexpr size_t kMaxMTU = 5;
  constexpr hci_spec::ConnectionHandle kHandle = 0x0001;
  InitializeACLDataChannel(DataBufferInfo(kMaxMTU, 100), DataBufferInfo());

  acl_data_channel()->RegisterLink(kHandle, bt::LinkType::kACL);

  // Empty packet list.
  EXPECT_FALSE(acl_data_channel()->SendPackets(
      LinkedList<ACLDataPacket>(), l2cap::kInvalidChannelId, AclDataChannel::PacketPriority::kLow));

  // Packet exceeds MTU
  LinkedList<ACLDataPacket> packets;
  packets.push_back(ACLDataPacket::New(kHandle, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                                       hci_spec::ACLBroadcastFlag::kPointToPoint, kMaxMTU + 1));
  EXPECT_FALSE(acl_data_channel()->SendPackets(std::move(packets), l2cap::kInvalidChannelId,
                                               AclDataChannel::PacketPriority::kLow));
}

// Suffix DeathTest has GoogleTest-specific behavior
using ACLDataChannelDeathTest = HCI_ACLDataChannelTest;

TEST_F(ACLDataChannelDeathTest, SendPacketsCrashesWithContinuingFragments) {
  constexpr size_t kMaxMTU = 5;
  constexpr hci_spec::ConnectionHandle kHandle = 0x0001;
  InitializeACLDataChannel(DataBufferInfo(kMaxMTU, 100), DataBufferInfo());

  acl_data_channel()->RegisterLink(kHandle, bt::LinkType::kACL);

  LinkedList<ACLDataPacket> packets;
  packets.push_back(ACLDataPacket::New(kHandle,
                                       hci_spec::ACLPacketBoundaryFlag::kContinuingFragment,
                                       hci_spec::ACLBroadcastFlag::kPointToPoint, kMaxMTU));
  ASSERT_DEATH_IF_SUPPORTED(
      acl_data_channel()->SendPackets(std::move(packets), l2cap::kInvalidChannelId,
                                      AclDataChannel::PacketPriority::kLow),
      "expected full PDU");
}

TEST_F(ACLDataChannelDeathTest, SendPacketsCrashesWithPacketsForMoreThanOneConnection) {
  constexpr size_t kMaxMTU = 5;
  constexpr hci_spec::ConnectionHandle kHandle0 = 0x0001;
  constexpr hci_spec::ConnectionHandle kHandle1 = 0x0002;
  InitializeACLDataChannel(DataBufferInfo(kMaxMTU, 100), DataBufferInfo());

  acl_data_channel()->RegisterLink(kHandle0, bt::LinkType::kACL);
  acl_data_channel()->RegisterLink(kHandle1, bt::LinkType::kACL);

  // Packet exceeds MTU
  LinkedList<ACLDataPacket> packets;
  packets.push_back(ACLDataPacket::New(kHandle0,
                                       hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                                       hci_spec::ACLBroadcastFlag::kPointToPoint, kMaxMTU));
  packets.push_back(ACLDataPacket::New(kHandle1,
                                       hci_spec::ACLPacketBoundaryFlag::kContinuingFragment,
                                       hci_spec::ACLBroadcastFlag::kPointToPoint, kMaxMTU));
  ASSERT_DEATH_IF_SUPPORTED(
      acl_data_channel()->SendPackets(std::move(packets), l2cap::kInvalidChannelId,
                                      AclDataChannel::PacketPriority::kLow),
      "expected only fragments for one connection");
}

// Tests sending multiple packets in a single call.
TEST_F(ACLDataChannelTest, SendPackets) {
  constexpr int kExpectedPacketCount = 5;
  constexpr hci_spec::ConnectionHandle kHandle = 0x0001;

  InitializeACLDataChannel(DataBufferInfo(1024, 100), DataBufferInfo());

  acl_data_channel()->RegisterLink(kHandle, bt::LinkType::kLE);

  bool pass = true;
  int seq_no = 0;
  auto data_cb = [&pass, &seq_no](const ByteBuffer& bytes) {
    ZX_DEBUG_ASSERT(bytes.size() >= sizeof(hci_spec::ACLDataHeader));
    PacketView<hci_spec::ACLDataHeader> packet(&bytes,
                                               bytes.size() - sizeof(hci_spec::ACLDataHeader));
    EXPECT_EQ(1u, packet.payload_size());

    int cur_no = packet.payload_data().data()[0];
    if (cur_no != seq_no + 1) {
      pass = false;
      return;
    }

    seq_no = cur_no;
  };
  test_device()->SetDataCallback(data_cb, dispatcher());

  LinkedList<ACLDataPacket> packets;
  for (int i = 1; i <= kExpectedPacketCount; ++i) {
    auto packet = ACLDataPacket::New(kHandle, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                                     hci_spec::ACLBroadcastFlag::kPointToPoint, 1);
    packet->mutable_view()->mutable_payload_bytes()[0] = i;
    packets.push_back(std::move(packet));
  }

  EXPECT_TRUE(acl_data_channel()->SendPackets(std::move(packets), l2cap::kInvalidChannelId,
                                              AclDataChannel::PacketPriority::kLow));

  RunLoopUntilIdle();

  EXPECT_TRUE(pass);
  EXPECT_EQ(kExpectedPacketCount, seq_no);
}

TEST_F(ACLDataChannelTest,
       UnregisterLinkDoesNotClearNumSentPacketsAndClearControllerPacketCountDoes) {
  constexpr size_t kMaxMTU = 1024;
  constexpr size_t kMaxNumPackets = 2;
  constexpr hci_spec::ConnectionHandle kHandle1 = 1;
  constexpr hci_spec::ConnectionHandle kHandle2 = 2;

  InitializeACLDataChannel(DataBufferInfo(kMaxMTU, kMaxNumPackets), DataBufferInfo());

  acl_data_channel()->RegisterLink(kHandle1, bt::LinkType::kLE);
  acl_data_channel()->RegisterLink(kHandle2, bt::LinkType::kLE);

  int packet_count = 0;
  test_device()->SetDataCallback([&](const auto&) { packet_count++; }, dispatcher());

  // Send 3 packets on two links. This is enough to fill up the data buffers.
  ASSERT_TRUE(acl_data_channel()->SendPacket(
      ACLDataPacket::New(kHandle1, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                         hci_spec::ACLBroadcastFlag::kPointToPoint, 1),
      l2cap::kInvalidChannelId, AclDataChannel::PacketPriority::kLow));
  ASSERT_TRUE(acl_data_channel()->SendPacket(
      ACLDataPacket::New(kHandle2, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                         hci_spec::ACLBroadcastFlag::kPointToPoint, 1),
      l2cap::kInvalidChannelId, AclDataChannel::PacketPriority::kLow));
  ASSERT_TRUE(acl_data_channel()->SendPacket(
      ACLDataPacket::New(kHandle1, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                         hci_spec::ACLBroadcastFlag::kPointToPoint, 1),
      l2cap::kInvalidChannelId, AclDataChannel::PacketPriority::kLow));

  RunLoopUntilIdle();

  // The third packet should have been queued.
  ASSERT_EQ(2, packet_count);

  // UnregisterLink should not decrement sent packet count,
  // so next packet should not be sent.
  acl_data_channel()->UnregisterLink(kHandle2);
  RunLoopUntilIdle();
  ASSERT_EQ(2, packet_count);

  // Clear the controller packet count for |kHandle2|. The next packet should go out.
  acl_data_channel()->ClearControllerPacketCount(kHandle2);
  RunLoopUntilIdle();
  ASSERT_EQ(3, packet_count);
}

TEST_F(ACLDataChannelTest, SendingPacketsOnUnregisteredLinkDropsPackets) {
  constexpr size_t kMaxMTU = 1024;
  constexpr size_t kMaxNumPackets = 2;
  constexpr hci_spec::ConnectionHandle kHandle = 1;

  InitializeACLDataChannel(DataBufferInfo(kMaxMTU, kMaxNumPackets), DataBufferInfo());

  int packet_count = 0;
  test_device()->SetDataCallback([&](const auto&) { packet_count++; }, dispatcher());

  // Send packet with unregistered handle.
  ASSERT_FALSE(acl_data_channel()->SendPacket(
      ACLDataPacket::New(kHandle, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                         hci_spec::ACLBroadcastFlag::kPointToPoint, 1),
      l2cap::kInvalidChannelId, AclDataChannel::PacketPriority::kLow));

  RunLoopUntilIdle();

  // Packet should not have been sent.
  ASSERT_EQ(0, packet_count);

  // Now register link. Packet should have been dropped and should still
  // not be sent.
  acl_data_channel()->RegisterLink(kHandle, bt::LinkType::kLE);

  RunLoopUntilIdle();

  // Packet should not have been sent.
  ASSERT_EQ(0, packet_count);

  // Unregister a link that has not been registered
  acl_data_channel()->UnregisterLink(kHandle);
  RunLoopUntilIdle();
  ASSERT_EQ(0, packet_count);
}

TEST_F(ACLDataChannelTest, UnregisterLinkClearsPendingPackets) {
  constexpr size_t kMaxMTU = 1024;
  constexpr size_t kMaxNumPackets = 1;
  constexpr hci_spec::ConnectionHandle kHandle1 = 1;
  constexpr hci_spec::ConnectionHandle kHandle2 = 2;

  InitializeACLDataChannel(DataBufferInfo(kMaxMTU, kMaxNumPackets), DataBufferInfo());

  acl_data_channel()->RegisterLink(kHandle1, bt::LinkType::kLE);
  acl_data_channel()->RegisterLink(kHandle2, bt::LinkType::kLE);

  int handle1_packet_count = 0;
  int handle2_packet_count = 0;
  auto data_callback = [&](const ByteBuffer& bytes) {
    ZX_DEBUG_ASSERT(bytes.size() >= sizeof(hci_spec::ACLDataHeader));

    PacketView<hci_spec::ACLDataHeader> packet(&bytes,
                                               bytes.size() - sizeof(hci_spec::ACLDataHeader));
    hci_spec::ConnectionHandle connection_handle =
        le16toh(packet.header().handle_and_flags) & 0xFFF;

    if (connection_handle == kHandle1) {
      handle1_packet_count++;
    } else {
      ASSERT_EQ(kHandle2, connection_handle);
      handle2_packet_count++;
    }
  };
  test_device()->SetDataCallback(data_callback, dispatcher());

  // Send 3 packets on two links. This is enough to fill up the data buffers.
  ASSERT_TRUE(acl_data_channel()->SendPacket(
      ACLDataPacket::New(kHandle1, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                         hci_spec::ACLBroadcastFlag::kPointToPoint, 1),
      l2cap::kInvalidChannelId, AclDataChannel::PacketPriority::kLow));
  ASSERT_TRUE(acl_data_channel()->SendPacket(
      ACLDataPacket::New(kHandle2, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                         hci_spec::ACLBroadcastFlag::kPointToPoint, 1),
      l2cap::kInvalidChannelId, AclDataChannel::PacketPriority::kLow));
  ASSERT_TRUE(acl_data_channel()->SendPacket(
      ACLDataPacket::New(kHandle1, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                         hci_spec::ACLBroadcastFlag::kPointToPoint, 1),
      l2cap::kInvalidChannelId, AclDataChannel::PacketPriority::kLow));

  RunLoopUntilIdle();

  // Only kHandle1 packet should have been sent
  ASSERT_EQ(1, handle1_packet_count);
  ASSERT_EQ(0, handle2_packet_count);

  // Clear pending packet for |kHandle2|
  acl_data_channel()->UnregisterLink(kHandle2);

  // Notify the processed packet with a Number Of Completed Packet HCI event.
  StaticByteBuffer event_buffer(0x13, 0x05,             // Event header
                                0x01,                   // Number of handles
                                0x01, 0x00, 0x01, 0x00  // 1 packet on handle 0x0001
  );
  test_device()->SendCommandChannelPacket(event_buffer);

  RunLoopUntilIdle();

  // second |kHandle1| packet should have been sent
  ASSERT_EQ(2, handle1_packet_count);
  ASSERT_EQ(0, handle2_packet_count);
}

TEST_F(ACLDataChannelTest, PacketsQueuedByFlowControlAreNotSentAfterUnregisterLink) {
  constexpr size_t kMaxMTU = 1024;
  constexpr size_t kMaxNumPackets = 1;
  constexpr hci_spec::ConnectionHandle kHandle1 = 1;

  InitializeACLDataChannel(DataBufferInfo(kMaxMTU, kMaxNumPackets), DataBufferInfo());

  acl_data_channel()->RegisterLink(kHandle1, bt::LinkType::kLE);

  int packet_count = 0;
  test_device()->SetDataCallback([&](const auto&) { packet_count++; }, dispatcher());

  ASSERT_TRUE(acl_data_channel()->SendPacket(
      ACLDataPacket::New(kHandle1, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                         hci_spec::ACLBroadcastFlag::kPointToPoint, 1),
      l2cap::kInvalidChannelId, AclDataChannel::PacketPriority::kLow));
  ASSERT_TRUE(acl_data_channel()->SendPacket(
      ACLDataPacket::New(kHandle1, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                         hci_spec::ACLBroadcastFlag::kPointToPoint, 1),
      l2cap::kInvalidChannelId, AclDataChannel::PacketPriority::kLow));

  RunLoopUntilIdle();

  // The second packet should have been queued.
  ASSERT_EQ(1, packet_count);

  // Clear the packet count for |kHandle2|. The second packet should NOT go out.
  acl_data_channel()->UnregisterLink(kHandle1);

  // Notify the processed packet with a Number Of Completed Packet HCI event.
  StaticByteBuffer event_buffer(0x13, 0x05,             // Event header
                                0x01,                   // Number of handles
                                0x01, 0x00, 0x01, 0x00  // 1 packet on handle 0x0001
  );
  test_device()->SendCommandChannelPacket(event_buffer);

  RunLoopUntilIdle();

  // The second packet should not have been sent
  ASSERT_EQ(1, packet_count);
}

TEST_F(ACLDataChannelTest,
       StalePacketsBufferedBeforeFirstUnregisterAndBeforeSecondRegisterAreNotSent) {
  constexpr size_t kMaxMTU = 1024;
  constexpr size_t kMaxNumPackets = 1;
  constexpr hci_spec::ConnectionHandle kHandle = 1;

  InitializeACLDataChannel(DataBufferInfo(kMaxMTU, kMaxNumPackets), DataBufferInfo());

  acl_data_channel()->RegisterLink(kHandle, bt::LinkType::kLE);

  // Unique packet to send to re-registered link with same handle.
  const StaticByteBuffer kPacket(
      // ACL data header (handle: 1, length 1)
      0x01, 0x00, 0x01, 0x00,

      // Unique payload to distinguish this packet from stale packet
      0x01);

  int data_cb_count = 0;
  auto data_cb = [&](const ByteBuffer& packet) {
    data_cb_count++;
    if (data_cb_count == 2) {
      EXPECT_TRUE(ContainersEqual(kPacket, packet));
    }
  };
  test_device()->SetDataCallback(data_cb, dispatcher());

  ASSERT_TRUE(acl_data_channel()->SendPacket(
      ACLDataPacket::New(kHandle, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                         hci_spec::ACLBroadcastFlag::kPointToPoint, 1),
      l2cap::kInvalidChannelId, AclDataChannel::PacketPriority::kLow));
  ASSERT_TRUE(acl_data_channel()->SendPacket(
      ACLDataPacket::New(kHandle, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                         hci_spec::ACLBroadcastFlag::kPointToPoint, 1),
      l2cap::kInvalidChannelId, AclDataChannel::PacketPriority::kLow));

  RunLoopUntilIdle();

  // The second packet should have been queued.
  ASSERT_EQ(1, data_cb_count);

  // Clear the packet count for |kHandle2|. The second packet should NOT go out.
  acl_data_channel()->UnregisterLink(kHandle);

  // Notify the processed packet with a Number Of Completed Packet HCI event.
  StaticByteBuffer event_buffer(0x13, 0x05,             // Event header
                                0x01,                   // Number of handles
                                0x01, 0x00, 0x01, 0x00  // 1 packet on handle 0x0001
  );
  test_device()->SendCommandChannelPacket(event_buffer);

  RunLoopUntilIdle();

  // The second packet should not have been sent
  ASSERT_EQ(1, data_cb_count);

  // Re-Register same link handle
  acl_data_channel()->RegisterLink(kHandle, bt::LinkType::kLE);

  auto packet = ACLDataPacket::New(kHandle, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                                   hci_spec::ACLBroadcastFlag::kPointToPoint, 1);
  packet->mutable_view()->mutable_payload_data().Fill(1);

  ASSERT_TRUE(acl_data_channel()->SendPacket(std::move(packet), l2cap::kInvalidChannelId,
                                             AclDataChannel::PacketPriority::kLow));

  RunLoopUntilIdle();

  // The new packet should have been sent to the MockController.
  ASSERT_EQ(2, data_cb_count);
}

TEST_F(ACLDataChannelTest, UnregisterLinkDropsFutureSentPackets) {
  constexpr size_t kMaxMTU = 1024;
  constexpr size_t kMaxNumPackets = 1;
  constexpr hci_spec::ConnectionHandle kHandle = 1;

  InitializeACLDataChannel(DataBufferInfo(kMaxMTU, kMaxNumPackets), DataBufferInfo());

  acl_data_channel()->RegisterLink(kHandle, bt::LinkType::kLE);

  int packet_count = 0;
  test_device()->SetDataCallback([&](const auto&) { packet_count++; }, dispatcher());

  ASSERT_TRUE(acl_data_channel()->SendPacket(
      ACLDataPacket::New(kHandle, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                         hci_spec::ACLBroadcastFlag::kPointToPoint, 1),
      l2cap::kInvalidChannelId, AclDataChannel::PacketPriority::kLow));

  RunLoopUntilIdle();
  ASSERT_EQ(1, packet_count);

  acl_data_channel()->UnregisterLink(kHandle);

  // attempt to send packet on unregistered link
  ASSERT_FALSE(acl_data_channel()->SendPacket(
      ACLDataPacket::New(kHandle, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                         hci_spec::ACLBroadcastFlag::kPointToPoint, 1),
      l2cap::kInvalidChannelId, AclDataChannel::PacketPriority::kLow));

  RunLoopUntilIdle();
  // second packet should not have been sent
  ASSERT_EQ(1, packet_count);
}

TEST_F(ACLDataChannelTest, ReceiveData) {
  constexpr size_t kMaxMTU = 5;
  constexpr size_t kMaxNumPackets = 5;

  // It doesn't matter what we set the buffer values to since we're testing
  // incoming packets.
  InitializeACLDataChannel(DataBufferInfo(kMaxMTU, kMaxNumPackets), DataBufferInfo());

  constexpr size_t kExpectedPacketCount = 2u;
  size_t num_rx_packets = 0u;
  hci_spec::ConnectionHandle packet0_handle;
  hci_spec::ConnectionHandle packet1_handle;
  auto data_rx_cb = [&](ACLDataPacketPtr packet) {
    num_rx_packets++;
    if (num_rx_packets == 1) {
      packet0_handle = packet->connection_handle();
    } else if (num_rx_packets == 2) {
      packet1_handle = packet->connection_handle();
    } else {
      ZX_PANIC("|num_rx_packets| has unexpected value: %zu", num_rx_packets);
    }
  };
  set_data_received_callback(std::move(data_rx_cb));

  // Malformed packet: smaller than the ACL header.
  StaticByteBuffer invalid0(0x01, 0x00, 0x00);

  // Malformed packet: the payload size given in the header doesn't match the
  // actual payload size.
  StaticByteBuffer invalid1(0x01, 0x00, 0x02, 0x00, 0x00);

  // Valid packet on handle 1.
  StaticByteBuffer valid0(0x01, 0x00, 0x01, 0x00, 0x00);

  // Valid packet on handle 2.
  StaticByteBuffer valid1(0x02, 0x00, 0x01, 0x00, 0x00);

  async::PostTask(dispatcher(), [&, this] {
    test_device()->SendACLDataChannelPacket(invalid0);
    test_device()->SendACLDataChannelPacket(invalid1);
    test_device()->SendACLDataChannelPacket(valid0);
    test_device()->SendACLDataChannelPacket(valid1);
  });

  RunLoopUntilIdle();

  EXPECT_EQ(kExpectedPacketCount, num_rx_packets);
  EXPECT_EQ(0x0001, packet0_handle);
  EXPECT_EQ(0x0002, packet1_handle);
}

TEST_F(ACLDataChannelTest, TransportClosedCallbackBothChannels) {
  InitializeACLDataChannel(DataBufferInfo(1u, 1u), DataBufferInfo(1u, 1u));

  int closed_cb_count = 0;
  auto closed_cb = [&closed_cb_count] { closed_cb_count++; };
  transport()->SetTransportClosedCallback(closed_cb);

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

  RunLoopUntilIdle();
  EXPECT_EQ(1, closed_cb_count);
}

// Make sure that a HCI "Number of completed packets" event received after shut
// down does not cause a crash.
TEST_F(ACLDataChannelTest, HciEventReceivedAfterShutDown) {
  InitializeACLDataChannel(DataBufferInfo(1u, 1u), DataBufferInfo(1u, 1u));

  // Notify the processed packets with a Number Of Completed Packet HCI event.
  StaticByteBuffer event_buffer(0x13, 0x09,              // Event header
                                0x02,                    // Number of handles
                                0x01, 0x00, 0x03, 0x00,  // 3 packets on handle 0x0001
                                0x02, 0x00, 0x02, 0x00   // 2 packets on handle 0x0002
  );

  // Shuts down ACLDataChannel and CommandChannel.
  DeleteTransport();

  test_device()->SendCommandChannelPacket(event_buffer);
  RunLoopUntilIdle();
}

TEST_F(ACLDataChannelTest, DropQueuedPacketsRemovesPacketsMatchingFilterFromQueue) {
  constexpr size_t kMaxMTU = 5;
  constexpr size_t kMaxNumPackets = 5;
  constexpr hci_spec::ConnectionHandle kHandle0 = 0x0001;
  constexpr hci_spec::ConnectionHandle kHandle1 = 0x0002;
  constexpr l2cap::ChannelId kChanId0 = 0x40;
  constexpr l2cap::ChannelId kChanId1 = 0x41;

  InitializeACLDataChannel(DataBufferInfo(kMaxMTU, kMaxNumPackets), DataBufferInfo());

  acl_data_channel()->RegisterLink(kHandle0, bt::LinkType::kLE);
  acl_data_channel()->RegisterLink(kHandle1, bt::LinkType::kACL);

  int handle0_packet_count = 0;
  int handle1_packet_count = 0;

  // Callback invoked by TestDevice when it receive a data packet from us.
  auto data_callback = [&](const ByteBuffer& bytes) {
    ZX_DEBUG_ASSERT(bytes.size() >= sizeof(hci_spec::ACLDataHeader));

    PacketView<hci_spec::ACLDataHeader> packet(&bytes,
                                               bytes.size() - sizeof(hci_spec::ACLDataHeader));
    hci_spec::ConnectionHandle connection_handle =
        le16toh(packet.header().handle_and_flags) & 0xFFF;

    if (connection_handle == kHandle0) {
      handle0_packet_count++;
    } else {
      ASSERT_EQ(kHandle1, connection_handle);
      handle1_packet_count++;
    }
  };
  test_device()->SetDataCallback(data_callback, dispatcher());

  // Queue up 10 packets in total, distributed among the two connection handles.
  for (size_t i = 0; i < 2 * kMaxNumPackets; ++i) {
    hci_spec::ConnectionHandle handle = (i % 2) ? kHandle1 : kHandle0;
    auto packet = ACLDataPacket::New(handle, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                                     hci_spec::ACLBroadcastFlag::kPointToPoint, kMaxMTU);
    EXPECT_TRUE(acl_data_channel()->SendPacket(std::move(packet), (i % 2) ? kChanId1 : kChanId0,
                                               AclDataChannel::PacketPriority::kLow));
  }

  RunLoopUntilIdle();

  // kMaxNumPackets is 5. The controller should have received 3 packets on
  // kHandle0 and 2 on kHandle1
  EXPECT_EQ(3, handle0_packet_count);
  EXPECT_EQ(2, handle1_packet_count);

  // Should remove 3 |kHandle1| packets from queue
  size_t predicate_count = 0;
  size_t predicate_true_count = 0;
  acl_data_channel()->DropQueuedPackets([&](const ACLDataPacketPtr& packet, l2cap::ChannelId id) {
    predicate_count++;
    // Verify that correct channels are passed to filter lambda
    if (packet->connection_handle() == kHandle0) {
      EXPECT_EQ(id, kChanId0);
    } else if (packet->connection_handle() == kHandle1) {
      EXPECT_EQ(id, kChanId1);
    }

    bool result = packet->connection_handle() == kHandle1;
    if (result) {
      predicate_true_count++;
    }
    return result;
  });
  // Should be called for each packet in queue (2 |kHandle0| packets + 3 |kHandle1| packets)
  EXPECT_EQ(predicate_count, 5u);
  // 3 |kHandle1| packets
  EXPECT_EQ(predicate_true_count, 3u);

  // Notify the processed packets with a Number Of Completed Packet HCI event.
  StaticByteBuffer event_buffer(0x13, 0x09,              // Event header
                                0x02,                    // Number of handles
                                0x01, 0x00, 0x03, 0x00,  // 3 packets on handle 0x0001
                                0x02, 0x00, 0x02, 0x00   // 2 packets on handle 0x0002
  );
  test_device()->SendCommandChannelPacket(event_buffer);

  RunLoopUntilIdle();

  EXPECT_EQ(5, handle0_packet_count);
  // Other 3 |kHandle1| packets should have been filtered out of queue
  EXPECT_EQ(2, handle1_packet_count);
}

TEST_F(ACLDataChannelTest, HighPriorityPacketsQueuedAfterLowPriorityPacketsAreSentFirst) {
  constexpr size_t kMaxMTU = 5;
  constexpr size_t kMaxNumPackets = 5;
  constexpr hci_spec::ConnectionHandle kHandle0 = 0x0001;
  constexpr hci_spec::ConnectionHandle kHandle1 = 0x0002;

  InitializeACLDataChannel(DataBufferInfo(kMaxMTU, kMaxNumPackets), DataBufferInfo());

  acl_data_channel()->RegisterLink(kHandle0, bt::LinkType::kACL);
  acl_data_channel()->RegisterLink(kHandle1, bt::LinkType::kACL);

  size_t handle0_packet_count = 0;
  size_t handle1_packet_count = 0;

  // Callback invoked by TestDevice when it receive a data packet from us.
  auto data_callback = [&](const ByteBuffer& bytes) {
    ZX_DEBUG_ASSERT(bytes.size() >= sizeof(hci_spec::ACLDataHeader));

    PacketView<hci_spec::ACLDataHeader> packet(&bytes,
                                               bytes.size() - sizeof(hci_spec::ACLDataHeader));
    hci_spec::ConnectionHandle connection_handle =
        le16toh(packet.header().handle_and_flags) & 0xFFF;

    if (connection_handle == kHandle0) {
      handle0_packet_count++;
    } else {
      ASSERT_EQ(kHandle1, connection_handle);
      handle1_packet_count++;
    }
  };
  test_device()->SetDataCallback(data_callback, dispatcher());

  // Fill controller with |kMaxNumPackets| packets so queue can grow.
  for (size_t i = 0; i < kMaxNumPackets; ++i) {
    auto packet = ACLDataPacket::New(kHandle0, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                                     hci_spec::ACLBroadcastFlag::kPointToPoint, kMaxMTU);
    EXPECT_TRUE(acl_data_channel()->SendPacket(std::move(packet), l2cap::kFirstDynamicChannelId,
                                               AclDataChannel::PacketPriority::kLow));
  }
  RunLoopUntilIdle();

  EXPECT_EQ(kMaxNumPackets, handle0_packet_count);
  handle0_packet_count = 0;

  // Queue up 10 packets in total, distributed among the two connection handles.
  for (size_t i = 0; i < 2 * kMaxNumPackets; ++i) {
    hci_spec::ConnectionHandle handle = (i % 2) ? kHandle1 : kHandle0;
    auto priority =
        (i % 2) ? AclDataChannel::PacketPriority::kLow : AclDataChannel::PacketPriority::kHigh;
    auto packet = ACLDataPacket::New(handle, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                                     hci_spec::ACLBroadcastFlag::kPointToPoint, kMaxMTU);
    EXPECT_TRUE(
        acl_data_channel()->SendPacket(std::move(packet), l2cap::kFirstDynamicChannelId, priority));
  }

  RunLoopUntilIdle();

  // No packets should have been sent because controller buffer is full.
  EXPECT_EQ(0u, handle0_packet_count);
  EXPECT_EQ(0u, handle1_packet_count);

  // Notify the processed packets with a Number Of Completed Packet HCI event.
  StaticByteBuffer event_buffer(0x13, 0x05,             // Event header
                                0x01,                   // Number of handles
                                0x01, 0x00, 0x05, 0x00  // 5 packets on handle 0x0001
  );
  test_device()->SendCommandChannelPacket(event_buffer);

  RunLoopUntilIdle();

  // Only high priority packets should have been sent.
  EXPECT_EQ(5u, handle0_packet_count);
  EXPECT_EQ(0u, handle1_packet_count);

  // Notify the processed packets with a Number Of Completed Packet HCI event.
  test_device()->SendCommandChannelPacket(event_buffer);

  RunLoopUntilIdle();
  EXPECT_EQ(5u, handle0_packet_count);
  // Now low priority packets should have been sent.
  EXPECT_EQ(5u, handle1_packet_count);
}

TEST_F(ACLDataChannelTest, OutOfBoundsPacketCountsIgnored) {
  constexpr size_t kMaxMTU = 5;
  constexpr size_t kMaxNumPackets = 6;
  constexpr hci_spec::ConnectionHandle kHandle0 = 0x0001;
  constexpr hci_spec::ConnectionHandle kHandle1 = 0x0002;

  InitializeACLDataChannel(DataBufferInfo(kMaxMTU, kMaxNumPackets), DataBufferInfo());

  acl_data_channel()->RegisterLink(kHandle0, bt::LinkType::kACL);
  acl_data_channel()->RegisterLink(kHandle1, bt::LinkType::kACL);

  size_t handle0_packet_count = 0;
  size_t handle1_packet_count = 0;

  // Callback invoked by TestDevice when it receive a data packet from us.
  auto data_callback = [&](const ByteBuffer& bytes) {
    ZX_DEBUG_ASSERT(bytes.size() >= sizeof(hci_spec::ACLDataHeader));

    PacketView<hci_spec::ACLDataHeader> packet(&bytes,
                                               bytes.size() - sizeof(hci_spec::ACLDataHeader));
    hci_spec::ConnectionHandle connection_handle =
        le16toh(packet.header().handle_and_flags) & 0xFFF;

    if (connection_handle == kHandle0) {
      handle0_packet_count++;
    } else {
      ASSERT_EQ(kHandle1, connection_handle);
      handle1_packet_count++;
    }
  };
  test_device()->SetDataCallback(data_callback, dispatcher());

  // Fill controller with |kMaxNumPackets| packets split evenly between the two handles.
  for (size_t i = 0; i < kMaxNumPackets; ++i) {
    hci_spec::ConnectionHandle handle = (i % 2) ? kHandle1 : kHandle0;
    auto packet = ACLDataPacket::New(handle, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                                     hci_spec::ACLBroadcastFlag::kPointToPoint, kMaxMTU);
    EXPECT_TRUE(acl_data_channel()->SendPacket(std::move(packet), l2cap::kFirstDynamicChannelId,
                                               AclDataChannel::PacketPriority::kLow));
  }
  RunLoopUntilIdle();

  EXPECT_EQ(kMaxNumPackets / 2, handle0_packet_count);
  EXPECT_EQ(kMaxNumPackets / 2, handle1_packet_count);
  handle0_packet_count = 0;
  handle1_packet_count = 0;

  // Queue up 3 packets for each handle,
  for (size_t i = 0; i < kMaxNumPackets / 2; ++i) {
    auto packet = ACLDataPacket::New(kHandle0, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                                     hci_spec::ACLBroadcastFlag::kPointToPoint, kMaxMTU);
    EXPECT_TRUE(acl_data_channel()->SendPacket(std::move(packet), l2cap::kFirstDynamicChannelId,
                                               AclDataChannel::PacketPriority::kLow));
  }
  for (size_t i = 0; i < kMaxNumPackets / 2; ++i) {
    auto packet = ACLDataPacket::New(kHandle1, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                                     hci_spec::ACLBroadcastFlag::kPointToPoint, kMaxMTU);
    EXPECT_TRUE(acl_data_channel()->SendPacket(std::move(packet), l2cap::kFirstDynamicChannelId,
                                               AclDataChannel::PacketPriority::kLow));
  }

  RunLoopUntilIdle();

  // No packets should have been sent because controller buffer is full.
  EXPECT_EQ(0u, handle0_packet_count);
  EXPECT_EQ(0u, handle1_packet_count);

  // Notify the processed packets with a Number Of Completed Packet HCI event.
  StaticByteBuffer event_buffer(0x13, 0x09,              // Event header
                                0x01,                    // Number of handles
                                0x01, 0x00, 0x03, 0x00,  // 3 packets on handle 0x0001
                                0x02, 0x00, 0x05, 0x00   // (ignored, not indicated in handle count)
  );

  test_device()->SendCommandChannelPacket(event_buffer);
  RunLoopUntilIdle();

  // Only packets on handle0 should have been sent.
  EXPECT_EQ(3u, handle0_packet_count);
  EXPECT_EQ(0u, handle1_packet_count);

  StaticByteBuffer short_buffer(0x13, 0x05,             // Event header
                                0x02,                   // Number of handles
                                0x02, 0x00, 0x02, 0x00  // 2 packets on handle 0x0002
                                // (missing second handle, should be ignored)
  );

  test_device()->SendCommandChannelPacket(short_buffer);
  RunLoopUntilIdle();

  // handle1 packets should have been sent anyway
  EXPECT_EQ(3u, handle0_packet_count);
  EXPECT_EQ(2u, handle1_packet_count);
}

class AclPriorityTest : public HCI_ACLDataChannelTest,
                        public ::testing::WithParamInterface<std::pair<hci::AclPriority, bool>> {};
TEST_P(AclPriorityTest, RequestAclPriority) {
  const auto kPriority = GetParam().first;
  const bool kExpectSuccess = GetParam().second;

  const DataBufferInfo kBREDRBufferInfo(1024, 50);
  InitializeACLDataChannel(kBREDRBufferInfo, DataBufferInfo());

  // Arbitrary command payload larger than hci_spec::CommandHeader.
  const auto op_code = hci_spec::VendorOpCode(0x01);
  const StaticByteBuffer kEncodedCommand(LowerBits(op_code), UpperBits(op_code),  // op code
                                         0x04,                                    // parameter size
                                         0x00, 0x01, 0x02, 0x03);                 // test parameter

  constexpr hci_spec::ConnectionHandle kLinkHandle = 0x0001;

  std::optional<hci_spec::ConnectionHandle> connection;
  std::optional<hci::AclPriority> priority;
  set_encode_acl_priority_command_cb(
      [&](hci_spec::ConnectionHandle cb_connection, hci::AclPriority cb_priority) {
        connection = cb_connection;
        priority = cb_priority;
        return fitx::ok(DynamicByteBuffer(kEncodedCommand));
      });

  auto cmd_complete = bt::testing::CommandCompletePacket(
      op_code,
      kExpectSuccess ? hci_spec::StatusCode::kSuccess : hci_spec::StatusCode::kUnknownCommand);
  EXPECT_CMD_PACKET_OUT(test_device(), kEncodedCommand, &cmd_complete);

  size_t request_cb_count = 0;
  acl_data_channel()->RequestAclPriority(kPriority, kLinkHandle, [&](auto result) {
    request_cb_count++;
    EXPECT_EQ(kExpectSuccess, result.is_ok());
  });

  RunLoopUntilIdle();
  EXPECT_EQ(request_cb_count, 1u);
  ASSERT_TRUE(connection);
  EXPECT_EQ(connection.value(), kLinkHandle);
  ASSERT_TRUE(priority);
  EXPECT_EQ(priority.value(), kPriority);
}

const std::array<std::pair<hci::AclPriority, bool>, 4> kPriorityParams = {
    {{hci::AclPriority::kSource, /*expect_success=*/false},
     {hci::AclPriority::kSource, true},
     {hci::AclPriority::kSink, true},
     {hci::AclPriority::kNormal, true}}};
INSTANTIATE_TEST_SUITE_P(ACLDataChannelTest, AclPriorityTest, ::testing::ValuesIn(kPriorityParams));

TEST_F(ACLDataChannelTest, RequestAclPriorityEncodeFails) {
  const DataBufferInfo kBREDRBufferInfo(1024, 50);
  InitializeACLDataChannel(kBREDRBufferInfo, DataBufferInfo());

  set_encode_acl_priority_command_cb([&](auto, auto) { return fitx::error(ZX_ERR_INTERNAL); });

  size_t request_cb_count = 0;
  acl_data_channel()->RequestAclPriority(hci::AclPriority::kSink, kLinkHandle, [&](auto result) {
    request_cb_count++;
    EXPECT_TRUE(result.is_error());
  });

  RunLoopUntilIdle();
  EXPECT_EQ(request_cb_count, 1u);
}

TEST_F(ACLDataChannelTest, RequestAclPriorityEncodeReturnsTooSmallBuffer) {
  const DataBufferInfo kBREDRBufferInfo(1024, 50);
  InitializeACLDataChannel(kBREDRBufferInfo, DataBufferInfo());

  set_encode_acl_priority_command_cb(
      [](auto, auto) { return fitx::ok(DynamicByteBuffer(StaticByteBuffer(0x00))); });

  size_t request_cb_count = 0;
  acl_data_channel()->RequestAclPriority(hci::AclPriority::kSink, kLinkHandle, [&](auto result) {
    request_cb_count++;
    EXPECT_TRUE(result.is_error());
  });

  RunLoopUntilIdle();
  EXPECT_EQ(request_cb_count, 1u);
}

TEST_F(ACLDataChannelTest, SetAutomaticFlushTimeout) {
  const DataBufferInfo kBREDRBufferInfo(1024, 50);
  InitializeACLDataChannel(kBREDRBufferInfo, DataBufferInfo());
  acl_data_channel()->RegisterLink(kLinkHandle, bt::LinkType::kACL);

  std::optional<Result<>> cb_status;
  auto result_cb = [&](auto status) { cb_status = status; };

  // Test command complete error
  const auto kCommandCompleteError = bt::testing::CommandCompletePacket(
      hci_spec::kWriteAutomaticFlushTimeout, hci_spec::StatusCode::kUnknownConnectionId);
  EXPECT_CMD_PACKET_OUT(test_device(),
                        bt::testing::WriteAutomaticFlushTimeoutPacket(kLinkHandle, 0),
                        &kCommandCompleteError);
  acl_data_channel()->SetBrEdrAutomaticFlushTimeout(zx::duration::infinite(), kLinkHandle,
                                                    result_cb);
  RunLoopUntilIdle();
  ASSERT_TRUE(cb_status.has_value());
  ASSERT_TRUE(cb_status->is_error());
  EXPECT_EQ(ToResult(hci_spec::StatusCode::kUnknownConnectionId), *cb_status);
  cb_status.reset();

  // Test flush timeout = 0 (no command should be sent)
  acl_data_channel()->SetBrEdrAutomaticFlushTimeout(zx::msec(0), kLinkHandle, result_cb);
  RunLoopUntilIdle();
  ASSERT_TRUE(cb_status.has_value());
  EXPECT_TRUE(cb_status->is_error());
  EXPECT_EQ(ToResult(hci_spec::StatusCode::kInvalidHCICommandParameters), *cb_status);

  // Test infinite flush timeout (flush timeout of 0 should be sent).
  const auto kCommandComplete = bt::testing::CommandCompletePacket(
      hci_spec::kWriteAutomaticFlushTimeout, hci_spec::StatusCode::kSuccess);
  EXPECT_CMD_PACKET_OUT(test_device(),
                        bt::testing::WriteAutomaticFlushTimeoutPacket(kLinkHandle, 0),
                        &kCommandComplete);
  acl_data_channel()->SetBrEdrAutomaticFlushTimeout(zx::duration::infinite(), kLinkHandle,
                                                    result_cb);
  RunLoopUntilIdle();
  ASSERT_TRUE(cb_status.has_value());
  EXPECT_EQ(fitx::ok(), *cb_status);
  cb_status.reset();

  // Test msec to parameter conversion (hci_spec::kMaxAutomaticFlushTimeoutDuration(1279) *
  // conversion_factor(1.6) = 2046).
  EXPECT_CMD_PACKET_OUT(test_device(),
                        bt::testing::WriteAutomaticFlushTimeoutPacket(kLinkHandle, 2046),
                        &kCommandComplete);
  acl_data_channel()->SetBrEdrAutomaticFlushTimeout(hci_spec::kMaxAutomaticFlushTimeoutDuration,
                                                    kLinkHandle, result_cb);
  RunLoopUntilIdle();
  ASSERT_TRUE(cb_status.has_value());
  EXPECT_EQ(fitx::ok(), *cb_status);
  cb_status.reset();

  // Test too large flush timeout (no command should be sent).
  acl_data_channel()->SetBrEdrAutomaticFlushTimeout(
      hci_spec::kMaxAutomaticFlushTimeoutDuration + zx::msec(1), kLinkHandle, result_cb);
  RunLoopUntilIdle();
  ASSERT_TRUE(cb_status.has_value());
  EXPECT_TRUE(cb_status->is_error());
  EXPECT_EQ(ToResult(hci_spec::StatusCode::kInvalidHCICommandParameters), *cb_status);
}

TEST_F(ACLDataChannelTest,
       SendingLowPriorityBrEdrPacketsWhenTooManyAreQueuedDropsLeastRecentlySentPduOnSameChannel) {
  constexpr size_t kMaxMtu = 4;
  constexpr size_t kMaxNumPackets = 2;
  constexpr hci_spec::ConnectionHandle kHandle0 = 0x0001;
  constexpr hci_spec::ConnectionHandle kHandle1 = 0x0002;

  InitializeACLDataChannel(DataBufferInfo(kMaxMtu, kMaxNumPackets),
                           DataBufferInfo(kMaxMtu, kMaxNumPackets));

  acl_data_channel()->RegisterLink(kHandle0, bt::LinkType::kLE);
  acl_data_channel()->RegisterLink(kHandle1, bt::LinkType::kACL);

  inspect::Inspector inspector;
  acl_data_channel()->AttachInspect(inspector.GetRoot(), AclDataChannel::kInspectNodeName);

  // Fill up both LE and BR/EDR controller buffers
  for (hci_spec::ConnectionHandle handle : {kHandle0, kHandle1}) {
    for (size_t i = 0; i < kMaxNumPackets; ++i) {
      auto packet = ACLDataPacket::New(handle, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                                       hci_spec::ACLBroadcastFlag::kPointToPoint, kMaxMtu);
      EXPECT_TRUE(acl_data_channel()->SendPacket(std::move(packet), l2cap::kFirstDynamicChannelId,
                                                 AclDataChannel::PacketPriority::kLow));
    }
  }
  RunLoopUntilIdle();

  // Callback invoked by TestDevice when it receive a data packet from us.
  size_t packet_count = 0;
  auto data_callback = [&](const ByteBuffer& bytes) {
    ASSERT_LE(sizeof(hci_spec::ACLDataHeader), bytes.size());
    PacketView<hci_spec::ACLDataHeader> packet(&bytes,
                                               bytes.size() - sizeof(hci_spec::ACLDataHeader));
    hci_spec::ConnectionHandle connection_handle =
        le16toh(packet.header().handle_and_flags) & 0xFFF;

    // LE is still waiting for controller credits
    EXPECT_EQ(kHandle1, connection_handle);

    if ((packet_count == 0) || (packet_count == 1)) {
      // The first low-priority queued packet and its continuation packet were dropped so the first
      // packets actually sent should be those for the second PDU
      EXPECT_EQ(1u, packet.payload_data()[0]);
    }

    packet_count++;
  };
  test_device()->SetDataCallback(data_callback, dispatcher());

  // Send enough data that the first PDU sent in this loop gets dropped
  for (size_t i = 0; i < AclDataChannel::kMaxAclPacketsPerChannel + 1; ++i) {
    // Send two fragments per PDU
    LinkedList<ACLDataPacket> packets;
    for (auto pbf : {hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                     hci_spec::ACLPacketBoundaryFlag::kContinuingFragment}) {
      auto packet =
          ACLDataPacket::New(kHandle1, pbf, hci_spec::ACLBroadcastFlag::kPointToPoint, kMaxMtu);

      // Write a sequence number into the payload, starting at 0
      packet->mutable_view()->mutable_payload_data()[0] = static_cast<uint8_t>(i);
      packets.push_back(std::move(packet));
    }
    EXPECT_TRUE(acl_data_channel()->SendPackets(std::move(packets), l2cap::kFirstDynamicChannelId,
                                                AclDataChannel::PacketPriority::kLow));
  }

  test_device()->SendCommandChannelPacket(bt::testing::NumberOfCompletedPacketsPacket(kHandle1, 2));
  RunLoopUntilIdle();

  EXPECT_EQ(2u, packet_count);

  using namespace ::inspect::testing;
  auto adc_matcher = NodeMatches(
      PropertyList(AllOf(Contains(UintIs("num_overflow_packets", packet_count)),
                         Contains(UintIs("num_recent_overflow_packets", packet_count)))));

  auto hierarchy = inspect::ReadFromVmo(inspector.DuplicateVmo()).take_value();
  EXPECT_THAT(hierarchy, ChildrenMatch(ElementsAre(adc_matcher)));
}

TEST_F(ACLDataChannelTest,
       SendingLowPriorityPacketsThatDropDoNotAffectDataOnSameLinkDifferentChannel) {
  constexpr size_t kMaxMtu = 4;
  constexpr size_t kMaxNumPackets = 2;
  constexpr hci_spec::ConnectionHandle kHandle0 = 0x0001;
  constexpr UniqueChannelId kChannelId0 = l2cap::kFirstDynamicChannelId;
  constexpr UniqueChannelId kChannelId1 = l2cap::kFirstDynamicChannelId + 1;

  InitializeACLDataChannel(DataBufferInfo(kMaxMtu, kMaxNumPackets));

  acl_data_channel()->RegisterLink(kHandle0, bt::LinkType::kACL);

  // Fill up controller buffers
  for (size_t i = 0; i < kMaxNumPackets; ++i) {
    auto packet = ACLDataPacket::New(kHandle0, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                                     hci_spec::ACLBroadcastFlag::kPointToPoint, kMaxMtu);
    EXPECT_TRUE(acl_data_channel()->SendPacket(std::move(packet), l2cap::kFirstDynamicChannelId,
                                               AclDataChannel::PacketPriority::kLow));
  }
  RunLoopUntilIdle();

  // Callback invoked by TestDevice when it receive a data packet from us.
  size_t packet_count = 0;
  auto data_callback = [&](const ByteBuffer& bytes) {
    ASSERT_LT(sizeof(hci_spec::ACLDataHeader), bytes.size());
    PacketView<hci_spec::ACLDataHeader> packet(&bytes,
                                               bytes.size() - sizeof(hci_spec::ACLDataHeader));

    // The first packet should be left in the queue because it is for kChannelId0 but the second
    // should be dropped as it was the least recently sent unsent packet for channel kChannelId1.
    if (packet_count == 0) {
      EXPECT_EQ(0u, packet.payload_data()[0]);
    } else if (packet_count == 1) {
      EXPECT_EQ(2u, packet.payload_data()[0]);
    }

    packet_count++;
  };
  test_device()->SetDataCallback(data_callback, dispatcher());

  // Send one packet on kChannelId0
  {
    auto packet = ACLDataPacket::New(kHandle0, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                                     hci_spec::ACLBroadcastFlag::kPointToPoint, kMaxMtu);

    // Write a sequence number into the payload, starting at 0
    packet->mutable_view()->mutable_payload_data()[0] = static_cast<uint8_t>(0);
    EXPECT_TRUE(acl_data_channel()->SendPacket(std::move(packet), kChannelId0,
                                               AclDataChannel::PacketPriority::kLow));
  }

  // Send enough data on kChannel1 that the first PDU sent in this loop gets dropped
  for (size_t i = 0; i < AclDataChannel::kMaxAclPacketsPerChannel + 1; i++) {
    auto packet = ACLDataPacket::New(kHandle0, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                                     hci_spec::ACLBroadcastFlag::kPointToPoint, kMaxMtu);

    // Write a sequence number into the payload, starting at 0
    packet->mutable_view()->mutable_payload_data()[0] = static_cast<uint8_t>(i + 1);
    EXPECT_TRUE(acl_data_channel()->SendPacket(std::move(packet), kChannelId1,
                                               AclDataChannel::PacketPriority::kLow));
  }

  test_device()->SendCommandChannelPacket(bt::testing::NumberOfCompletedPacketsPacket(kHandle0, 2));
  RunLoopUntilIdle();

  EXPECT_EQ(2u, packet_count);
}

TEST_F(ACLDataChannelTest, SendingLowPriorityPacketsThatDropDoNotAffectDataOnDifferentLink) {
  constexpr size_t kMaxMtu = 4;
  constexpr size_t kMaxNumPackets = 2;
  constexpr hci_spec::ConnectionHandle kHandle0 = 0x0001;
  constexpr hci_spec::ConnectionHandle kHandle1 = 0x0002;

  InitializeACLDataChannel(DataBufferInfo(kMaxMtu, kMaxNumPackets));

  acl_data_channel()->RegisterLink(kHandle0, bt::LinkType::kACL);
  acl_data_channel()->RegisterLink(kHandle1, bt::LinkType::kACL);

  // Fill up controller buffers
  for (size_t i = 0; i < kMaxNumPackets; ++i) {
    auto packet = ACLDataPacket::New(kHandle0, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                                     hci_spec::ACLBroadcastFlag::kPointToPoint, kMaxMtu);
    EXPECT_TRUE(acl_data_channel()->SendPacket(std::move(packet), l2cap::kFirstDynamicChannelId,
                                               AclDataChannel::PacketPriority::kLow));
  }
  RunLoopUntilIdle();

  // Callback invoked by TestDevice when it receive a data packet from us.
  size_t packet_count = 0;
  auto data_callback = [&](const ByteBuffer& bytes) {
    ASSERT_LT(sizeof(hci_spec::ACLDataHeader), bytes.size());
    PacketView<hci_spec::ACLDataHeader> packet(&bytes,
                                               bytes.size() - sizeof(hci_spec::ACLDataHeader));
    hci_spec::ConnectionHandle connection_handle =
        le16toh(packet.header().handle_and_flags) & 0xFFF;

    // First packet on kHandle0 doesn't get dropped, but first packet on kHandle1 does get dropped
    // because there are too many queued for that channel on that link.
    if (packet_count == 0) {
      EXPECT_EQ(kHandle0, connection_handle);
      EXPECT_EQ(0u, packet.payload_data()[0]);
    } else if (packet_count == 1) {
      EXPECT_EQ(kHandle1, connection_handle);
      EXPECT_EQ(2u, packet.payload_data()[0]);
    }
    packet_count++;
  };
  test_device()->SetDataCallback(data_callback, dispatcher());

  // Send one data packet on kHandle0
  {
    auto packet = ACLDataPacket::New(kHandle0, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                                     hci_spec::ACLBroadcastFlag::kPointToPoint, kMaxMtu);

    // Write a sequence number into the payload, starting at 0
    packet->mutable_view()->mutable_payload_data()[0] = static_cast<uint8_t>(0);
    EXPECT_TRUE(acl_data_channel()->SendPacket(std::move(packet), l2cap::kFirstDynamicChannelId,
                                               AclDataChannel::PacketPriority::kLow));
  }

  // Send enough data on kHandle1 that the first PDU sent in this loop gets dropped
  for (size_t i = 0; i < AclDataChannel::kMaxAclPacketsPerChannel + 1; i++) {
    auto packet = ACLDataPacket::New(kHandle1, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                                     hci_spec::ACLBroadcastFlag::kPointToPoint, kMaxMtu);

    // Write a sequence number into the payload, starting at 0
    packet->mutable_view()->mutable_payload_data()[0] = static_cast<uint8_t>(i + 1);
    EXPECT_TRUE(acl_data_channel()->SendPacket(std::move(packet), l2cap::kFirstDynamicChannelId,
                                               AclDataChannel::PacketPriority::kLow));
  }

  test_device()->SendCommandChannelPacket(bt::testing::NumberOfCompletedPacketsPacket(kHandle0, 2));
  RunLoopUntilIdle();

  EXPECT_EQ(2u, packet_count);
}

TEST_F(ACLDataChannelTest, QueuedAclAndLePacketsAreSentUsingSeparateBufferCounts) {
  constexpr size_t kMaxMtu = 4;
  constexpr size_t kMaxNumPackets = 2;
  constexpr hci_spec::ConnectionHandle kHandle0 = 0x0001;
  constexpr hci_spec::ConnectionHandle kHandle1 = 0x0002;

  InitializeACLDataChannel(DataBufferInfo(kMaxMtu, kMaxNumPackets),
                           DataBufferInfo(kMaxMtu, kMaxNumPackets));

  acl_data_channel()->RegisterLink(kHandle0, bt::LinkType::kLE);
  acl_data_channel()->RegisterLink(kHandle1, bt::LinkType::kACL);

  // Fill up both LE and BR/EDR controller buffers, leaving one additional packet in the queue of
  // each type
  for (hci_spec::ConnectionHandle handle : {kHandle0, kHandle1}) {
    for (size_t i = 0; i < kMaxNumPackets + 1; ++i) {
      auto packet = ACLDataPacket::New(handle, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                                       hci_spec::ACLBroadcastFlag::kPointToPoint, kMaxMtu);
      EXPECT_TRUE(acl_data_channel()->SendPacket(std::move(packet), l2cap::kFirstDynamicChannelId,
                                                 AclDataChannel::PacketPriority::kLow));
    }
  }
  RunLoopUntilIdle();

  // Callback invoked by TestDevice when it receive a data packet from us.
  size_t packet_count = 0;
  test_device()->SetDataCallback([&](auto&) { packet_count++; }, dispatcher());

  StaticByteBuffer event_buffer(0x13, 0x09,  // Event header
                                0x02,        // Number of handles
                                LowerBits(kHandle0), UpperBits(kHandle0), LowerBits(uint16_t{1}),
                                UpperBits(uint16_t{1}),  // 1 packets on kHandle0
                                LowerBits(kHandle1), UpperBits(kHandle1), LowerBits(uint16_t{1}),
                                UpperBits(uint16_t{1})  // 1 packets on kHandle1
  );
  test_device()->SendCommandChannelPacket(event_buffer);
  RunLoopUntilIdle();

  EXPECT_EQ(2u, packet_count);
}

TEST_F(ACLDataChannelTest, InspectHierarchyContainsOutboundQueueState) {
  constexpr size_t kMaxMtu = 4;
  constexpr size_t kMaxNumPackets = 2;
  constexpr hci_spec::ConnectionHandle kHandle0 = 0x0001;
  constexpr hci_spec::ConnectionHandle kHandle1 = 0x0002;

  InitializeACLDataChannel(DataBufferInfo(kMaxMtu, kMaxNumPackets),
                           DataBufferInfo(kMaxMtu, kMaxNumPackets));

  acl_data_channel()->RegisterLink(kHandle0, bt::LinkType::kLE);
  acl_data_channel()->RegisterLink(kHandle1, bt::LinkType::kACL);

  // Fill up both LE and BR/EDR controller buffers, leaving one additional packet in the queue of
  // each type
  for (hci_spec::ConnectionHandle handle : {kHandle0, kHandle1}) {
    for (size_t i = 0; i < kMaxNumPackets + 1; ++i) {
      auto packet = ACLDataPacket::New(handle, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                                       hci_spec::ACLBroadcastFlag::kPointToPoint, kMaxMtu);
      EXPECT_TRUE(acl_data_channel()->SendPacket(std::move(packet), l2cap::kFirstDynamicChannelId,
                                                 AclDataChannel::PacketPriority::kLow));
    }
  }
  RunLoopUntilIdle();

  inspect::Inspector inspector;
  const std::string kNodeName = "adc_node_name";
  acl_data_channel()->AttachInspect(inspector.GetRoot(), kNodeName);

  using namespace ::inspect::testing;
  auto bredr_matcher = NodeMatches(AllOf(
      NameMatches("bredr"), PropertyList(ElementsAre(UintIs("num_sent_packets", kMaxNumPackets)))));

  auto le_matcher = NodeMatches(
      AllOf(NameMatches("le"),
            PropertyList(UnorderedElementsAre(UintIs("num_sent_packets", kMaxNumPackets),
                                              BoolIs("independent_from_bredr", true)))));

  auto send_latency_matcher =
      NodeMatches(AllOf(NameMatches("send_latency"),
                        PropertyList(UnorderedElementsAre(IntIs("50th_percentile_us", 0),
                                                          IntIs("95th_percentile_us", 0),
                                                          IntIs("99th_percentile_us", 0)))));

  auto send_size_matcher =
      NodeMatches(AllOf(NameMatches("send_size"),
                        PropertyList(UnorderedElementsAre(UintIs("10th_percentile_bytes", 0),
                                                          UintIs("50th_percentile_bytes", 0),
                                                          UintIs("90th_percentile_bytes", 0)))));

  auto metrics_matcher =
      AllOf(NodeMatches(NameMatches("metrics")),
            ChildrenMatch(UnorderedElementsAre(send_latency_matcher, send_size_matcher)));

  auto adc_matcher = AllOf(
      NodeMatches(AllOf(NameMatches(kNodeName),
                        PropertyList(UnorderedElementsAre(
                            UintIs("num_queued_packets", 2), UintIs("num_overflow_packets", 0),
                            UintIs("num_recent_overflow_packets", 0))))),
      ChildrenMatch(UnorderedElementsAre(bredr_matcher, le_matcher, metrics_matcher)));

  auto hierarchy = inspect::ReadFromVmo(inspector.DuplicateVmo()).take_value();
  EXPECT_THAT(hierarchy, ChildrenMatch(ElementsAre(adc_matcher)));
}

TEST_F(ACLDataChannelTest, SendingPacketsUpdatesSendMetrics) {
  constexpr size_t kMaxMtu = 4;
  constexpr size_t kMaxNumPackets = 2;
  constexpr hci_spec::ConnectionHandle kHandle0 = 0x0001;

  InitializeACLDataChannel(DataBufferInfo(kMaxMtu, kMaxNumPackets));

  inspect::Inspector inspector;
  acl_data_channel()->AttachInspect(inspector.GetRoot(), AclDataChannel::kInspectNodeName);

  acl_data_channel()->RegisterLink(kHandle0, bt::LinkType::kACL);

  // Fill up controller buffers
  for (size_t i = 0; i < kMaxNumPackets; ++i) {
    auto packet = ACLDataPacket::New(kHandle0, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                                     hci_spec::ACLBroadcastFlag::kPointToPoint, kMaxMtu);
    ASSERT_TRUE(acl_data_channel()->SendPacket(std::move(packet), l2cap::kFirstDynamicChannelId,
                                               AclDataChannel::PacketPriority::kLow));
  }
  RunLoopUntilIdle();

  // Send enough data that metrics are exported
  constexpr size_t kNumTestPackets = 256;
  constexpr zx::duration kSendLatency = zx::msec(1);
  for (size_t i = 0; i < kNumTestPackets; ++i) {
    auto packet = ACLDataPacket::New(kHandle0, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
                                     hci_spec::ACLBroadcastFlag::kPointToPoint, kMaxMtu);
    ASSERT_TRUE(acl_data_channel()->SendPacket(std::move(packet), l2cap::kFirstDynamicChannelId,
                                               AclDataChannel::PacketPriority::kLow));
    RunLoopFor(kSendLatency);
    test_device()->SendCommandChannelPacket(
        bt::testing::NumberOfCompletedPacketsPacket(kHandle0, 1));
    RunLoopUntilIdle();
  }

  // Wait for the metric writing task to catch up
  RunLoopRepeatedlyFor(zx::min(1));

  inspect::Hierarchy hierarchy = ReadInspect(inspector);
  const inspect::Hierarchy* const send_latency_node =
      hierarchy.GetByPath({AclDataChannel::kInspectNodeName, "metrics", "send_latency"});
  ASSERT_TRUE(send_latency_node);
  const auto* const send_latency_median_wrapped =
      send_latency_node->node().get_property<inspect::IntPropertyValue>("50th_percentile_us");
  ASSERT_TRUE(send_latency_median_wrapped);
  EXPECT_EQ(kSendLatency.to_usecs(), send_latency_median_wrapped->value());

  const inspect::Hierarchy* const send_size_node =
      hierarchy.GetByPath({AclDataChannel::kInspectNodeName, "metrics", "send_size"});
  ASSERT_TRUE(send_size_node);
  const auto* const send_size_median_wrapped =
      send_size_node->node().get_property<inspect::UintPropertyValue>("50th_percentile_bytes");
  ASSERT_TRUE(send_size_median_wrapped);
  EXPECT_EQ(kMaxMtu, send_size_median_wrapped->value());
}

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