OSDN Git Service

add legacy shim l2cap tests
authorChris Manton <cmanton@google.com>
Tue, 5 Nov 2019 19:39:07 +0000 (11:39 -0800)
committerMyles Watson <mylesgw@google.com>
Wed, 6 Nov 2019 16:49:20 +0000 (16:49 +0000)
Bug: 143697964
Test: out/host/linux-x86/nativetest64/bluetooth_test_legacy/bluetooth_test_legacy

Change-Id: I67166a5e0f7e6733bb695026d89ef226c4eae2c1

main/Android.bp
main/shim/l2cap.cc
main/shim/l2cap_test.cc [new file with mode: 0644]
main/shim/test_stack.cc [new file with mode: 0644]
main/shim/test_stack.h [new file with mode: 0644]

index 1ef608f..fec6644 100644 (file)
@@ -123,6 +123,7 @@ cc_library_static {
         ":LibBluetoothSources",
         "shim/entry_for_test.cc",
     ],
+    host_supported: true,
     include_dirs: [
         "system/bt",
         "system/bt/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",
+    ],
+}
+
index 597c1df..bbf8c8c 100644 (file)
@@ -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;
diff --git a/main/shim/l2cap_test.cc b/main/shim/l2cap_test.cc
new file mode 100644 (file)
index 0000000..c0f9a7b
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+ * 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
diff --git a/main/shim/test_stack.cc b/main/shim/test_stack.cc
new file mode 100644 (file)
index 0000000..14a7f5a
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * 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; }
diff --git a/main/shim/test_stack.h b/main/shim/test_stack.h
new file mode 100644 (file)
index 0000000..967e7f9
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * 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();
+};