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

Commit 3dbb3459 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Add more HCI unit tests."

parents e42b4248 974a1475
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ using std::unique_ptr;
static void fail_if_reset_complete_not_success(CommandCompleteView complete) {
  auto reset_complete = ResetCompleteView::Create(complete);
  ASSERT(reset_complete.IsValid());
  LOG_DEBUG("Reset completed with status: %s", ErrorCodeText(ErrorCode::SUCCESS).c_str());
  ASSERT(reset_complete.GetStatus() == ErrorCode::SUCCESS);
}

+109 −9
Original line number Diff line number Diff line
@@ -37,6 +37,12 @@

using namespace std::chrono_literals;

namespace {
constexpr size_t kBufSize = 512;
constexpr char kOurEventHandlerWasInvoked[] = "Our event handler was invoked.";
constexpr char kOurLeEventHandlerWasInvoked[] = "Our LE event handler was invoked.";
}  // namespace

namespace bluetooth {
namespace hci {

@@ -68,7 +74,7 @@ class TestHciHal : public hal::HciHal {
  TestHciHal() : hal::HciHal() {}

  ~TestHciHal() {
    ASSERT_LOG(callbacks == nullptr, "unregisterIncomingPacketCallback() must be called");
    ASSERT(callbacks == nullptr);
  }

  void registerIncomingPacketCallback(hal::HciHalCallbacks* callback) override {
@@ -81,7 +87,8 @@ class TestHciHal : public hal::HciHal {

  void sendHciCommand(hal::HciPacket command) override {
    outgoing_commands_.push_back(std::move(command));
    LOG_DEBUG("Enqueued HCI command in HAL.");
    sent_commands_++;
    LOG_DEBUG("Enqueued HCI command %d in HAL.", sent_commands_);
  }

  void sendScoData(hal::HciPacket data) override {}
@@ -111,19 +118,24 @@ class TestHciHal : public hal::HciHal {
    return outgoing_commands_.size();
  }

  void InjectEvent(std::unique_ptr<packet::BasePacketBuilder> packet) {
    callbacks->hciEventReceived(GetPacketBytes(std::move(packet)));
  }

  std::string ToString() const override {
    return std::string("TestHciHal");
  }

  void InjectResetCompleteEventWithCode(ErrorCode code) {
    auto reset_complete = ResetCompleteBuilder::Create(0x01, code);
    InjectEvent(std::move(reset_complete));
  }

  void InjectEvent(std::unique_ptr<packet::BasePacketBuilder> packet) {
    callbacks->hciEventReceived(GetPacketBytes(std::move(packet)));
  }
  static const ModuleFactory Factory;

 private:
  std::list<hal::HciPacket> outgoing_commands_;
  std::unique_ptr<std::promise<void>> sent_command_promise_;
  int sent_commands_{0};
};

const ModuleFactory TestHciHal::Factory = ModuleFactory([]() { return new TestHciHal(); });
@@ -152,8 +164,12 @@ class HciLayerTest : public ::testing::Test {
  }

  void FailIfResetNotSent() {
    hci_handler_->BindOnceOn(this, &HciLayerTest::fail_if_reset_not_sent).Invoke();
  }

  void fail_if_reset_not_sent() {
    std::promise<void> promise;
    log_capture_->WaitUntilLogContains(&promise, "Enqueued HCI command in HAL.");
    log_capture_->WaitUntilLogContains(&promise, "Enqueued HCI command 1 in HAL.");
    auto sent_command = hal_->GetSentCommand();
    auto reset_view = ResetView::Create(CommandView::Create(sent_command));
    ASSERT_TRUE(reset_view.IsValid());
@@ -177,7 +193,7 @@ TEST_F(HciLayerTest, controller_debug_info_requested_on_hci_timeout) {
  FakeTimerAdvance(HciLayer::kHciTimeoutMs.count());

  std::promise<void> promise;
  log_capture_->WaitUntilLogContains(&promise, "Enqueued HCI command in HAL.");
  log_capture_->WaitUntilLogContains(&promise, "Enqueued HCI command 2 in HAL.");
  auto sent_command = hal_->GetSentCommand();
  auto debug_info_view = ControllerDebugInfoView::Create(VendorCommandView::Create(sent_command));
  ASSERT_TRUE(debug_info_view.IsValid());
@@ -188,7 +204,7 @@ TEST_F(HciLayerTest, abort_after_hci_restart_timeout) {
  FakeTimerAdvance(HciLayer::kHciTimeoutMs.count());

  std::promise<void> promise;
  log_capture_->WaitUntilLogContains(&promise, "Enqueued HCI command in HAL.");
  log_capture_->WaitUntilLogContains(&promise, "Enqueued HCI command 2 in HAL.");
  auto sent_command = hal_->GetSentCommand();
  auto debug_info_view = ControllerDebugInfoView::Create(VendorCommandView::Create(sent_command));
  ASSERT_TRUE(debug_info_view.IsValid());
@@ -219,5 +235,89 @@ TEST_F(HciLayerTest, abort_on_root_inflammation_event) {
      "");
}

TEST_F(HciLayerTest, successful_reset) {
  FailIfResetNotSent();
  auto error_code = ErrorCode::SUCCESS;
  hal_->InjectResetCompleteEventWithCode(error_code);
  std::promise<void> promise;
  auto buf = std::make_unique<char[]>(kBufSize);
  std::snprintf(buf.get(), kBufSize, "Reset completed with status: %s", ErrorCodeText(error_code).c_str());
  log_capture_->WaitUntilLogContains(&promise, buf.get());
}

TEST_F(HciLayerTest, abort_if_reset_complete_returns_error) {
  FailIfResetNotSent();
  ASSERT_DEATH(
      {
        auto error_code = ErrorCode::UNSPECIFIED_ERROR;
        hal_->InjectResetCompleteEventWithCode(error_code);
        std::promise<void> promise;
        auto buf = std::make_unique<char[]>(kBufSize);
        std::snprintf(buf.get(), kBufSize, "Reset completed with status: %s", ErrorCodeText(error_code).c_str());
        log_capture_->WaitUntilLogContains(&promise, buf.get());
      },
      "");
}

TEST_F(HciLayerTest, event_handler_is_invoked) {
  FailIfResetNotSent();
  hci_->UnregisterEventHandler(EventCode::COMMAND_COMPLETE);
  hci_->RegisterEventHandler(EventCode::COMMAND_COMPLETE, hci_handler_->Bind([](EventView view) {
    LOG_DEBUG("%s", kOurEventHandlerWasInvoked);
  }));
  auto error_code = ErrorCode::SUCCESS;
  hal_->InjectResetCompleteEventWithCode(error_code);
  std::promise<void> promise;
  log_capture_->WaitUntilLogContains(&promise, kOurEventHandlerWasInvoked);
}

TEST_F(HciLayerTest, le_event_handler_is_invoked) {
  FailIfResetNotSent();
  hci_->RegisterLeEventHandler(SubeventCode::ENHANCED_CONNECTION_COMPLETE, hci_handler_->Bind([](LeMetaEventView view) {
    LOG_DEBUG("%s", kOurLeEventHandlerWasInvoked);
  }));
  hci::Address remote_address;
  Address::FromString("D0:05:04:03:02:01", remote_address);
  hal_->InjectEvent(LeEnhancedConnectionCompleteBuilder::Create(
      ErrorCode::SUCCESS,
      0x0041,
      Role::PERIPHERAL,
      AddressType::PUBLIC_DEVICE_ADDRESS,
      remote_address,
      Address::kEmpty,
      Address::kEmpty,
      0x0024,
      0x0000,
      0x0011,
      ClockAccuracy::PPM_30));
  std::promise<void> promise;
  log_capture_->WaitUntilLogContains(&promise, kOurLeEventHandlerWasInvoked);
}

TEST_F(HciLayerTest, abort_on_second_register_event_handler) {
  FailIfResetNotSent();
  ASSERT_DEATH(
      {
        hci_->RegisterEventHandler(EventCode::COMMAND_COMPLETE, hci_handler_->Bind([](EventView view) {}));
        std::promise<void> promise;
        log_capture_->WaitUntilLogContains(&promise, "Can not register a second handler for");
      },
      "");
}

TEST_F(HciLayerTest, abort_on_second_register_le_event_handler) {
  FailIfResetNotSent();
  hci_->RegisterLeEventHandler(
      SubeventCode::ENHANCED_CONNECTION_COMPLETE, hci_handler_->Bind([](LeMetaEventView view) {}));
  ASSERT_DEATH(
      {
        hci_->RegisterLeEventHandler(
            SubeventCode::ENHANCED_CONNECTION_COMPLETE, hci_handler_->Bind([](LeMetaEventView view) {}));
        std::promise<void> promise;
        log_capture_->WaitUntilLogContains(&promise, "Can not register a second handler for");
      },
      "");
}

}  // namespace hci
}  // namespace bluetooth