// Copyright 2018 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 "garnet/drivers/bluetooth/lib/sdp/server.h"

#include "gtest/gtest.h"

#include "garnet/drivers/bluetooth/lib/common/test_helpers.h"
#include "garnet/drivers/bluetooth/lib/data/fake_domain.h"
#include "garnet/drivers/bluetooth/lib/l2cap/fake_channel.h"
#include "garnet/drivers/bluetooth/lib/l2cap/l2cap.h"
#include "garnet/drivers/bluetooth/lib/sdp/pdu.h"
#include "garnet/drivers/bluetooth/lib/sdp/status.h"
#include "garnet/drivers/bluetooth/lib/testing/fake_controller.h"
#include "garnet/drivers/bluetooth/lib/testing/fake_controller_test.h"

namespace btlib {
namespace sdp {
namespace {

using common::LowerBits;
using common::UpperBits;

using ::btlib::testing::FakeController;

using TestingBase = ::btlib::testing::FakeControllerTest<FakeController>;

constexpr hci::ConnectionHandle kTestHandle1 = 1;
constexpr hci::ConnectionHandle kTestHandle2 = 2;

void NopConnectCallback(zx::socket, hci::ConnectionHandle, const DataElement&) {
}

class SDP_ServerTest : public TestingBase {
 public:
  SDP_ServerTest() = default;
  ~SDP_ServerTest() = default;

 protected:
  void SetUp() override {
    l2cap_ = data::testing::FakeDomain::Create();
    l2cap_->set_channel_callback(
        [this](auto fake_chan) { channel_ = std::move(fake_chan); });
    l2cap_->Initialize();
    l2cap_->AddACLConnection(kTestHandle1, hci::Connection::Role::kSlave,
                             nullptr, nullptr, nullptr);
    l2cap_->AddACLConnection(kTestHandle2, hci::Connection::Role::kSlave,
                             nullptr, nullptr, nullptr);
    server_ = std::make_unique<Server>(l2cap_);
  }

  void TearDown() override {
    channel_ = nullptr;
    server_ = nullptr;
    l2cap_ = nullptr;
  }

  Server* server() const { return server_.get(); }

  fbl::RefPtr<data::testing::FakeDomain> l2cap() const { return l2cap_; }

  fbl::RefPtr<l2cap::testing::FakeChannel> fake_chan() const {
    return channel_;
  }

  bool Expect(const common::ByteBuffer& expected) {
    if (!fake_chan()) {
      bt_log(ERROR, "unittest", "no channel, failing!");
      return false;
    }

    bool success = false;
    auto cb = [&expected, &success, this](auto cb_packet) {
      success = common::ContainersEqual(expected, *cb_packet);
    };

    fake_chan()->SetSendCallback(cb, dispatcher());
    RunLoopUntilIdle();

    return success;
  }

  bool ReceiveAndExpect(const common::ByteBuffer& packet,
                        const common::ByteBuffer& expected_response) {
    if (!fake_chan()) {
      bt_log(ERROR, "unittest", "no channel, failing!");
      return false;
    }

    fake_chan()->Receive(packet);

    return Expect(expected_response);
  }

  ServiceHandle AddSPP(sdp::Server::ConnectCallback cb = NopConnectCallback) {
    ServiceRecord record;

    record.SetServiceClassUUIDs({profile::kSerialPort});
    record.AddProtocolDescriptor(ServiceRecord::kPrimaryProtocolList,
                                 protocol::kL2CAP, DataElement());
    record.AddProtocolDescriptor(ServiceRecord::kPrimaryProtocolList,
                                 protocol::kRFCOMM, DataElement(uint8_t(0)));
    record.AddProfile(profile::kSerialPort, 1, 2);
    record.AddInfo("en", "FAKE", "", "");
    ServiceHandle handle =
        server()->RegisterService(std::move(record), std::move(cb));
    EXPECT_TRUE(handle);
    return handle;
  }

  ServiceHandle AddA2DPSink(
      sdp::Server::ConnectCallback cb = NopConnectCallback) {
    ServiceRecord record;
    record.SetServiceClassUUIDs({profile::kAudioSink});
    record.AddProtocolDescriptor(ServiceRecord::kPrimaryProtocolList,
                                 protocol::kL2CAP, DataElement(l2cap::kAVDTP));
    record.AddProtocolDescriptor(ServiceRecord::kPrimaryProtocolList,
                                 protocol::kAVDTP,
                                 DataElement(uint16_t(0x0103)));  // Version
    record.AddProfile(profile::kAdvancedAudioDistribution, 1, 3);
    record.SetAttribute(kA2DP_SupportedFeatures,
                        DataElement(uint16_t(0x0001)));  // Headphones
    ServiceHandle handle =
        server()->RegisterService(std::move(record), std::move(cb));
    EXPECT_TRUE(handle);
    return handle;
  }

