// 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/hci.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
