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

Commit 89d0a406 authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Add more HCI unit tests." am: 3dbb3459

parents bb4ded26 3dbb3459
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