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

Commit 29f33663 authored by Chris Manton's avatar Chris Manton
Browse files

test: Fix flaky bt_host_test_bta

Also do some clean up

Bug: 285201407
Test: bt_host_test_bta64
Change-Id: I6c7378a33790944dc10e42b71be2e92c5d8ebe0c
parent 498899d5
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -21,8 +21,11 @@
#include <memory>

#include "bta/dm/bta_dm_int.h"
#include "osi/include/allocator.h"
#include "stack/include/bt_hdr.h"
#include "stack/include/btm_status.h"
#include "test/fake/fake_osi.h"
#include "test/mock/mock_stack_btm.h"
#include "types/bluetooth/uuid.h"

using bluetooth::Uuid;
@@ -32,7 +35,25 @@ class BtaCustUuid : public testing::Test {
  void SetUp() override {
    fake_osi_ = std::make_unique<test::fake::FakeOsi>();
    bta_dm_cb = {};
    btm_client_interface = {};
    btm_client_interface.eir.BTM_WriteEIR = [](BT_HDR* p_buf) -> tBTM_STATUS {
      osi_free(p_buf);
      return BTM_SUCCESS;
    };
    btm_client_interface.eir.BTM_GetEirSupportedServices =
        [](uint32_t* p_eir_uuid, uint8_t** p, uint8_t max_num_uuid16,
           uint8_t* p_num_uuid16) -> uint8_t { return 0; };
    btm_client_interface.eir.BTM_WriteEIR = [](BT_HDR* p_buf) -> tBTM_STATUS {
      osi_free(p_buf);
      return BTM_SUCCESS;
    };
    btm_client_interface.local.BTM_ReadLocalDeviceNameFromController =
        [](tBTM_CMPL_CB* cb) -> tBTM_STATUS { return BTM_CMD_STARTED; };
    btm_client_interface.security.BTM_SecRegister =
        [](const tBTM_APPL_INFO* p_cb_info) -> bool { return true; };
  }
  void TearDown() override { btm_client_interface = {}; }

  std::unique_ptr<test::fake::FakeOsi> fake_osi_;
};

+94 −70
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@
#include "common/message_loop_thread.h"
#include "osi/include/compat.h"
#include "stack/include/bt_dev_class.h"
#include "stack/include/bt_device_type.h"
#include "stack/include/bt_name.h"
#include "stack/include/btm_status.h"
#include "test/common/main_handler.h"
@@ -41,8 +42,10 @@
#include "test/mock/mock_osi_alarm.h"
#include "test/mock/mock_osi_allocator.h"
#include "test/mock/mock_stack_acl.h"
#include "test/mock/mock_stack_btm_ble.h"
#include "test/mock/mock_stack_btm_inq.h"
#include "test/mock/mock_stack_btm_sec.h"
#include "types/ble_address_with_type.h"

using namespace std::chrono_literals;
using ::testing::ElementsAre;
@@ -97,91 +100,72 @@ class BtaDmTest : public testing::Test {
  std::unique_ptr<test::fake::FakeOsi> fake_osi_;
};

class BtaDmCustomAlarmTest : public BtaDmTest {
 protected:
  void SetUp() override {
    BtaDmTest::SetUp();
    test::mock::osi_alarm::alarm_set_on_mloop.body =
        [this](alarm_t* alarm, uint64_t interval_ms, alarm_callback_t cb,
               void* data) {
          ASSERT_TRUE(alarm != nullptr);
          this->alarm_callback = cb;
          this->alarm_data = data;
        };
  }
  void TearDown() override {
    test::mock::osi_alarm::alarm_set_on_mloop = {};
    BtaDmTest::TearDown();
  }
  alarm_callback_t alarm_callback;
  void* alarm_data{nullptr};
};

TEST_F(BtaDmTest, nop) {
  bool status = true;
  ASSERT_EQ(true, status);
}

