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

Commit 4514897e authored by Rahul Arya's avatar Rahul Arya
Browse files

Revert^2 Move TestHciLayer into a separate file

Previously we were copy/pasting it everywhere. Not only was this huge code
duplication, it also violated ODR since we were not always correctly namespacing
it. This CL wraps all its copies inside an anonymous namespace, and also exposes
it in bluetooth::hci in a separate file.

Re-landing due to build failure on previous attempt, since presubmits passed but then a conflicting change was submitted later.

Change-Id: I42aa96a6415a509e85500cfab445f2497b2ca436
Test: all existing
Bug: 247839849
parent 84193678
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ filegroup {
        "class_of_device_unittest.cc",
        "controller_test.cc",
        "controller_unittest.cc",
        "hci_layer_fake.cc",
        "hci_layer_test.cc",
        "hci_layer_unittest.cc",
        "hci_packets_test.cc",
+6 −5
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@

#include "hci/acl_manager/le_connection_management_callbacks.h"
#include "hci/address_with_type.h"
#include "hci/hci_layer_fake.h"
#include "hci/hci_packets.h"
#include "hci/le_acl_connection_interface.h"
#include "os/handler.h"
@@ -59,7 +60,8 @@ constexpr uint16_t kTimeout = 0x80;
constexpr uint16_t kContinuationNumber = 0x32;

namespace bluetooth::hci::acl_manager {
hci::PacketView<hci::kLittleEndian> GetPacketView(std::unique_ptr<packet::BasePacketBuilder> packet);

namespace {

class TestLeConnectionManagementCallbacks : public hci::acl_manager::LeConnectionManagementCallbacks {
  void OnConnectionUpdate(
@@ -90,7 +92,6 @@ class TestLeConnectionManagementCallbacks : public hci::acl_manager::LeConnectio
  FRIEND_TEST(LeAclConnectionTest, LeSubrateRequest_success);
  FRIEND_TEST(LeAclConnectionTest, LeSubrateRequest_error);
};
}  // namespace bluetooth::hci::acl_manager

class TestLeAclConnectionInterface : public hci::LeAclConnectionInterface {
 private:
@@ -161,8 +162,6 @@ class TestLeAclConnectionInterface : public hci::LeAclConnectionInterface {
  std::unique_ptr<std::future<void>> command_future_;
};

namespace bluetooth::hci::acl_manager {

class LeAclConnectionTest : public ::testing::Test {
 protected:
  void SetUp() override {
@@ -250,4 +249,6 @@ TEST_F(LeAclConnectionTest, LeSubrateRequest_error) {
  on_status.Invoke(std::move(command_status));
  sync_handler();
}

}  // namespace
}  // namespace bluetooth::hci::acl_manager
 No newline at end of file
+3 −0
Original line number Diff line number Diff line
@@ -163,6 +163,8 @@ namespace bluetooth {
namespace hci {
namespace acl_manager {

namespace {

PacketView<kLittleEndian> GetPacketView(std::unique_ptr<packet::BasePacketBuilder> packet) {
  auto bytes = std::make_shared<std::vector<uint8_t>>();
  BitInserter i(*bytes);
@@ -382,6 +384,7 @@ class TestHciLayer : public HciLayer {
  std::unique_ptr<std::future<void>> command_future_;
  CommandInterfaceImpl<AclCommandBuilder> le_acl_connection_manager_interface_{*this};
};
}  // namespace

class MockLeConnectionCallbacks : public LeConnectionCallbacks {
 public:
+17 −10
Original line number Diff line number Diff line
@@ -64,13 +64,15 @@ PacketView<kLittleEndian> GetPacketView(std::unique_ptr<packet::BasePacketBuilde

}  // namespace

namespace {

class TestHciLayer : public HciLayer {
 public:
  void EnqueueCommand(
      std::unique_ptr<CommandBuilder> command,
      common::ContextualOnceCallback<void(CommandCompleteView)> on_complete) override {
    GetHandler()->Post(common::BindOnce(&TestHciLayer::HandleCommand, common::Unretained(this), std::move(command),
                                        std::move(on_complete)));
    GetHandler()->Post(common::BindOnce(
        &TestHciLayer::HandleCommand, common::Unretained(this), std::move(command), std::move(on_complete)));
  }

  void EnqueueCommand(
@@ -100,8 +102,8 @@ class TestHciLayer : public HciLayer {
        local_version_information.lmp_version_ = LmpVersion::V_4_2;
        local_version_information.manufacturer_name_ = 0xBAD;
        local_version_information.lmp_subversion_ = 0x5678;
        event_builder = ReadLocalVersionInformationCompleteBuilder::Create(num_packets, ErrorCode::SUCCESS,
                                                                           local_version_information);
        event_builder = ReadLocalVersionInformationCompleteBuilder::Create(
            num_packets, ErrorCode::SUCCESS, local_version_information);
      } break;
      case (OpCode::READ_LOCAL_SUPPORTED_COMMANDS): {
        std::array<uint8_t, 64> supported_commands;
@@ -120,13 +122,17 @@ class TestHciLayer : public HciLayer {
        uint8_t page_bumber = read_command.GetPageNumber();
        uint64_t lmp_features = 0x012345678abcdef;
        lmp_features += page_bumber;
        event_builder = ReadLocalExtendedFeaturesCompleteBuilder::Create(num_packets, ErrorCode::SUCCESS, page_bumber,
                                                                         0x02, lmp_features);
        event_builder = ReadLocalExtendedFeaturesCompleteBuilder::Create(
            num_packets, ErrorCode::SUCCESS, page_bumber, 0x02, lmp_features);
      } break;
      case (OpCode::READ_BUFFER_SIZE): {
        event_builder = ReadBufferSizeCompleteBuilder::Create(
            num_packets, ErrorCode::SUCCESS, acl_data_packet_length, synchronous_data_packet_length,
            total_num_acl_data_packets, total_num_synchronous_data_packets);
            num_packets,
            ErrorCode::SUCCESS,
            acl_data_packet_length,
            synchronous_data_packet_length,
            total_num_acl_data_packets,
            total_num_synchronous_data_packets);
      } break;
      case (OpCode::READ_BD_ADDR): {
        event_builder = ReadBdAddrCompleteBuilder::Create(num_packets, ErrorCode::SUCCESS, Address::kAny);
@@ -178,8 +184,8 @@ class TestHciLayer : public HciLayer {
          payload->AddOctets2(feature_spec_version);
          payload->AddOctets(payload_bytes);
        }
        event_builder = LeGetVendorCapabilitiesCompleteBuilder::Create(num_packets, ErrorCode::SUCCESS,
                                                                       base_vendor_capabilities, std::move(payload));
        event_builder = LeGetVendorCapabilitiesCompleteBuilder::Create(
            num_packets, ErrorCode::SUCCESS, base_vendor_capabilities, std::move(payload));
      } break;
      case (OpCode::SET_EVENT_MASK): {
        auto view = SetEventMaskView::Create(command);
@@ -303,6 +309,7 @@ class ControllerTest : public ::testing::Test {
  os::Handler* client_handler_ = nullptr;
  uint16_t feature_spec_version_ = 98;
};
}  // namespace

class Controller055Test : public ControllerTest {
 protected:
+160 −0
Original line number Diff line number Diff line
/*
 * Copyright 2022 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 "hci/hci_layer_fake.h"

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

#include <algorithm>
#include <chrono>

namespace bluetooth {
namespace hci {

using packet::kLittleEndian;
using packet::PacketView;
using packet::RawBuilder;

PacketView<packet::kLittleEndian> GetPacketView(std::unique_ptr<packet::BasePacketBuilder> packet) {
  auto bytes = std::make_shared<std::vector<uint8_t>>();
  BitInserter i(*bytes);
  bytes->reserve(packet->size());
  packet->Serialize(i);
  return packet::PacketView<packet::kLittleEndian>(bytes);
}

void TestHciLayer::EnqueueCommand(
    std::unique_ptr<CommandBuilder> command, common::ContextualOnceCallback<void(CommandStatusView)> on_status) {
  std::lock_guard<std::mutex> lock(mutex_);
  command_queue_.push(std::move(command));
  command_status_callbacks.push_back(std::move(on_status));
  command_count_--;
  if (command_promise_ != nullptr && command_count_ == 0) {
    command_promise_->set_value();
    command_promise_.reset();
  }
}

void TestHciLayer::EnqueueCommand(
    std::unique_ptr<CommandBuilder> command, common::ContextualOnceCallback<void(CommandCompleteView)> on_complete) {
  std::lock_guard<std::mutex> lock(mutex_);
  command_queue_.push(std::move(command));
  command_complete_callbacks.push_back(std::move(on_complete));
  command_count_--;
  if (command_promise_ != nullptr && command_count_ == 0) {
    command_promise_->set_value();
    command_promise_.reset();
  }
}

void TestHciLayer::SetCommandFuture(uint16_t num_command) {
  ASSERT_TRUE(command_promise_ == nullptr) << "Promises, Promises, ... Only one at a time.";
  command_count_ = num_command;
  command_promise_ = std::make_unique<std::promise<void>>();
  command_future_ = std::make_unique<std::future<void>>(command_promise_->get_future());
}

CommandView TestHciLayer::GetCommand() {
  // Wait for EnqueueCommand if command_queue_ is empty
  if (command_queue_.empty() && command_future_ != nullptr) {
    command_future_->wait_for(std::chrono::milliseconds(1000));
  }

  std::lock_guard<std::mutex> lock(mutex_);
  if (command_queue_.empty()) {
    LOG_ERROR("Command queue is empty");
    return empty_command_view_;
  }

  auto last = std::move(command_queue_.front());
  command_queue_.pop();
  CommandView command_packet_view = CommandView::Create(GetPacketView(std::move(last)));
  if (!command_packet_view.IsValid()) {
    LOG_ERROR("Got invalid command");
    return empty_command_view_;
  }
  return command_packet_view;
}

void TestHciLayer::RegisterEventHandler(
    EventCode event_code, common::ContextualCallback<void(EventView)> event_handler) {
  registered_events_[event_code] = event_handler;
}

void TestHciLayer::UnregisterEventHandler(EventCode event_code) {
  registered_events_.erase(event_code);
}

void TestHciLayer::RegisterLeEventHandler(
    SubeventCode subevent_code, common::ContextualCallback<void(LeMetaEventView)> event_handler) {
  registered_le_events_[subevent_code] = event_handler;
}

void TestHciLayer::UnregisterLeEventHandler(SubeventCode subevent_code) {
  registered_le_events_.erase(subevent_code);
}

void TestHciLayer::IncomingEvent(std::unique_ptr<EventBuilder> event_builder) {
  auto packet = GetPacketView(std::move(event_builder));
  EventView event = EventView::Create(packet);
  ASSERT_TRUE(event.IsValid());
  EventCode event_code = event.GetEventCode();
  ASSERT_NE(registered_events_.find(event_code), registered_events_.end()) << EventCodeText(event_code);
  registered_events_[event_code].Invoke(event);
}

void TestHciLayer::IncomingLeMetaEvent(std::unique_ptr<LeMetaEventBuilder> event_builder) {
  auto packet = GetPacketView(std::move(event_builder));
  EventView event = EventView::Create(packet);
  LeMetaEventView meta_event_view = LeMetaEventView::Create(event);
  ASSERT_TRUE(meta_event_view.IsValid());
  SubeventCode subevent_code = meta_event_view.GetSubeventCode();
  ASSERT_TRUE(registered_le_events_.find(subevent_code) != registered_le_events_.end());
  registered_le_events_[subevent_code].Invoke(meta_event_view);
}

void TestHciLayer::CommandCompleteCallback(EventView event) {
  CommandCompleteView complete_view = CommandCompleteView::Create(event);
  ASSERT_TRUE(complete_view.IsValid());
  std::move(command_complete_callbacks.front()).Invoke(complete_view);
  command_complete_callbacks.pop_front();
}

void TestHciLayer::CommandStatusCallback(EventView event) {
  CommandStatusView status_view = CommandStatusView::Create(event);
  ASSERT_TRUE(status_view.IsValid());
  std::move(command_status_callbacks.front()).Invoke(status_view);
  command_status_callbacks.pop_front();
}

void TestHciLayer::InitEmptyCommand() {
  auto payload = std::make_unique<bluetooth::packet::RawBuilder>();
  auto command_builder = CommandBuilder::Create(OpCode::NONE, std::move(payload));
  empty_command_view_ = CommandView::Create(GetPacketView(std::move(command_builder)));
  ASSERT_TRUE(empty_command_view_.IsValid());
}

void TestHciLayer::ListDependencies(ModuleList* list) const {}
void TestHciLayer::Start() {
  InitEmptyCommand();
  RegisterEventHandler(EventCode::COMMAND_COMPLETE, GetHandler()->BindOn(this, &TestHciLayer::CommandCompleteCallback));
  RegisterEventHandler(EventCode::COMMAND_STATUS, GetHandler()->BindOn(this, &TestHciLayer::CommandStatusCallback));
}
void TestHciLayer::Stop() {}

}  // namespace hci
}  // namespace bluetooth
 No newline at end of file
Loading