 private:
  fbl::RefPtr<l2cap::testing::FakeChannel> channel_;
  fbl::RefPtr<data::testing::FakeDomain> l2cap_;
  std::unique_ptr<Server> server_;
};

constexpr l2cap::ChannelId kSdpChannel = 0x0041;

#define SDP_ERROR_RSP(t_id, code)                                              \
  common::CreateStaticByteBuffer(0x01, UpperBits(t_id), LowerBits(t_id), 0x00, \
                                 0x02, UpperBits(uint16_t(code)),              \
                                 LowerBits(uint16_t(code)));

// Test:
//  - Accepts channels and holds channel open correctly.
//  - Packets that are the wrong length are responded to with kInvalidSize
//  - Answers with the same TransactionID as sent
TEST_F(SDP_ServerTest, BasicError) {
  l2cap()->TriggerInboundL2capChannel(kTestHandle1, l2cap::kSDP, kSdpChannel,
                                      0x0bad);
  RunLoopUntilIdle();
  ASSERT_TRUE(fake_chan());
  EXPECT_TRUE(fake_chan()->activated());

  const auto kRspErrSize = SDP_ERROR_RSP(0x1001, ErrorCode::kInvalidSize);

  const auto kTooSmall =
      common::CreateStaticByteBuffer(0x01,        // SDP_ServiceSearchRequest
                                     0x10, 0x01,  // Transaction ID (0x1001)
                                     0x00, 0x09   // Parameter length (9 bytes)
      );

  const auto kRspTooSmall = SDP_ERROR_RSP(0x1001, ErrorCode::kInvalidSize);

  const auto kTooBig =
      common::CreateStaticByteBuffer(0x01,        // SDP_ServiceSearchRequest
                                     0x20, 0x10,  // Transaction ID (0x2010)
                                     0x00, 0x02,  // Parameter length (2 bytes)
                                     0x01, 0x02, 0x03  // 3 bytes of parameters
      );

  const auto kRspTooBig = SDP_ERROR_RSP(0x2010, ErrorCode::kInvalidSize);

  EXPECT_TRUE(ReceiveAndExpect(kTooSmall, kRspTooSmall));
  EXPECT_TRUE(ReceiveAndExpect(kTooBig, kRspTooBig));

  const auto kRspInvalidSyntax =
      SDP_ERROR_RSP(0x2010, ErrorCode::kInvalidRequestSyntax);

  // Responses aren't valid requests
  EXPECT_TRUE(ReceiveAndExpect(kRspTooBig, kRspInvalidSyntax));
}

// Test:
//  - Passes an initialized ServiceRecord that has a matching SericeHandle
//  - Doesn't add a service that doesn't contain a ServiceClassIDList
//  - Adds a service that is valid.
//  - Services can be Unregistered.
TEST_F(SDP_ServerTest, RegisterService) {
  EXPECT_FALSE(server()->RegisterService(ServiceRecord(), {}));

  ServiceRecord record;
  record.SetAttribute(kServiceClassIdList, DataElement(uint16_t(42)));
  EXPECT_FALSE(server()->RegisterService(std::move(record), {}));

  ServiceRecord has_handle;
  has_handle.SetHandle(42);
  EXPECT_FALSE(server()->RegisterService(std::move(has_handle), {}));

  ServiceRecord valid;
  valid.SetServiceClassUUIDs({profile::kAVRemoteControl});
  ServiceHandle handle = server()->RegisterService(std::move(valid), {});

  EXPECT_TRUE(handle);

  EXPECT_TRUE(server()->UnregisterService(handle));
  EXPECT_FALSE(server()->UnregisterService(handle));
}

TEST_F(SDP_ServerTest, PSMVerification) {
  ServiceRecord no_psm;
  no_psm.SetServiceClassUUIDs({profile::kAVRemoteControl});
  no_psm.AddProtocolDescriptor(ServiceRecord::kPrimaryProtocolList,
                               protocol::kL2CAP, DataElement());

  EXPECT_FALSE(server()->RegisterService(std::move(no_psm), {}));

  ServiceRecord psm_wrong_argtype;
  psm_wrong_argtype.SetServiceClassUUIDs({profile::kAVRemoteControl});
  psm_wrong_argtype.AddProtocolDescriptor(ServiceRecord::kPrimaryProtocolList,
                                          protocol::kL2CAP,
                                          DataElement(bool(true)));

  EXPECT_FALSE(server()->RegisterService(std::move(psm_wrong_argtype), {}));

  ServiceRecord psm_rfcomm;
  psm_rfcomm.SetServiceClassUUIDs({profile::kAVRemoteControl});
  psm_rfcomm.AddProtocolDescriptor(ServiceRecord::kPrimaryProtocolList,
                                   protocol::kL2CAP, DataElement());
  // Don't need an argument for RFCOMM, it will be auto-assigned.
  psm_rfcomm.AddProtocolDescriptor(ServiceRecord::kPrimaryProtocolList,
                                   protocol::kRFCOMM, DataElement());

  EXPECT_TRUE(
      server()->RegisterService(std::move(psm_rfcomm), NopConnectCallback));

  // Another RFCOMM is also fine.
  ServiceRecord psm_rfcomm2;
  psm_rfcomm2.SetServiceClassUUIDs({profile::kAVRemoteControl});
  psm_rfcomm2.AddProtocolDescriptor(ServiceRecord::kPrimaryProtocolList,
                                    protocol::kL2CAP, DataElement());
  // Don't need an argument for RFCOMM, it will be auto-assigned.
  psm_rfcomm2.AddProtocolDescriptor(ServiceRecord::kPrimaryProtocolList,
                                    protocol::kRFCOMM, DataElement());

  EXPECT_TRUE(
      server()->RegisterService(std::move(psm_rfcomm2), NopConnectCallback));

  ServiceRecord psm_ok;
  psm_ok.SetServiceClassUUIDs({profile::kAVRemoteControl});
  psm_ok.AddProtocolDescriptor(ServiceRecord::kPrimaryProtocolList,
                               protocol::kL2CAP, DataElement(uint16_t(500)));

  auto handle =
      server()->RegisterService(std::move(psm_ok), NopConnectCallback);
  EXPECT_TRUE(handle);

  ServiceRecord psm_duplicate;
  psm_duplicate.SetServiceClassUUIDs({profile::kAVRemoteControl});
  psm_duplicate.AddProtocolDescriptor(ServiceRecord::kPrimaryProtocolList,
                                      protocol::kL2CAP,
                                      DataElement(uint16_t(500)));

  EXPECT_FALSE(
      server()->RegisterService(std::move(psm_duplicate), NopConnectCallback));

  // Unregistering allows us to re-register with PSM.
  server()->UnregisterService(handle);
  ServiceRecord psm_readd;
  psm_readd.SetServiceClassUUIDs({profile::kAVRemoteControl});
  psm_readd.AddProtocolDescriptor(ServiceRecord::kPrimaryProtocolList,
                                  protocol::kL2CAP, DataElement(uint16_t(500)));

  EXPECT_TRUE(
      server()->RegisterService(std::move(psm_readd), NopConnectCallback));

  // TODO(NET-1417): test that new connections to the PSM get delivered once
  // they are deliverable
}

#define UINT32_AS_BE_BYTES(x)                                    \
  UpperBits(x >> 16), LowerBits(x >> 16), UpperBits(x & 0xFFFF), \
      LowerBits(x & 0xFFFF)

// Test ServiceSearchRequest:
//  - returns services with the UUID included
//  - doesn't return services that don't have the UUID
//  - fails when there are no items or too many items in the search
//  - doesn't return more than the max requested
TEST_F(SDP_ServerTest, ServiceSearchRequest) {
  ServiceHandle spp_handle = AddSPP();
  ServiceHandle a2dp_handle = AddA2DPSink();

  l2cap()->TriggerInboundL2capChannel(kTestHandle1, l2cap::kSDP, kSdpChannel,
                                      0x0bad);
  RunLoopUntilIdle();

  const auto kL2capSearch = common::CreateStaticByteBuffer(
      0x02,        // SDP_ServiceSearchRequest
      0x10, 0x01,  // Transaction ID (0x1001)
      0x00, 0x08,  // Parameter length (8 bytes)
      // ServiceSearchPattern
      0x35, 0x03,        // Sequence uint8 3 bytes
      0x19, 0x01, 0x00,  // UUID: Protocol: L2CAP
      0xFF, 0xFF,        // MaximumServiceRecordCount: (none)
      0x00               // Contunuation State: none
  );

  ServiceSearchRequest search_req;
  EXPECT_FALSE(search_req.valid());
  EXPECT_EQ(nullptr, search_req.GetPDU(0x1001));

  search_req.set_search_pattern({protocol::kL2CAP});

  auto pdu = search_req.GetPDU(0x1001);
  EXPECT_NE(nullptr, pdu);

  EXPECT_TRUE(ContainersEqual(kL2capSearch, *pdu));

  const auto kL2capSearchResponse = common::CreateStaticByteBuffer(
      0x03,                            // SDP_ServicesearchResponse
      0x10, 0x01,                      // Transaction ID (0x1001)
      0x00, 0x0D,                      // Parameter length (13 bytes)
      0x00, 0x02,                      // Total service record count: 2
      0x00, 0x02,                      // Current service record count: 2
      UINT32_AS_BE_BYTES(spp_handle),  // This list isn't specifically ordered
      UINT32_AS_BE_BYTES(a2dp_handle),
      0x00  // No continuation state
  );

  bool recv = false;
  std::vector<ServiceHandle> handles;
  TransactionId tid;
  auto cb = [&recv, &handles, &tid](auto cb_packet) {
    EXPECT_LE(sizeof(Header), cb_packet->size());
    common::PacketView<Header> packet(cb_packet.get());
    EXPECT_EQ(kServiceSearchResponse, packet.header().pdu_id);
    tid = betoh16(packet.header().tid);
    uint16_t len = betoh16(packet.header().param_length);
    bt_log(SPEW, "unittest", "resize packet to %d", len);
    packet.Resize(len);
    ServiceSearchResponse resp;
    auto status = resp.Parse(packet.payload_data());
    EXPECT_TRUE(status);
    handles = resp.service_record_handle_list();
    recv = true;
  };

  fake_chan()->SetSendCallback(cb, dispatcher());
  fake_chan()->Receive(kL2capSearch);
  RunLoopUntilIdle();

  EXPECT_TRUE(recv);
  EXPECT_EQ(0x1001, tid);
  EXPECT_EQ(2u, handles.size());
  EXPECT_NE(handles.end(),
            std::find(handles.begin(), handles.end(), spp_handle));
  EXPECT_NE(handles.end(),
            std::find(handles.begin(), handles.end(), a2dp_handle));

  const auto kInvalidNoItems = common::CreateStaticByteBuffer(
      0x02,        // SDP_ServiceSearchRequest
      0x10, 0xA1,  // Transaction ID (0x10A1)
      0x00, 0x05,  // Parameter length (5 bytes)
      // ServiceSearchPattern
      0x35, 0x00,  // Sequence uint8 0 bytes
      0xFF, 0xFF,  // MaximumServiceRecordCount: (none)
      0x00         // Contunuation State: none
  );

  const auto kRspErrSyntax =
      SDP_ERROR_RSP(0x10A1, ErrorCode::kInvalidRequestSyntax);

  EXPECT_TRUE(ReceiveAndExpect(kInvalidNoItems, kRspErrSyntax));

  const auto kInvalidTooManyItems = common::CreateStaticByteBuffer(
      0x02,        // SDP_ServiceSearchRequest
      0x10, 0xA1,  // Transaction ID (0x10B1)
      0x00, 0x2C,  // Parameter length (44 bytes)
      // ServiceSearchPattern
      0x35, 0x27,        // Sequence uint8 27 bytes
      0x19, 0x30, 0x01,  // 13 UUIDs in the search
      0x19, 0x30, 0x02, 0x19, 0x30, 0x03, 0x19, 0x30, 0x04, 0x19, 0x30, 0x05,
      0x19, 0x30, 0x06, 0x19, 0x30, 0x07, 0x19, 0x30, 0x08, 0x19, 0x30, 0x09,
      0x19, 0x30, 0x10, 0x19, 0x30, 0x11, 0x19, 0x30, 0x12, 0x19, 0x30, 0x13,
      0xFF, 0xFF,  // MaximumServiceRecordCount: (none)
      0x00         // Contunuation State: none
  );

  EXPECT_TRUE(ReceiveAndExpect(kInvalidTooManyItems, kRspErrSyntax));
}

// Test ServiceSearchRequest:
//  - doesn't return more than the max requested
TEST_F(SDP_ServerTest, ServiceSearchRequestOneOfMany) {
  l2cap()->TriggerInboundL2capChannel(kTestHandle1, l2cap::kSDP, kSdpChannel,
                                      0x0bad);
  RunLoopUntilIdle();

  ServiceHandle spp_handle = AddSPP();
  ServiceHandle a2dp_handle = AddA2DPSink();

  bool recv = false;
  std::vector<ServiceHandle> handles;
  TransactionId tid;
  auto cb = [&recv, &handles, &tid](auto cb_packet) {
    EXPECT_LE(sizeof(Header), cb_packet->size());
    common::PacketView<Header> packet(cb_packet.get());
    EXPECT_EQ(kServiceSearchResponse, packet.header().pdu_id);
    tid = betoh16(packet.header().tid);
    uint16_t len = betoh16(packet.header().param_length);
    bt_log(SPEW, "unittests", "resizing packet to %d", len);
    packet.Resize(len);
    ServiceSearchResponse resp;
    auto status = resp.Parse(packet.payload_data());
    EXPECT_TRUE(status);
    handles = resp.service_record_handle_list();
    recv = true;
  };

  const auto kL2capSearchOne = common::CreateStaticByteBuffer(
      0x02,        // SDP_ServiceSearchRequest
      0x10, 0xC1,  // Transaction ID (0x10C1)
      0x00, 0x08,  // Parameter length (8 bytes)
      // ServiceSearchPattern
      0x35, 0x03,        // Sequence uint8 3 bytes
      0x19, 0x01, 0x00,  // UUID: Protocol: L2CAP
      0x00, 0x01,        // MaximumServiceRecordCount: 1
      0x00               // Contunuation State: none
  );

  handles.clear();
  recv = false;

  fake_chan()->SetSendCallback(cb, dispatcher());
  fake_chan()->Receive(kL2capSearchOne);
  RunLoopUntilIdle();

  EXPECT_TRUE(recv);
  EXPECT_EQ(0x10C1, tid);
  EXPECT_EQ(1u, handles.size());
  bool found_spp =
      std::find(handles.begin(), handles.end(), spp_handle) != handles.end();
  bool found_a2dp =
      std::find(handles.begin(), handles.end(), a2dp_handle) != handles.end();
  EXPECT_TRUE(found_spp || found_a2dp);
}

// Test:
//  - Answers ServiceAttributeRequest correctly
//  - Continuation state is generated correctly re:
//    MaximumAttributeListByteCount
//  - Valid Continuation state continues response
TEST_F(SDP_ServerTest, ServiceAttributeRequest) {
  ServiceRecord record;
  record.SetServiceClassUUIDs({profile::kAVRemoteControl});
  record.SetAttribute(0xf00d, DataElement(uint32_t(0xfeedbeef)));
  record.SetAttribute(0xf000, DataElement(uint32_t(0x01234567)));

  ServiceHandle handle = server()->RegisterService(std::move(record), {});

  EXPECT_TRUE(handle);

  l2cap()->TriggerInboundL2capChannel(kTestHandle1, l2cap::kSDP, kSdpChannel,
                                      0x0bad);
  RunLoopUntilIdle();

  const auto kRequestAttr = common::CreateStaticByteBuffer(
      0x04,                        // SDP_ServiceAttritbuteRequest
      0x10, 0x01,                  // Transaction ID (0x1001)
      0x00, 0x11,                  // Parameter length (17 bytes)
      UINT32_AS_BE_BYTES(handle),  // ServiceRecordHandle
      0x00, 0x0A,                  // MaximumAttributeByteCount (10 bytes max)
      // AttributeIDList
      0x35, 0x08,  // Sequence uint8 8 bytes
      0x09,        // uint16_t, single attribute
      0x00, 0x01,  // ServiceClassIDList
      0x0A,        // uint32_t, which is a range (0x3000 - 0xf000)
      0x30, 0x00,  // low end of range
      0xf0, 0x00,  // high end of range
      0x00         // Contunuation State: none
  );

  size_t received = 0;

  ServiceAttributeResponse rsp;

  auto send_cb = [this, handle, &rsp, &received](auto cb_packet) {
    EXPECT_LE(sizeof(Header), cb_packet->size());
    common::PacketView<sdp::Header> packet(cb_packet.get());
    ASSERT_EQ(0x05, packet.header().pdu_id);
    uint16_t len = betoh16(packet.header().param_length);
    EXPECT_LE(len, 0x11);  // 10 + 2 (byte count) + 5 (cont state)
    packet.Resize(len);
    Status st = rsp.Parse(packet.payload_data());
    if (received == 0) {
      // Server should have split this into more than one response.
      EXPECT_FALSE(st);
      EXPECT_EQ(common::HostError::kInProgress, st.error());
      EXPECT_FALSE(rsp.complete());
    }
    received++;
    if (!st && (st.error() != common::HostError::kInProgress)) {
      // This isn't a valid packet and we shouldn't try to get
      // a continuation.
      return;
    }
    if (!rsp.complete()) {
      // Repeat the request with the continuation state if it was returned.
      auto continuation = rsp.ContinuationState();
      uint8_t cont_size = continuation.size();
      EXPECT_NE(0u, cont_size);
      // Make another request with the continutation data.
      size_t param_size = 17 + cont_size;
      auto kContinuedRequestAttrStart = common::CreateStaticByteBuffer(
          0x04,  // SDP_ServiceAttributeRequest
          0x10, static_cast<uint8_t>(received + 1), UpperBits(param_size),
          LowerBits(param_size),       // Parameter length
          UINT32_AS_BE_BYTES(handle),  // ServiceRecordHandle
          0x00, 0x0A,  // MaximumAttributeByteCount (10 bytes max)
          // AttributeIDList
          0x35, 0x08,  // Sequence uint8 8 bytes
          0x09,        // uint16_t, single attribute
          0x00, 0x01,  // ServiceClassIDList
          0x0A,        // uint32_t, which is a range (0x3000 - 0xf000)
          0x30, 0x00,  // low end of range
          0xf0, 0x00   // high end of range
      );
      common::DynamicByteBuffer req(kContinuedRequestAttrStart.size() +
                                    sizeof(uint8_t) + cont_size);

      kContinuedRequestAttrStart.Copy(&req);
      req.Write(&cont_size, sizeof(uint8_t), kContinuedRequestAttrStart.size());
      req.Write(continuation,
                kContinuedRequestAttrStart.size() + sizeof(uint8_t));

      fake_chan()->Receive(req);
    }
  };

  fake_chan()->SetSendCallback(send_cb, dispatcher());
  fake_chan()->Receive(kRequestAttr);
  RunLoopUntilIdle();

  EXPECT_GE(received, 1u);
  const auto& attrs = rsp.attributes();
  EXPECT_EQ(2u, attrs.size());
  EXPECT_NE(attrs.end(), attrs.find(kServiceClassIdList));
  EXPECT_NE(attrs.end(), attrs.find(0xf000));

  const auto kInvalidRangeOrder = common::CreateStaticByteBuffer(
      0x04,                        // SDP_ServiceAttritbuteRequest
      0xE0, 0x01,                  // Transaction ID (0xE001)
      0x00, 0x11,                  // Parameter length (17 bytes)
      UINT32_AS_BE_BYTES(handle),  // ServiceRecordHandle
      0x00, 0x0A,                  // MaximumAttributeByteCount (10 bytes max)
      // AttributeIDList
      0x35, 0x08,  // Sequence uint8 8 bytes
      0x09,        // uint16_t, single attribute
      0x00, 0x01,  // ServiceClassIDList
      0x0A,        // uint32_t, which is a range (0x3000 - 0xf000)
      0xf0, 0x00,  // low end of range
      0x30, 0x00,  // high end of range
      0x00         // Contunuation State: none
  );

  const auto kRspErrSyntax =
      SDP_ERROR_RSP(0xE001, ErrorCode::kInvalidRequestSyntax);

  EXPECT_TRUE(ReceiveAndExpect(kInvalidRangeOrder, kRspErrSyntax));

  const auto kInvalidMaxBytes = common::CreateStaticByteBuffer(
      0x04,                        // SDP_ServiceAttritbuteRequest
      0xE0, 0x02,                  // Transaction ID (0xE001)
      0x00, 0x0C,                  // Parameter length (12 bytes)
      UINT32_AS_BE_BYTES(handle),  // ServiceRecordHandle
      0x00, 0x05,                  // MaximumAttributeByteCount (5 bytes max)
      // AttributeIDList
      0x35, 0x03,  // Sequence uint8 3 bytes
      0x09,        // uint16_t, single attribute
      0x00, 0x01,  // ServiceClassIDList
      0x00         // Contunuation State: none
  );

  const auto kRspErrSyntax2 =
      SDP_ERROR_RSP(0xE002, ErrorCode::kInvalidRequestSyntax);

  EXPECT_TRUE(ReceiveAndExpect(kInvalidMaxBytes, kRspErrSyntax2));
}

// Test:
//  - Answers ServiceSearchAttributeRequest correctly
//  - Continuation state is generated correctly re:
//    MaximumAttributeListsByteCount
//  - Valid Continuation state continues response
TEST_F(SDP_ServerTest, SearchAttributeRequest) {
  ServiceRecord record1;
  record1.SetServiceClassUUIDs({profile::kAVRemoteControl});
  record1.AddProtocolDescriptor(ServiceRecord::kPrimaryProtocolList,
                                protocol::kL2CAP, DataElement(uint16_t(500)));
  record1.SetAttribute(0xf00d, DataElement(uint32_t(0xfeedbeef)));
  record1.SetAttribute(0xf000, DataElement(uint32_t(0x01234567)));

  ServiceHandle handle1 =
      server()->RegisterService(std::move(record1), NopConnectCallback);

  EXPECT_TRUE(handle1);

  ServiceRecord record2;
  record2.SetServiceClassUUIDs({profile::kAVRemoteControl});
  record2.AddProtocolDescriptor(ServiceRecord::kPrimaryProtocolList,
                                protocol::kL2CAP, DataElement(uint16_t(501)));
  ServiceHandle handle2 =
      server()->RegisterService(std::move(record2), NopConnectCallback);

  EXPECT_TRUE(handle2);

  l2cap()->TriggerInboundL2capChannel(kTestHandle1, l2cap::kSDP, kSdpChannel,
                                      0x0bad);
  RunLoopUntilIdle();

  const auto kRequestAttr = common::CreateStaticByteBuffer(
      0x06,        // SDP_ServiceAttritbuteRequest
      0x10, 0x01,  // Transaction ID (0x1001)
      0x00, 0x12,  // Parameter length (18 bytes)
      // ServiceSearchPattern
      0x35, 0x03,        // Sequence uint8 3 bytes
      0x19, 0x01, 0x00,  // UUID: Protocol: L2CAP
      0x00, 0x0A,        // MaximumAttributeByteCount (10 bytes max)
      // AttributeIDList
      0x35, 0x08,  // Sequence uint8 8 bytes
      0x09,        // uint16_t, single attribute
      0x00, 0x00,  // ServiceRecordHandle
      0x0A,        // uint32_t, which is a range (0x3000 - 0xf000)
      0x30, 0x00,  // low end of range
      0xf0, 0x00,  // high end of range
      0x00         // Contunuation State: none
  );

  size_t received = 0;

  ServiceSearchAttributeResponse rsp;

  auto send_cb = [this, &rsp, &received](auto cb_packet) {
    EXPECT_LE(sizeof(Header), cb_packet->size());
    common::PacketView<sdp::Header> packet(cb_packet.get());
    ASSERT_EQ(0x07, packet.header().pdu_id);
    uint16_t len = betoh16(packet.header().param_length);
    EXPECT_LE(len, 0x11);  // 2 (byte count) + 10 (max len) + 5 (cont state)
    packet.Resize(len);
    Status st = rsp.Parse(packet.payload_data());
    if (received == 0) {
      // Server should have split this into more than one response.
      EXPECT_FALSE(st);
      EXPECT_EQ(common::HostError::kInProgress, st.error());
      EXPECT_FALSE(rsp.complete());
    }
    received++;
    if (!st && (st.error() != common::HostError::kInProgress)) {
      // This isn't a valid packet and we shouldn't try to get
      // a continuation.
      return;
    }
    if (!rsp.complete()) {
      // Repeat the request with the continuation state if it was returned.
      auto continuation = rsp.ContinuationState();
      uint8_t cont_size = continuation.size();
      EXPECT_NE(0u, cont_size);
      // Make another request with the continutation data.
      size_t param_size = 18 + cont_size;
      auto kContinuedRequestAttrStart = common::CreateStaticByteBuffer(
          0x06,  // SDP_ServiceAttributeRequest
          0x10, static_cast<uint8_t>(received + 1),      // Transaction ID
          UpperBits(param_size), LowerBits(param_size),  // Parameter length
          0x35, 0x03,        // Sequence uint8 3 bytes
          0x19, 0x01, 0x00,  // SearchPattern: L2CAP
          0x00, 0x0A,        // MaximumAttributeByteCount (10 bytes max)
          // AttributeIDList
          0x35, 0x08,  // Sequence uint8 8 bytes
          0x09,        // uint16_t, single attribute
          0x00, 0x00,  // ServiceRecordHandle
          0x0A,        // uint32_t, which is a range (0x3000 - 0xf000)
          0x30, 0x00,  // low end of range
          0xf0, 0x00   // high end of range
      );
      common::DynamicByteBuffer req(kContinuedRequestAttrStart.size() +
                                    sizeof(uint8_t) + cont_size);

      kContinuedRequestAttrStart.Copy(&req);
      req.Write(&cont_size, sizeof(uint8_t), kContinuedRequestAttrStart.size());
      req.Write(continuation,
                kContinuedRequestAttrStart.size() + sizeof(uint8_t));

      fake_chan()->Receive(req);
    }
  };

  fake_chan()->SetSendCallback(send_cb, dispatcher());
  fake_chan()->Receive(kRequestAttr);
  RunLoopUntilIdle();

  EXPECT_GE(received, 1u);
  // We should receive both of our entered records.
  EXPECT_EQ(2u, rsp.num_attribute_lists());
  for (size_t i = 0; i < rsp.num_attribute_lists(); i++) {
    const auto& attrs = rsp.attributes(i);
    // Every service has a record handle
    auto handle_it = attrs.find(kServiceRecordHandle);
    EXPECT_NE(attrs.end(), handle_it);
    ServiceHandle received_handle = *handle_it->second.Get<uint32_t>();
    if (received_handle == handle1) {
      // The first service also has another attribute we should find.
      EXPECT_EQ(2u, attrs.size());
      EXPECT_NE(attrs.end(), attrs.find(0xf000));
    }
  }

  const auto kInvalidRangeOrder = common::CreateStaticByteBuffer(
      0x06,                          // SDP_ServiceAttritbuteRequest
      0xE0, 0x01,                    // Transaction ID (0xE001)
      0x00, 0x12,                    // Parameter length (18 bytes)
      0x35, 0x03, 0x19, 0x01, 0x00,  // SearchPattern: L2CAP
      0x00, 0x0A,                    // MaximumAttributeByteCount (10 bytes max)
      // AttributeIDList
      0x35, 0x08,  // Sequence uint8 8 bytes
      0x09,        // uint16_t, single attribute
      0x00, 0x01,  // ServiceClassIDList
      0x0A,        // uint32_t, which is a range (0x3000 - 0xf000)
      0xf0, 0x00,  // low end of range
      0x30, 0x00,  // high end of range
      0x00         // Contunuation State: none
  );

  const auto kRspErrSyntax =
      SDP_ERROR_RSP(0xE001, ErrorCode::kInvalidRequestSyntax);

  EXPECT_TRUE(ReceiveAndExpect(kInvalidRangeOrder, kRspErrSyntax));

  const auto kInvalidMaxBytes = common::CreateStaticByteBuffer(
      0x04,                          // SDP_ServiceAttritbuteRequest
      0xE0, 0x02,                    // Transaction ID (0xE002)
      0x00, 0x0D,                    // Parameter length (13 bytes)
      0x35, 0x03, 0x19, 0x01, 0x00,  // SearchPattern: L2CAP
      0x00, 0x05,                    // MaximumAttributeByteCount (5 bytes max)
      // AttributeIDList
      0x35, 0x03,  // Sequence uint8 3 bytes
      0x09,        // uint16_t, single attribute
      0x00, 0x01,  // ServiceClassIDList
      0x00         // Contunuation State: none
  );

  const auto kRspErrSyntax2 =
      SDP_ERROR_RSP(0xE002, ErrorCode::kInvalidRequestSyntax);

  EXPECT_TRUE(ReceiveAndExpect(kInvalidMaxBytes, kRspErrSyntax2));
}

TEST_F(SDP_ServerTest, ConnectionCallbacks) {
  l2cap()->TriggerInboundL2capChannel(kTestHandle1, l2cap::kSDP, kSdpChannel,
                                      0x0bad);
  RunLoopUntilIdle();

  std::vector<zx::socket> socks;
  hci::ConnectionHandle latest_handle;

  // Register a service
  AddA2DPSink([&socks, &latest_handle](zx::socket incoming_sock, auto handle,
                                       const auto& protocol) {
    bt_log(SPEW, "test", "Got socket for the a2dp sink");
    socks.emplace_back(std::move(incoming_sock));
    latest_handle = handle;
  });

  // Connect to the service
  l2cap()->TriggerInboundL2capChannel(kTestHandle1, l2cap::kAVDTP,
                                      kSdpChannel + 1, 0x0b00);
  RunLoopUntilIdle();

  // It should get a callback with a socket
  EXPECT_EQ(1u, socks.size());
  EXPECT_EQ(kTestHandle1, latest_handle);

  // Connect to the same service again with the same PSM (on a different
  // connection, it should still work)
  l2cap()->TriggerInboundL2capChannel(kTestHandle2, l2cap::kAVDTP,
                                      kSdpChannel + 2, 0x0b01);
  RunLoopUntilIdle();

  ASSERT_EQ(2u, socks.size());
  EXPECT_EQ(kTestHandle2, latest_handle);
  EXPECT_NE(socks.front(), socks.back());
}

// Browse Group gets set correctly
TEST_F(SDP_ServerTest, BrowseGroup) {
  AddA2DPSink();

  l2cap()->TriggerInboundL2capChannel(kTestHandle1, l2cap::kSDP, kSdpChannel,
                                      0x0bad);
  RunLoopUntilIdle();

  const auto kRequestAttr = common::CreateStaticByteBuffer(
      0x06,        // SDP_ServiceAttritbuteRequest
      0x10, 0x01,  // Transaction ID (0x1001)
      0x00, 0x0D,  // Parameter length (12 bytes)
      // ServiceSearchPattern
      0x35, 0x03,        // Sequence uint8 3 bytes
      0x19, 0x01, 0x00,  // UUID: Protocol: L2CAP
      0xFF, 0xFF,        // MaximumAttributeByteCount (no max)
      // AttributeIDList
      0x35, 0x03,  // Sequence uint8 3 bytes
      0x09,        // uint16_t, single attribute
      0x00, 0x05,  // BrowseGroupList
      0x00         // Contunuation State: none
  );

  ServiceSearchAttributeResponse rsp;
  auto send_cb = [this, &rsp](auto cb_packet) {
    EXPECT_LE(sizeof(Header), cb_packet->size());
    common::PacketView<sdp::Header> packet(cb_packet.get());
    ASSERT_EQ(0x07, packet.header().pdu_id);
    uint16_t len = betoh16(packet.header().param_length);
    packet.Resize(len);
    auto status = rsp.Parse(packet.payload_data());
    EXPECT_TRUE(status);
  };

  fake_chan()->SetSendCallback(send_cb, dispatcher());
  fake_chan()->Receive(kRequestAttr);
  RunLoopUntilIdle();

  EXPECT_EQ(1u, rsp.num_attribute_lists());
  auto& attributes = rsp.attributes(0);
  auto group_attr_it = attributes.find(kBrowseGroupList);
  ASSERT_EQ(DataElement::Type::kSequence, group_attr_it->second.type());
  ASSERT_EQ(DataElement::Type::kUuid, group_attr_it->second.At(0)->type());
  EXPECT_NE(attributes.end(), group_attr_it);
  EXPECT_EQ(kPublicBrowseRootUuid,
            *group_attr_it->second.At(0)->Get<common::UUID>());
}

#undef SDP_ERROR_RSP
#undef UINT32_AS_LE_BYTES

}  // namespace
}  // namespace sdp
}  // namespace btlib
