// Copyright 2020 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/testing/fake_dynamic_channel.h"

#include <lib/gtest/test_loop_fixture.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/l2cap/l2cap_defs.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/test_packets.h"
#include "src/connectivity/bluetooth/core/bt-host/testing/fake_l2cap.h"
#include "src/connectivity/bluetooth/core/bt-host/testing/fake_signaling_server.h"

namespace bt::testing {
namespace {

hci::ConnectionHandle kConnectionHandle = 0x01;
l2cap::CommandId kCommandId = 0x02;
l2cap::PSM kPsm = l2cap::kSDP;

TEST(TESTING_FakeDynamicChannelTest, ConnectOpenDisconnectChannel) {
  std::unique_ptr<ByteBuffer> received_packet;
  auto send_cb = [&received_packet](auto kConnectionHandle, auto cid, auto& buffer) {
    received_packet = std::make_unique<DynamicByteBuffer>(buffer);
  };
  auto fake_l2cap = FakeL2cap(send_cb);
  auto server = std::make_unique<FakeSignalingServer>();
  server->RegisterWithL2cap(&fake_l2cap);
  auto channel_cb = [](auto fake_dynamic_channel) {};
  fake_l2cap.RegisterService(kPsm, channel_cb);
  l2cap::ChannelId src_id = l2cap::kFirstDynamicChannelId;
  l2cap::ChannelParameters params;

  // Assemble and send the ConnectionRequest to connect, but not open, the channel.
  auto connection_acl_packet =
      l2cap::testing::AclConnectionReq(kCommandId, kConnectionHandle, src_id, kPsm);
  const auto& connection_header = connection_acl_packet.As<hci::ACLDataHeader>();
  auto connection_header_len = sizeof(connection_header);
  auto connection_payload_len = le16toh(connection_header.data_total_length);
  auto connection_packet = DynamicByteBuffer(connection_payload_len);
  connection_acl_packet.Copy(&connection_packet, connection_header_len, connection_payload_len);
  fake_l2cap.HandlePdu(kConnectionHandle, connection_packet);

  // Anticipate that we then receive a ConfigurationRequest. HandlePdu will
  // first send a ConnectionResponse, but the most recent packet should be a
  // ConfigurationRequest. The channel should also be connected, but not open,
  // at this time.
  // Manually create the expected ConfigurationRequest with no payload.
  StaticByteBuffer expected_request(
      // Configuration request command code, CommandId associated with the test
      l2cap::kConfigurationRequest, kCommandId,
      // Payload length (4 total bytes)
      0x04, 0x00,
      // Source ID (2 bytes)
      LowerBits(src_id), UpperBits(src_id),
      // No continuation flags (2 bytes)
      0x00, 0x00);
  EXPECT_TRUE(ContainersEqual(expected_request, *received_packet));
  EXPECT_FALSE(fake_l2cap.FindDynamicChannelByLocalId(kConnectionHandle, src_id)
                   ->configuration_request_received());
  EXPECT_FALSE(fake_l2cap.FindDynamicChannelByLocalId(kConnectionHandle, src_id)
                   ->configuration_response_received());
  EXPECT_FALSE(fake_l2cap.FindDynamicChannelByRemoteId(kConnectionHandle, src_id)->opened());

  // Send a ConfigurationResponse to the received ConfigurationRequest.
  auto configuration_response_acl_packet =
      l2cap::testing::AclConfigRsp(kCommandId, kConnectionHandle, src_id, params);
  const auto& configuration_response_header =
      configuration_response_acl_packet.As<hci::ACLDataHeader>();
  auto configuration_response_header_len = sizeof(configuration_response_header);
  auto configuration_response_payload_len =
      le16toh(configuration_response_header.data_total_length);
  auto configuration_response_packet = DynamicByteBuffer(configuration_response_payload_len);
  configuration_response_acl_packet.Copy(&configuration_response_packet,
                                         configuration_response_header_len,
                                         configuration_response_payload_len);
  fake_l2cap.HandlePdu(kConnectionHandle, configuration_response_packet);
  EXPECT_FALSE(fake_l2cap.FindDynamicChannelByLocalId(kConnectionHandle, src_id)
                   ->configuration_request_received());
  EXPECT_TRUE(fake_l2cap.FindDynamicChannelByLocalId(kConnectionHandle, src_id)
                  ->configuration_response_received());
  EXPECT_FALSE(fake_l2cap.FindDynamicChannelByRemoteId(kConnectionHandle, src_id)->opened());

  // Assemble and send the ConfigurationRequest to open up the channel.
  // In this isolated test, we can assume that the src_id and dest_id are identical.
  auto configuration_request_acl_packet =
      l2cap::testing::AclConfigReq(kCommandId, kConnectionHandle, src_id, params);
  const auto& configuration_request_header =
      configuration_request_acl_packet.As<hci::ACLDataHeader>();
  auto configuration_request_header_len = sizeof(configuration_request_header);
  auto configuration_request_payload_len = le16toh(configuration_request_header.data_total_length);
  auto configuration_request_packet = DynamicByteBuffer(configuration_request_payload_len);
  configuration_request_acl_packet.Copy(&configuration_request_packet,
                                        configuration_request_header_len,
                                        configuration_request_payload_len);
  fake_l2cap.HandlePdu(kConnectionHandle, configuration_request_packet);

  // Anticipate that we then receive a ConfigurationResponse after we send a
  // Manually create the expected ConfigurationRequest with no payload.
  StaticByteBuffer expected_response(
      // Configuration request command code, CommandId associated with the test
      l2cap::kConfigurationResponse, kCommandId,
      // Payload length (6 total bytes)
      0x06, 0x00,
      // Source ID (2 bytes)
      LowerBits(src_id), UpperBits(src_id),
      // No continuation flags (2 bytes)
      0x00, 0x00,
      // Result (Success)
      LowerBits(0x0000), UpperBits(0x0000));
  EXPECT_TRUE(ContainersEqual(expected_response, *received_packet));
  EXPECT_TRUE(fake_l2cap.FindDynamicChannelByLocalId(kConnectionHandle, src_id)
                  ->configuration_request_received());
  EXPECT_TRUE(fake_l2cap.FindDynamicChannelByLocalId(kConnectionHandle, src_id)
                  ->configuration_response_received());
  EXPECT_TRUE(fake_l2cap.FindDynamicChannelByRemoteId(kConnectionHandle, src_id)->opened());

  // Assemble and send the DisconnectionRequest to open up the channel.
  // In this isolated test, we can assume that the src_id and dest_id are identical.
  auto disconnection_acl_packet =
      l2cap::testing::AclDisconnectionReq(kCommandId, kConnectionHandle, src_id, src_id);
  const auto& disconnection_header = disconnection_acl_packet.As<hci::ACLDataHeader>();
  auto disconnection_header_len = sizeof(disconnection_header);
  auto disconnection_payload_len = le16toh(disconnection_header.data_total_length);
  auto disconnection_packet = DynamicByteBuffer(disconnection_payload_len);
  disconnection_acl_packet.Copy(&disconnection_packet, disconnection_header_len,
                                disconnection_payload_len);
  fake_l2cap.HandlePdu(kConnectionHandle, disconnection_packet);

  // Anticipate that we receive a DisconnectionResponse after we send the
  // request and that the channel has been deleted.
  StaticByteBuffer disconnection_response(
      // Configuration request command code, CommandId associated with the test
      l2cap::kDisconnectionResponse, kCommandId,
      // Payload length (4 total bytes)
      0x04, 0x00,
      // Source ID (2 bytes)
      LowerBits(src_id), UpperBits(src_id),
      // Dest ID (2 bytes)
      LowerBits(src_id), UpperBits(src_id));
  EXPECT_TRUE(ContainersEqual(disconnection_response, *received_packet));
  EXPECT_FALSE(fake_l2cap.FindDynamicChannelByLocalId(kConnectionHandle, src_id));
};

TEST(TESTING_FakeDynamicChannelTest, FailToRegisterChannelWithoutRegisteredService) {
  // Create a custom FakeL2cap with no registered services.
  std::unique_ptr<ByteBuffer> received_packet;
  auto send_cb = [&received_packet](auto kConnectionHandle, auto cid, auto& buffer) {
    received_packet = std::make_unique<DynamicByteBuffer>(buffer);
  };
  auto fake_l2cap_without_service = FakeL2cap(send_cb);
  auto server = std::make_unique<FakeSignalingServer>();
  server->RegisterWithL2cap(&fake_l2cap_without_service);
  l2cap::ChannelId src_id = l2cap::kFirstDynamicChannelId;

  // Assemble and send the ConnectionRequest to connect, but not open, the channel.
  auto connection_acl_packet =
      l2cap::testing::AclConnectionReq(kCommandId, kConnectionHandle, src_id, kPsm);
  const auto& connection_header = connection_acl_packet.As<hci::ACLDataHeader>();
  auto connection_header_len = sizeof(connection_header);
  auto connection_payload_len = le16toh(connection_header.data_total_length);
  auto connection_packet = DynamicByteBuffer(connection_payload_len);
  connection_acl_packet.Copy(&connection_packet, connection_header_len, connection_payload_len);
  fake_l2cap_without_service.HandlePdu(kConnectionHandle, connection_packet);

  // Anticipate that we will receive a rejection as the packet is not supported.
  // As this is an isolated test case, assume that src_id and dst_id are the same.
  auto expected_acl_response = l2cap::testing::AclConnectionRsp(
      kCommandId, kConnectionHandle, src_id, l2cap::kInvalidChannelId,
      l2cap::ConnectionResult::kPSMNotSupported);
  auto expected_response =
      expected_acl_response.view(sizeof(hci::ACLDataHeader) + sizeof(l2cap::CommandHeader));
  EXPECT_TRUE(ContainersEqual(expected_response, *received_packet));
  EXPECT_FALSE(fake_l2cap_without_service.FindDynamicChannelByLocalId(kConnectionHandle, src_id));
};

TEST(TESTING_FakeDynamicChannelTest, FailToRegisterChannelWithInvalidCid) {
  // Configure FakeSignalingServer to copy any received signaling packets.
  std::unique_ptr<ByteBuffer> received_packet;
  auto send_cb = [&received_packet](auto kConnectionHandle, auto cid, auto& buffer) {
    received_packet = std::make_unique<DynamicByteBuffer>(buffer);
  };
  auto fake_l2cap = FakeL2cap(send_cb);
  auto server = std::make_unique<FakeSignalingServer>();
  server->RegisterWithL2cap(&fake_l2cap);
  auto channel_cb = [](auto fake_dynamic_channel) {};
  fake_l2cap.RegisterService(kPsm, channel_cb);
  l2cap::ChannelId src_id = l2cap::kInvalidChannelId;

  // Assemble and send the ConnectionRequest to connect, but not open, the channel.
  auto connection_acl_packet =
      l2cap::testing::AclConnectionReq(kCommandId, kConnectionHandle, src_id, kPsm);
  const auto& connection_header = connection_acl_packet.As<hci::ACLDataHeader>();
  auto connection_header_len = sizeof(connection_header);
  auto connection_payload_len = le16toh(connection_header.data_total_length);
  auto connection_packet = DynamicByteBuffer(connection_payload_len);
  connection_acl_packet.Copy(&connection_packet, connection_header_len, connection_payload_len);
  fake_l2cap.HandlePdu(kConnectionHandle, connection_packet);

  // Anticipate that we will receive a rejection as the ID is not supported.
  auto expected_acl_response = l2cap::testing::AclConnectionRsp(
      kCommandId, kConnectionHandle, src_id, l2cap::kInvalidChannelId,
      l2cap::ConnectionResult::kInvalidSourceCID);
  auto expected_response =
      expected_acl_response.view(sizeof(hci::ACLDataHeader) + sizeof(l2cap::CommandHeader));
  EXPECT_TRUE(ContainersEqual(expected_response, *received_packet));
  EXPECT_FALSE(fake_l2cap.FindDynamicChannelByLocalId(kConnectionHandle, src_id));
};

TEST(TESTING_FakeDynamicChannelTest, FailToRegisterDuplicateRemoteId) {
  std::unique_ptr<ByteBuffer> received_packet;
  auto send_cb = [&received_packet](auto kConnectionHandle, auto cid, auto& buffer) {
    received_packet = std::make_unique<DynamicByteBuffer>(buffer);
  };
  auto fake_l2cap = FakeL2cap(send_cb);
  auto server = std::make_unique<FakeSignalingServer>();
  server->RegisterWithL2cap(&fake_l2cap);
  auto channel_cb = [](auto fake_dynamic_channel) {};
  fake_l2cap.RegisterService(kPsm, channel_cb);
  l2cap::ChannelId src_id = l2cap::kFirstDynamicChannelId;
  l2cap::ChannelParameters params;

  // Assemble and send the ConnectionRequest to connect, but not open, the channel.
  auto connection_acl_packet =
      l2cap::testing::AclConnectionReq(kCommandId, kConnectionHandle, src_id, kPsm);
  const auto& connection_header = connection_acl_packet.As<hci::ACLDataHeader>();
  auto connection_header_len = sizeof(connection_header);
  auto connection_payload_len = le16toh(connection_header.data_total_length);
  auto connection_packet = DynamicByteBuffer(connection_payload_len);
  connection_acl_packet.Copy(&connection_packet, connection_header_len, connection_payload_len);
  fake_l2cap.HandlePdu(kConnectionHandle, connection_packet);

  // Anticipate that we then receive a ConfigurationRequest. HandlePdu will
  // first send a ConnectionResponse, but the most recent packet should be a
  // ConfigurationRequest. The channel should also be connected, but not open,
  // at this time.
  // Manually create the expected ConfigurationRequest with no payload.
  StaticByteBuffer expected_request(
      // Configuration request command code, CommandId associated with the test
      l2cap::kConfigurationRequest, kCommandId,
      // Payload length (4 total bytes)
      0x04, 0x00,
      // Source ID (2 bytes)
      LowerBits(src_id), UpperBits(src_id),
      // No continuation flags (2 bytes)
      0x00, 0x00);
  EXPECT_TRUE(ContainersEqual(expected_request, *received_packet));
  EXPECT_FALSE(fake_l2cap.FindDynamicChannelByLocalId(kConnectionHandle, src_id)
                   ->configuration_request_received());
  EXPECT_FALSE(fake_l2cap.FindDynamicChannelByLocalId(kConnectionHandle, src_id)
                   ->configuration_response_received());
  EXPECT_FALSE(fake_l2cap.FindDynamicChannelByLocalId(kConnectionHandle, src_id)->opened());

  // Send a ConfigurationResponse to the received ConfigurationRequest.
  auto configuration_response_acl_packet =
      l2cap::testing::AclConfigRsp(kCommandId, kConnectionHandle, src_id, params);
  const auto& configuration_response_header =
      configuration_response_acl_packet.As<hci::ACLDataHeader>();
  auto configuration_response_header_len = sizeof(configuration_response_header);
  auto configuration_response_payload_len =
      le16toh(configuration_response_header.data_total_length);
  auto configuration_response_packet = DynamicByteBuffer(configuration_response_payload_len);
  configuration_response_acl_packet.Copy(&configuration_response_packet,
                                         configuration_response_header_len,
                                         configuration_response_payload_len);
  fake_l2cap.HandlePdu(kConnectionHandle, configuration_response_packet);
  EXPECT_FALSE(fake_l2cap.FindDynamicChannelByLocalId(kConnectionHandle, src_id)
                   ->configuration_request_received());
  EXPECT_TRUE(fake_l2cap.FindDynamicChannelByLocalId(kConnectionHandle, src_id)
                  ->configuration_response_received());
  EXPECT_FALSE(fake_l2cap.FindDynamicChannelByLocalId(kConnectionHandle, src_id)->opened());

  // Assemble and send the ConfigurationRequest to open up the channel.
  // In this isolated test, we can assume that the src_id and dest_id are identical.
  auto configuration_request_acl_packet =
      l2cap::testing::AclConfigReq(kCommandId, kConnectionHandle, src_id, params);
  const auto& configuration_request_header =
      configuration_request_acl_packet.As<hci::ACLDataHeader>();
  auto configuration_request_header_len = sizeof(configuration_request_header);
  auto configuration_request_payload_len = le16toh(configuration_request_header.data_total_length);
  auto configuration_request_packet = DynamicByteBuffer(configuration_request_payload_len);
  configuration_request_acl_packet.Copy(&configuration_request_packet,
                                        configuration_request_header_len,
                                        configuration_request_payload_len);
  fake_l2cap.HandlePdu(kConnectionHandle, configuration_request_packet);

  // Anticipate that we then receive a ConfigurationResponse after we send a
  // Manually create the expected ConfigurationRequest with no payload.
  StaticByteBuffer expected_response(
      // Configuration request command code, CommandId associated with the test
      l2cap::kConfigurationResponse, kCommandId,
      // Payload length (6 total bytes)
      0x06, 0x00,
      // Source ID (2 bytes)
      LowerBits(src_id), UpperBits(src_id),
      // No continuation flags (2 bytes)
      0x00, 0x00,
      // Result (Success)
      LowerBits(0x0000), UpperBits(0x0000));
  EXPECT_TRUE(ContainersEqual(expected_response, *received_packet));
  EXPECT_TRUE(fake_l2cap.FindDynamicChannelByLocalId(kConnectionHandle, src_id)
                  ->configuration_request_received());
  EXPECT_TRUE(fake_l2cap.FindDynamicChannelByLocalId(kConnectionHandle, src_id)
                  ->configuration_response_received());
  EXPECT_TRUE(fake_l2cap.FindDynamicChannelByLocalId(kConnectionHandle, src_id)->opened());

  // Try to open up the same channel again.
  auto second_connection_acl_packet =
      l2cap::testing::AclConnectionReq(kCommandId, kConnectionHandle, src_id, kPsm);
  const auto& second_connection_header = second_connection_acl_packet.As<hci::ACLDataHeader>();
  auto second_connection_header_len = sizeof(second_connection_header);
  auto second_connection_payload_len = le16toh(second_connection_header.data_total_length);
  auto second_connection_packet = DynamicByteBuffer(second_connection_payload_len);
  second_connection_acl_packet.Copy(&second_connection_packet, second_connection_header_len,
                                    second_connection_payload_len);
  fake_l2cap.HandlePdu(kConnectionHandle, second_connection_packet);

  // Anticipate that we will receive a rejection as the remote ID has already been registered.
  auto second_expected_acl_response = l2cap::testing::AclConnectionRsp(
      kCommandId, kConnectionHandle, src_id, l2cap::kInvalidChannelId,
      l2cap::ConnectionResult::kSourceCIDAlreadyAllocated);
  auto second_expected_response =
      second_expected_acl_response.view(sizeof(hci::ACLDataHeader) + sizeof(l2cap::CommandHeader));
  EXPECT_TRUE(ContainersEqual(second_expected_response, *received_packet));
};

TEST(TESTING_FakeDynamicChannelTest, FailWhenOutOfIds) {
  auto unexpected_cb = [](auto handle, auto& pdu) {};
  std::unique_ptr<ByteBuffer> received_packet;
  auto send_cb = [&received_packet](auto kConnectionHandle, auto cid, auto& buffer) {
    received_packet = std::make_unique<DynamicByteBuffer>(buffer);
  };
  auto fewer_ids_fake_l2cap_ = FakeL2cap(send_cb, unexpected_cb, l2cap::kFirstDynamicChannelId);
  auto server = std::make_unique<FakeSignalingServer>();
  server->RegisterWithL2cap(&fewer_ids_fake_l2cap_);
  auto channel_cb = [](auto fake_dynamic_channel) {};
  fewer_ids_fake_l2cap_.RegisterService(kPsm, channel_cb);
  l2cap::ChannelId src_id = l2cap::kFirstDynamicChannelId;

  // Assemble and send the ConnectionRequest to connect, but not open, the channel.
  auto connection_acl_packet =
      l2cap::testing::AclConnectionReq(kCommandId, kConnectionHandle, src_id, kPsm);
  const auto& connection_header = connection_acl_packet.As<hci::ACLDataHeader>();
  auto connection_header_len = sizeof(connection_header);
  auto connection_payload_len = le16toh(connection_header.data_total_length);
  auto connection_packet = DynamicByteBuffer(connection_payload_len);
  connection_acl_packet.Copy(&connection_packet, connection_header_len, connection_payload_len);
  fewer_ids_fake_l2cap_.HandlePdu(kConnectionHandle, connection_packet);
  EXPECT_FALSE(
      fewer_ids_fake_l2cap_.FindDynamicChannelByLocalId(kConnectionHandle, src_id)->opened());

  // The FakeL2cap instance should now be out of ChannelIds to assign.
  l2cap::ChannelId second_src_id = l2cap::kFirstDynamicChannelId + 1;
  auto second_connection_acl_packet =
      l2cap::testing::AclConnectionReq(kCommandId, kConnectionHandle, second_src_id, kPsm);
  const auto& second_connection_header = second_connection_acl_packet.As<hci::ACLDataHeader>();
  auto second_connection_header_len = sizeof(second_connection_header);
  auto second_connection_payload_len = le16toh(second_connection_header.data_total_length);
  auto second_connection_packet = DynamicByteBuffer(second_connection_payload_len);
  second_connection_acl_packet.Copy(&second_connection_packet, second_connection_header_len,
                                    second_connection_payload_len);
  fewer_ids_fake_l2cap_.HandlePdu(kConnectionHandle, second_connection_packet);

  // Anticipate that we will receive a rejection as there are no Ids left.
  auto expected_acl_response = l2cap::testing::AclConnectionRsp(
      kCommandId, kConnectionHandle, second_src_id, l2cap::kInvalidChannelId,
      l2cap::ConnectionResult::kNoResources);
  auto expected_response =
      expected_acl_response.view(sizeof(hci::ACLDataHeader) + sizeof(l2cap::CommandHeader));
  EXPECT_TRUE(ContainersEqual(expected_response, *received_packet));
  EXPECT_FALSE(fewer_ids_fake_l2cap_.FindDynamicChannelByLocalId(kConnectionHandle, second_src_id));
};

}  // namespace
}  // namespace bt::testing