TEST_F(BtaDmTest, disable_no_acl_links) {
TEST_F(BtaDmCustomAlarmTest, disable_no_acl_links) {
  bta_dm_cb.disabling = true;

  alarm_callback_t alarm_callback;
  void* alarm_data{nullptr};
  test::mock::osi_alarm::alarm_set_on_mloop.body =
      [&alarm_callback, &alarm_data](alarm_t* alarm, uint64_t interval_ms,
                                     alarm_callback_t cb, void* data) {
        ASSERT_TRUE(alarm != nullptr);
        alarm_callback = cb;
        alarm_data = data;
      };

  bta_dm_disable();  // Waiting for all ACL connections to drain
  ASSERT_EQ(0, get_func_call_count("btm_remove_acl"));
  ASSERT_EQ(1, get_func_call_count("alarm_set_on_mloop"));

  // Execute timer callback
  alarm_callback(alarm_data);
  alarm_callback(this->alarm_data);
  ASSERT_EQ(1, get_func_call_count("alarm_set_on_mloop"));
  ASSERT_EQ(0, get_func_call_count("BTIF_dm_disable"));
  ASSERT_EQ(1, get_func_call_count("future_ready"));
  ASSERT_TRUE(!bta_dm_cb.disabling);

  test::mock::osi_alarm::alarm_set_on_mloop = {};
}

TEST_F(BtaDmTest, disable_first_pass_with_acl_links) {
  uint16_t links_up = 1;
  test::mock::stack_acl::BTM_GetNumAclLinks.body = [&links_up]() {
    return links_up;
  };
TEST_F(BtaDmCustomAlarmTest, disable_first_pass_with_acl_links) {
  test::mock::stack_acl::BTM_GetNumAclLinks.body = []() { return 1; };
  bta_dm_cb.disabling = true;
  // ACL link is open
  bta_dm_cb.device_list.count = 1;

  alarm_callback_t alarm_callback;
  void* alarm_data{nullptr};
  test::mock::osi_alarm::alarm_set_on_mloop.body =
      [&alarm_callback, &alarm_data](alarm_t* alarm, uint64_t interval_ms,
                                     alarm_callback_t cb, void* data) {
        ASSERT_TRUE(alarm != nullptr);
        alarm_callback = cb;
        alarm_data = data;
      };

  bta_dm_disable();              // Waiting for all ACL connections to drain
  ASSERT_EQ(1, get_func_call_count("alarm_set_on_mloop"));
  ASSERT_EQ(0, get_func_call_count("BTIF_dm_disable"));

  links_up = 0;
  test::mock::stack_acl::BTM_GetNumAclLinks.body = []() { return 0; };
  // First disable pass
  alarm_callback(alarm_data);
  alarm_callback(this->alarm_data);
  ASSERT_EQ(1, get_func_call_count("alarm_set_on_mloop"));
  ASSERT_EQ(1, get_func_call_count("BTIF_dm_disable"));
  ASSERT_TRUE(!bta_dm_cb.disabling);

  test::mock::stack_acl::BTM_GetNumAclLinks = {};
  test::mock::osi_alarm::alarm_set_on_mloop = {};
}

TEST_F(BtaDmTest, disable_second_pass_with_acl_links) {
  uint16_t links_up = 1;
  test::mock::stack_acl::BTM_GetNumAclLinks.body = [&links_up]() {
    return links_up;
  };
TEST_F(BtaDmCustomAlarmTest, disable_second_pass_with_acl_links) {
  test::mock::stack_acl::BTM_GetNumAclLinks.body = []() { return 1; };
  bta_dm_cb.disabling = true;
  // ACL link is open
  bta_dm_cb.device_list.count = 1;

  alarm_callback_t alarm_callback;
  void* alarm_data{nullptr};
  test::mock::osi_alarm::alarm_set_on_mloop.body =
      [&alarm_callback, &alarm_data](alarm_t* alarm, uint64_t interval_ms,
                                     alarm_callback_t cb, void* data) {
        ASSERT_TRUE(alarm != nullptr);
        alarm_callback = cb;
        alarm_data = data;
      };

  bta_dm_disable();  // Waiting for all ACL connections to drain
  ASSERT_EQ(1, get_func_call_count("alarm_set_on_mloop"));
  ASSERT_EQ(0, get_func_call_count("BTIF_dm_disable"));
@@ -198,7 +182,6 @@ TEST_F(BtaDmTest, disable_second_pass_with_acl_links) {
  ASSERT_TRUE(!bta_dm_cb.disabling);

  test::mock::stack_acl::BTM_GetNumAclLinks = {};
  test::mock::osi_alarm::alarm_set_on_mloop = {};
}

namespace {
@@ -238,19 +221,18 @@ tBTM_STATUS bta_dm_sp_cback(tBTM_SP_EVT event, tBTM_SP_EVT_DATA* p_data);
}  // namespace bluetooth

TEST_F(BtaDmTest, bta_dm_set_encryption) {
  const RawAddress bd_addr{{0x11, 0x22, 0x33, 0x44, 0x55, 0x66}};
  const tBT_TRANSPORT transport{BT_TRANSPORT_LE};
  const tBTM_BLE_SEC_ACT sec_act{BTM_BLE_SEC_NONE};

  // Callback not provided
  bta_dm_set_encryption(bd_addr, transport, nullptr, sec_act);
  bta_dm_set_encryption(kRawAddress, transport, nullptr, sec_act);

  // Device connection does not exist
  bta_dm_set_encryption(bd_addr, transport, BTA_DM_ENCRYPT_CBACK, sec_act);
  bta_dm_set_encryption(kRawAddress, transport, BTA_DM_ENCRYPT_CBACK, sec_act);

  // Setup a connected device
  tBTA_DM_PEER_DEVICE* device =
      bluetooth::legacy::testing::allocate_device_for(bd_addr, transport);
      bluetooth::legacy::testing::allocate_device_for(kRawAddress, transport);
  ASSERT_TRUE(device != nullptr);
  device->conn_state = BTA_DM_CONNECTED;
  device->p_encrypt_cback = nullptr;
@@ -258,7 +240,7 @@ TEST_F(BtaDmTest, bta_dm_set_encryption) {
  // Setup a device that is busy with another encryption
  // Fake indication that the encryption is in progress with non-null callback
  device->p_encrypt_cback = BTA_DM_ENCRYPT_CBACK;
  bta_dm_set_encryption(bd_addr, transport, BTA_DM_ENCRYPT_CBACK, sec_act);
  bta_dm_set_encryption(kRawAddress, transport, BTA_DM_ENCRYPT_CBACK, sec_act);
  ASSERT_EQ(0, get_func_call_count("BTM_SetEncryption"));
  ASSERT_EQ(1UL, BTA_DM_ENCRYPT_CBACK_queue.size());
  auto params = BTA_DM_ENCRYPT_CBACK_queue.front();
@@ -274,7 +256,7 @@ TEST_F(BtaDmTest, bta_dm_set_encryption) {
    return BTM_MODE_UNSUPPORTED;
  };

  bta_dm_set_encryption(bd_addr, transport, BTA_DM_ENCRYPT_CBACK, sec_act);
  bta_dm_set_encryption(kRawAddress, transport, BTA_DM_ENCRYPT_CBACK, sec_act);
  ASSERT_EQ(1, get_func_call_count("BTM_SetEncryption"));
  ASSERT_EQ(0UL, BTA_DM_ENCRYPT_CBACK_queue.size());
  device->p_encrypt_cback = nullptr;
@@ -285,7 +267,7 @@ TEST_F(BtaDmTest, bta_dm_set_encryption) {
         tBTM_SEC_CALLBACK* p_callback, void* p_ref_data,
         tBTM_BLE_SEC_ACT sec_act) -> tBTM_STATUS { return BTM_CMD_STARTED; };

  bta_dm_set_encryption(bd_addr, transport, BTA_DM_ENCRYPT_CBACK, sec_act);
  bta_dm_set_encryption(kRawAddress, transport, BTA_DM_ENCRYPT_CBACK, sec_act);
  ASSERT_EQ(2, get_func_call_count("BTM_SetEncryption"));
  ASSERT_EQ(0UL, BTA_DM_ENCRYPT_CBACK_queue.size());
  ASSERT_NE(nullptr, device->p_encrypt_cback);
@@ -298,31 +280,30 @@ void bta_dm_encrypt_cback(const RawAddress* bd_addr, tBT_TRANSPORT transport,
                          UNUSED_ATTR void* p_ref_data, tBTM_STATUS result);

TEST_F(BtaDmTest, bta_dm_encrypt_cback) {
  const RawAddress bd_addr{{0x11, 0x22, 0x33, 0x44, 0x55, 0x66}};
  const tBT_TRANSPORT transport{BT_TRANSPORT_LE};

  // Setup a connected device
  tBTA_DM_PEER_DEVICE* device =
      bluetooth::legacy::testing::allocate_device_for(bd_addr, transport);
      bluetooth::legacy::testing::allocate_device_for(kRawAddress, transport);
  ASSERT_TRUE(device != nullptr);
  device->conn_state = BTA_DM_CONNECTED;

  // Encryption with no callback set
  device->p_encrypt_cback = nullptr;
  bta_dm_encrypt_cback(&bd_addr, transport, nullptr, BTM_SUCCESS);
  bta_dm_encrypt_cback(&kRawAddress, transport, nullptr, BTM_SUCCESS);
  ASSERT_EQ(0UL, BTA_DM_ENCRYPT_CBACK_queue.size());

  // Encryption with callback
  device->p_encrypt_cback = BTA_DM_ENCRYPT_CBACK;
  bta_dm_encrypt_cback(&bd_addr, transport, nullptr, BTM_SUCCESS);
  bta_dm_encrypt_cback(&kRawAddress, transport, nullptr, BTM_SUCCESS);
  device->p_encrypt_cback = BTA_DM_ENCRYPT_CBACK;
  bta_dm_encrypt_cback(&bd_addr, transport, nullptr, BTM_WRONG_MODE);
  bta_dm_encrypt_cback(&kRawAddress, transport, nullptr, BTM_WRONG_MODE);
  device->p_encrypt_cback = BTA_DM_ENCRYPT_CBACK;
  bta_dm_encrypt_cback(&bd_addr, transport, nullptr, BTM_NO_RESOURCES);
  bta_dm_encrypt_cback(&kRawAddress, transport, nullptr, BTM_NO_RESOURCES);
  device->p_encrypt_cback = BTA_DM_ENCRYPT_CBACK;
  bta_dm_encrypt_cback(&bd_addr, transport, nullptr, BTM_BUSY);
  bta_dm_encrypt_cback(&kRawAddress, transport, nullptr, BTM_BUSY);
  device->p_encrypt_cback = BTA_DM_ENCRYPT_CBACK;
  bta_dm_encrypt_cback(&bd_addr, transport, nullptr, BTM_ILLEGAL_VALUE);
  bta_dm_encrypt_cback(&kRawAddress, transport, nullptr, BTM_ILLEGAL_VALUE);

  ASSERT_EQ(5UL, BTA_DM_ENCRYPT_CBACK_queue.size());

@@ -457,30 +438,73 @@ TEST_F(BtaDmTest, bta_dm_remname_cback__HCI_ERR_CONNECTION_EXISTS) {
}

TEST_F(BtaDmTest, bta_dm_determine_discovery_transport__BT_TRANSPORT_BR_EDR) {
  const RawAddress bd_addr{{0x11, 0x22, 0x33, 0x44, 0x55, 0x66}};
  bta_dm_search_cb.transport = BT_TRANSPORT_BR_EDR;

  ASSERT_EQ(BT_TRANSPORT_BR_EDR,
            bluetooth::legacy::testing::bta_dm_determine_discovery_transport(
                bd_addr));
                kRawAddress));
}

TEST_F(BtaDmTest, bta_dm_determine_discovery_transport__BT_TRANSPORT_LE) {
  const RawAddress bd_addr{{0x11, 0x22, 0x33, 0x44, 0x55, 0x66}};
  bta_dm_search_cb.transport = BT_TRANSPORT_LE;

  ASSERT_EQ(BT_TRANSPORT_LE,
            bluetooth::legacy::testing::bta_dm_determine_discovery_transport(
                bd_addr));
                kRawAddress));
}

TEST_F(BtaDmTest,
       bta_dm_determine_discovery_transport__BT_TRANSPORT_AUTO__BR_EDR) {
  bta_dm_search_cb.transport = BT_TRANSPORT_AUTO;

  test::mock::stack_btm_ble::BTM_ReadDevInfo.body =
      [](const RawAddress& remote_bda, tBT_DEVICE_TYPE* p_dev_type,
         tBLE_ADDR_TYPE* p_addr_type) {
        *p_dev_type = BT_DEVICE_TYPE_BREDR;
        *p_addr_type = BLE_ADDR_PUBLIC;
      };

  ASSERT_EQ(BT_TRANSPORT_BR_EDR,
            bluetooth::legacy::testing::bta_dm_determine_discovery_transport(
                kRawAddress));

  test::mock::stack_btm_ble::BTM_ReadDevInfo = {};
}

TEST_F(BtaDmTest,
       bta_dm_determine_discovery_transport__BT_TRANSPORT_AUTO__BLE__PUBLIC) {
  bta_dm_search_cb.transport = BT_TRANSPORT_AUTO;

  test::mock::stack_btm_ble::BTM_ReadDevInfo.body =
      [](const RawAddress& remote_bda, tBT_DEVICE_TYPE* p_dev_type,
         tBLE_ADDR_TYPE* p_addr_type) {
        *p_dev_type = BT_DEVICE_TYPE_BLE;
        *p_addr_type = BLE_ADDR_PUBLIC;
      };

  ASSERT_EQ(BT_TRANSPORT_LE,
            bluetooth::legacy::testing::bta_dm_determine_discovery_transport(
                kRawAddress));

  test::mock::stack_btm_ble::BTM_ReadDevInfo = {};
}

TEST_F(BtaDmTest, bta_dm_determine_discovery_transport__BT_TRANSPORT_AUTO) {
  const RawAddress bd_addr{{0x11, 0x22, 0x33, 0x44, 0x55, 0x66}};
TEST_F(BtaDmTest,
       bta_dm_determine_discovery_transport__BT_TRANSPORT_AUTO__DUMO) {
  bta_dm_search_cb.transport = BT_TRANSPORT_AUTO;

  test::mock::stack_btm_ble::BTM_ReadDevInfo.body =
      [](const RawAddress& remote_bda, tBT_DEVICE_TYPE* p_dev_type,
         tBLE_ADDR_TYPE* p_addr_type) {
        *p_dev_type = BT_DEVICE_TYPE_DUMO;
        *p_addr_type = BLE_ADDR_PUBLIC;
      };

  ASSERT_EQ(BT_TRANSPORT_BR_EDR,
            bluetooth::legacy::testing::bta_dm_determine_discovery_transport(
                bd_addr));
                kRawAddress));

  test::mock::stack_btm_ble::BTM_ReadDevInfo = {};
}

TEST_F(BtaDmTest, bta_dm_search_evt_text) {
+18 −4
Original line number Diff line number Diff line
@@ -96,7 +96,22 @@ class BtaPanTest : public ::testing::Test {
  std::deque<struct UuidPiece> uuids;
};

TEST_F(BtaPanTest, BTA_PanSetRole_Null) {
class BtaPanRegisteredTest : public BtaPanTest {
 protected:
  void SetUp() {
    BtaPanTest::SetUp();
    bta_sys_eir_register(BTA_SYS_EIR_CBACK);
  }

  void TearDown() {
    bta_sys_eir_unregister();
    BtaPanTest::TearDown();
  }
};

TEST_F(BtaPanTest, nop) {}

TEST_F(BtaPanRegisteredTest, BTA_PanSetRole_Null) {
  tBTA_PAN_ROLE role = BTA_PAN_ROLE_PANU | BTA_PAN_ROLE_NAP;
  tBTA_PAN_ROLE_INFO user_info = {
      .p_srv_name = std::string(),
@@ -108,7 +123,6 @@ TEST_F(BtaPanTest, BTA_PanSetRole_Null) {
      .app_id = 34,
  };

  bta_sys_eir_register(BTA_SYS_EIR_CBACK);
  BTA_PanSetRole(role, user_info, nap_info);

  // Wait for main thread to complete
@@ -125,7 +139,7 @@ TEST_F(BtaPanTest, BTA_PanSetRole_Null) {
  ASSERT_EQ(true, uuids[1].adding);
}

TEST_F(BtaPanTest, BTA_PanSetRole_WithNames) {
TEST_F(BtaPanRegisteredTest, BTA_PanSetRole_WithNames) {
  tBTA_PAN_ROLE role = BTA_PAN_ROLE_PANU | BTA_PAN_ROLE_NAP;
  tBTA_PAN_ROLE_INFO user_info = {
      .p_srv_name = "TestPanUser",
@@ -172,7 +186,7 @@ TEST_F(BtaPanTest, BTA_PanSetRole_WithNames) {

constexpr size_t kBtaServiceNameLen = static_cast<size_t>(BTA_SERVICE_NAME_LEN);

TEST_F(BtaPanTest, BTA_PanSetRole_WithLongNames) {
TEST_F(BtaPanRegisteredTest, BTA_PanSetRole_WithLongNames) {
  tBTA_PAN_ROLE role = BTA_PAN_ROLE_PANU | BTA_PAN_ROLE_NAP;
  tBTA_PAN_ROLE_INFO user_info = {
      .p_srv_name = std::string(200, 'A'),
+15 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include "bta/dm/bta_dm_int.h"
#include "test/common/main_handler.h"
#include "test/fake/fake_osi.h"
#include "test/mock/mock_stack_btm.h"
#include "test/mock/mock_stack_gatt_api.h"

void BTA_dm_on_hw_on();
@@ -36,6 +37,19 @@ class BtaSdpTest : public testing::Test {
    test::mock::stack_gatt_api::GATT_Register.body =
        [](const bluetooth::Uuid& p_app_uuid128, const std::string name,
           tGATT_CBACK* p_cb_info, bool eatt_support) { return 5; };
    btm_client_interface = {};
    btm_client_interface.eir.BTM_GetEirSupportedServices =
        [](uint32_t* p_eir_uuid, uint8_t** p, uint8_t max_num_uuid16,
           uint8_t* p_num_uuid16) -> uint8_t { return 0; };
    btm_client_interface.eir.BTM_WriteEIR = [](BT_HDR* p_buf) -> tBTM_STATUS {
      osi_free(p_buf);
      return BTM_SUCCESS;
    };
    btm_client_interface.local.BTM_ReadLocalDeviceNameFromController =
        [](tBTM_CMPL_CB* cb) -> tBTM_STATUS { return BTM_CMD_STARTED; };
    btm_client_interface.security.BTM_SecRegister =
        [](const tBTM_APPL_INFO* p_cb_info) -> bool { return true; };

    main_thread_start_up();
    sync_main_handler();

@@ -49,6 +63,7 @@ class BtaSdpTest : public testing::Test {
    main_thread_shut_down();

    test::mock::stack_gatt_api::GATT_Register = {};
    btm_client_interface = {};
  }
  std::unique_ptr<test::fake::FakeOsi> fake_osi_;
};
+21 −0
Original line number Diff line number Diff line
/*
 * Copyright 2023 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.
 */

#pragma once

#include "stack/include/btm_client_interface.h"

extern struct btm_client_interface_t btm_client_interface;