Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3ee967bf authored by Chris Manton's avatar Chris Manton Committed by Myles Watson
Browse files

add legacy shim l2cap tests

Bug: 143697964
Test: out/host/linux-x86/nativetest64/bluetooth_test_legacy/bluetooth_test_legacy

Change-Id: I67166a5e0f7e6733bb695026d89ef226c4eae2c1
parent 6fd2c99b
Loading
Loading
Loading
Loading
+31 −0
Original line number Diff line number Diff line
@@ -123,6 +123,7 @@ cc_library_static {
        ":LibBluetoothSources",
        "shim/entry_for_test.cc",
    ],
    host_supported: true,
    include_dirs: [
        "packages/modules/Bluetooth/system",
        "packages/modules/Bluetooth/system/bta/include",
@@ -137,3 +138,33 @@ cc_library_static {
        "-DBUILDCFG",
    ],
}

filegroup {
    name: "BluetoothLegacyShimTestSources",
    srcs: [
        "shim/l2cap_test.cc",
        "shim/test_stack.cc",
    ]
}

cc_test {
    name: "bluetooth_test_legacy",
    defaults: ["fluoride_defaults",
               "fluoride_osi_defaults",
    ],
    test_suites: ["device-tests"],
    host_supported: true,
    srcs: [
        ":BluetoothLegacyShimTestSources",
    ],
    static_libs: [
        "libgmock",
        "libbluetooth-for-tests",
        "libosi",
    ],
    shared_libs: [
        "libchrome",
        "liblog",
    ],
}
+2 −7
Original line number Diff line number Diff line
@@ -246,13 +246,9 @@ bool bluetooth::legacy::shim::L2cap::WriteNonFlushable(uint16_t cid,

bool bluetooth::legacy::shim::L2cap::SetCallbacks(
    uint16_t cid, const tL2CAP_APPL_INFO* callbacks) {
  LOG_DEBUG(LOG_TAG, "Mapping cid:%hd to callbacks", cid);
  CHECK(callbacks != nullptr);
  if (cid_to_callback_map_.find(cid) != cid_to_callback_map_.end()) {
    LOG_WARN(LOG_TAG, "Already have mapped cid:%hd to callbacks", cid);
  }
  LOG_ASSERT(cid_to_callback_map_.find(cid) != cid_to_callback_map_.end())
      << "Registering multiple channel callbacks "
  LOG_ASSERT(cid_to_callback_map_.find(cid) == cid_to_callback_map_.end())
      << "Already have callbacks registered for "
         "connection_interface_descriptor:"
      << cid;
  cid_to_callback_map_[cid] = callbacks;
@@ -295,7 +291,6 @@ bool bluetooth::legacy::shim::L2cap::ConfigRequest(

  auto func = cid_to_postable_map_[cid];
  func([&cid, &callbacks](uint16_t cid2) {
    LOG_WARN(LOG_TAG, "Hello world %hd %hd", cid, cid2);
    callbacks->pL2CA_ConfigCfm_Cb(cid, nullptr);
  });
  return true;
+254 −0
Original line number Diff line number Diff line
/*
 * Copyright 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <gtest/gtest.h>
#include <cstdint>

#define LOG_TAG "bt_shim_test"

#include "osi/include/log.h"
#include "shim/l2cap.h"
#include "shim/test_stack.h"
#include "types/raw_address.h"

TestStack test_stack_;

bluetooth::shim::IStack* bluetooth::shim::GetGabeldorscheStack() {
  return (bluetooth::shim::IStack*)&test_stack_;
}

namespace bluetooth {
namespace legacy {

namespace {

constexpr uint16_t kPsm = 123;
constexpr uint16_t kCid = 987;
constexpr size_t kDataBufferSize = 1024;

uint8_t bt_hdr_data[] = {
    0x00, 0x00,                                     /* event */
    0x08, 0x00,                                     /* len */
    0x00, 0x00,                                     /* offset */
    0x00, 0x00,                                     /* layer specific */
    0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, /* data */
    0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, /* data */
};

class L2capTest;
L2capTest* l2cap_test_ = nullptr;

class L2capTest : public ::testing::Test {
 public:
  static shim::L2cap* l2cap_;

  struct {
    int L2caConnectCfmCb;
    int L2caConnectPndCb;
    int L2caConfigIndCb;
    int L2caConfigCfmCb;
    int L2caDisconnectIndCb;
    int L2caDisconnectCfmCb;
    int L2caQosViolationIndCb;
    int L2caDataIndCb;
    int L2caCongestionStatusCb;
    int L2caTxCompleteCb;
    int L2caCreditsReceivedCb;
  } cnt_{
      .L2caConnectCfmCb = 0,
      .L2caConnectPndCb = 0,
      .L2caConfigIndCb = 0,
      .L2caConfigCfmCb = 0,
      .L2caDisconnectIndCb = 0,
      .L2caDisconnectCfmCb = 0,
      .L2caQosViolationIndCb = 0,
      .L2caDataIndCb = 0,
      .L2caCongestionStatusCb = 0,
      .L2caTxCompleteCb = 0,
      .L2caCreditsReceivedCb = 0,
  };

 protected:
  void SetUp() override {
    l2cap_ = new shim::L2cap();
    l2cap_test_ = this;
  }

  void TearDown() override {
    delete l2cap_;
    l2cap_ = nullptr;
  }

  uint8_t data_buffer_[kDataBufferSize];
};

shim::L2cap* L2capTest::l2cap_ = nullptr;
// Indication of remotely initiated connection response sent
void L2caConnectIndCb(const RawAddress& raw_address, uint16_t a, uint16_t b,
                      uint8_t c) {
  LOG_INFO(LOG_TAG, "%s", __func__);
}

// Confirms locally initiated connection request completed
void L2caConnectCfmCb(uint16_t cid, uint16_t result) {
  l2cap_test_->cnt_.L2caConnectCfmCb++;
  LOG_INFO(LOG_TAG, "%s cid:%hd result:%hd", __func__, cid, result);
}

void L2caConnectPndCb(uint16_t cid) {
  l2cap_test_->cnt_.L2caConnectPndCb++;
  LOG_INFO(LOG_TAG, "%s", __func__);
}

// Indication of remotely initiated configuration response sent
void L2caConfigIndCb(uint16_t cid, tL2CAP_CFG_INFO* callbacks) {
  l2cap_test_->cnt_.L2caConfigIndCb++;
  LOG_INFO(LOG_TAG, "%s", __func__);
}

// Confirms locally initiated config request completed
void L2caConfigCfmCb(uint16_t cid, tL2CAP_CFG_INFO* callbacks) {
  l2cap_test_->cnt_.L2caConfigCfmCb++;
  LOG_INFO(LOG_TAG, "%s", __func__);
}

// Indication of remotely initiated disconnection response sent
void L2caDisconnectIndCb(uint16_t cid, bool needs_ack) {
  l2cap_test_->cnt_.L2caDisconnectIndCb++;
  LOG_INFO(LOG_TAG, "%s", __func__);
}

// Confirms locally initiated disconnect request completed
void L2caDisconnectCfmCb(uint16_t cid, uint16_t result) {
  l2cap_test_->cnt_.L2caDisconnectCfmCb++;
  LOG_INFO(LOG_TAG, "%s", __func__);
}

void L2caQosViolationIndCb(const RawAddress& raw_address) {
  l2cap_test_->cnt_.L2caQosViolationIndCb++;
  LOG_INFO(LOG_TAG, "%s", __func__);
}

void L2caDataIndCb(uint16_t cid, BT_HDR* bt_hdr) {
  l2cap_test_->cnt_.L2caDataIndCb++;
  LOG_INFO(LOG_TAG, "%s", __func__);
}

void L2caCongestionStatusCb(uint16_t cid, bool is_congested) {
  l2cap_test_->cnt_.L2caCongestionStatusCb++;
  LOG_INFO(LOG_TAG, "%s", __func__);
}

void L2caTxCompleteCb(uint16_t cid, uint16_t sdu_cnt) {
  l2cap_test_->cnt_.L2caTxCompleteCb++;
  LOG_INFO(LOG_TAG, "%s", __func__);
}

void L2caCreditsReceivedCb(uint16_t cid, uint16_t credits_received,
                           uint16_t credit_count) {
  l2cap_test_->cnt_.L2caCreditsReceivedCb++;
  LOG_INFO(LOG_TAG, "%s", __func__);
}

tL2CAP_APPL_INFO test_callbacks{
    .pL2CA_ConnectInd_Cb = L2caConnectIndCb,
    .pL2CA_ConnectCfm_Cb = L2caConnectCfmCb,
    .pL2CA_ConnectPnd_Cb = L2caConnectPndCb,
    .pL2CA_ConfigInd_Cb = L2caConfigIndCb,
    .pL2CA_ConfigCfm_Cb = L2caConfigCfmCb,
    .pL2CA_DisconnectInd_Cb = L2caDisconnectIndCb,
    .pL2CA_DisconnectCfm_Cb = L2caDisconnectCfmCb,
    .pL2CA_QoSViolationInd_Cb = L2caQosViolationIndCb,
    .pL2CA_DataInd_Cb = L2caDataIndCb,
    .pL2CA_CongestionStatus_Cb = L2caCongestionStatusCb,
    .pL2CA_TxComplete_Cb = L2caTxCompleteCb,
    .pL2CA_CreditsReceived_Cb = L2caCreditsReceivedCb,
};

TEST_F(L2capTest, Base) { LOG_INFO(LOG_TAG, "Got test %p", &test_callbacks); }

TEST_F(L2capTest, Callbacks) {
  bool rc = l2cap_->SetCallbacks(kPsm, &test_callbacks);
  CHECK(rc == true);
}

TEST_F(L2capTest, RegisterService) {
  l2cap_->RegisterService(123, &test_callbacks, false);
}

TEST_F(L2capTest, CreateConnection_NotRegistered) {
  RawAddress raw_address;
  std::string string_address("11:22:33:44:55:66");
  RawAddress::FromString(string_address, raw_address);
  uint16_t cid = l2cap_->CreateConnection(123, raw_address);
  CHECK(cid == 0);
}

TEST_F(L2capTest, CreateConnection_Registered) {
  test_stack_.test_l2cap_.cid_ = kCid;
  l2cap_->RegisterService(123, &test_callbacks, false);

  RawAddress raw_address;
  std::string string_address("11:22:33:44:55:66");
  RawAddress::FromString(string_address, raw_address);
  uint16_t cid = l2cap_->CreateConnection(123, raw_address);
  CHECK(cid != 0);
}

TEST_F(L2capTest, CreateConnection_WithHandshake) {
  test_stack_.test_l2cap_.cid_ = kCid;
  l2cap_->RegisterService(kPsm, &test_callbacks, false);

  RawAddress raw_address;
  std::string string_address("11:22:33:44:55:66");
  RawAddress::FromString(string_address, raw_address);
  uint16_t cid = l2cap_->CreateConnection(kPsm, raw_address);
  CHECK(cid != 0);

  {
    // Simulate a successful connection response
    l2cap_->OnConnectionReady(kPsm, kCid,
                              [&cid](std::function<void(uint16_t)> func) {
                                LOG_INFO(LOG_TAG, "In closure cid:%d", cid);
                                func(cid);
                              });
  }
  CHECK(cnt_.L2caConnectCfmCb == 1);

  CHECK(l2cap_->ConfigRequest(cid, nullptr) == true);
  CHECK(cnt_.L2caConfigCfmCb == 1);

  BT_HDR* bt_hdr = (BT_HDR*)bt_hdr_data;

  test_stack_.test_l2cap_.data_buffer_ = data_buffer_;
  test_stack_.test_l2cap_.data_buffer_size_ = kDataBufferSize;

  l2cap_->Write(cid, bt_hdr);

  CHECK(data_buffer_[0] == 0x11);
  CHECK(data_buffer_[1] == 0x22);
  CHECK(data_buffer_[2] == 0x33);
  CHECK(data_buffer_[3] == 0x44);
  CHECK(data_buffer_[4] == 0x55);
  CHECK(data_buffer_[5] == 0x66);
  CHECK(data_buffer_[6] == 0x77);
  CHECK(data_buffer_[7] == 0x88);
  CHECK(data_buffer_[8] == 0x00);
}

}  // namespace
}  // namespace legacy
}  // namespace bluetooth
+87 −0
Original line number Diff line number Diff line
/*
 * Copyright 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <cstdint>
#include <future>

#include "gd/shim/only_include_this_file_into_legacy_stack___ever.h"
#include "main/shim/entry.h"
#include "main/shim/test_stack.h"
#include "osi/include/log.h"

#define ASSERT(condition)                                    \
  do {                                                       \
    if (!(condition)) {                                      \
      LOG_ALWAYS_FATAL("assertion '" #condition "' failed"); \
    }                                                        \
  } while (false)

void TestGdShimL2cap::RegisterService(
    uint16_t psm, bluetooth::shim::ConnectionOpenCallback on_open,
    std::promise<void> completed) {
  completed.set_value();
}

void TestGdShimL2cap::CreateConnection(uint16_t psm, const std::string address,
                                       std::promise<uint16_t> completed) {
  completed.set_value(cid_);
}

void TestGdShimL2cap::SetReadDataReadyCallback(
    uint16_t cid, bluetooth::shim::ReadDataReadyCallback on_data_ready) {}

void TestGdShimL2cap::SetConnectionClosedCallback(
    uint16_t cid, bluetooth::shim::ConnectionClosedCallback on_closed) {}

bool TestGdShimL2cap::Write(uint16_t cid, const uint8_t* data, size_t len) {
  ASSERT(data_buffer_ != nullptr);
  ASSERT(data_buffer_size_ > len);
  memcpy(data_buffer_, data, len);
  return write_success_;
}

bool TestGdShimL2cap::WriteFlushable(uint16_t cid, const uint8_t* data,
                                     size_t len) {
  return write_success_;
}

bool TestGdShimL2cap::WriteNonFlushable(uint16_t cid, const uint8_t* data,
                                        size_t len) {
  return write_success_;
}

bool TestGdShimL2cap::IsCongested(uint16_t cid) { return is_congested_; }

void TestStack::Start() {}

void TestStack::Stop() {}

bluetooth::shim::IController* TestStack::GetController() { return nullptr; }

bluetooth::shim::IConnectability* TestStack::GetConnectability() {
  return nullptr;
}

bluetooth::shim::IDiscoverability* TestStack::GetDiscoverability() {
  return nullptr;
}

bluetooth::shim::IHciLayer* TestStack::GetHciLayer() { return nullptr; }

bluetooth::shim::IInquiry* TestStack::GetInquiry() { return nullptr; }

bluetooth::shim::IL2cap* TestStack::GetL2cap() { return &test_l2cap_; }

bluetooth::shim::IPage* TestStack::GetPage() { return nullptr; }
+64 −0
Original line number Diff line number Diff line
/*
 * Copyright 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <cstdint>
#include <future>

#include "gd/shim/only_include_this_file_into_legacy_stack___ever.h"
#include "main/shim/entry.h"

class TestGdShimL2cap : public bluetooth::shim::IL2cap {
 public:
  uint16_t cid_{0};
  bool write_success_{false};
  bool is_congested_{false};
  uint8_t* data_buffer_{nullptr};
  size_t data_buffer_size_{0};

  void RegisterService(uint16_t psm,
                       bluetooth::shim::ConnectionOpenCallback on_open,
                       std::promise<void> completed) override;
  void CreateConnection(uint16_t psm, const std::string address,
                        std::promise<uint16_t> completed) override;
  void SetReadDataReadyCallback(
      uint16_t cid,
      bluetooth::shim::ReadDataReadyCallback on_data_ready) override;
  void SetConnectionClosedCallback(
      uint16_t cid,
      bluetooth::shim::ConnectionClosedCallback on_closed) override;
  bool Write(uint16_t cid, const uint8_t* data, size_t len) override;
  bool WriteFlushable(uint16_t cid, const uint8_t* data, size_t len) override;
  bool WriteNonFlushable(uint16_t cid, const uint8_t* data,
                         size_t len) override;
  bool IsCongested(uint16_t cid) override;
};

class TestStack : public bluetooth::shim::IStack {
 public:
  TestStack() = default;

  bluetooth::shim::IController* GetController();
  bluetooth::shim::IConnectability* GetConnectability();
  bluetooth::shim::IDiscoverability* GetDiscoverability();
  bluetooth::shim::IHciLayer* GetHciLayer();
  bluetooth::shim::IInquiry* GetInquiry();
  bluetooth::shim::IL2cap* GetL2cap();
  bluetooth::shim::IPage* GetPage();

  TestGdShimL2cap test_l2cap_;

  void Start();
  void Stop();
};