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

Commit 83561b21 authored by Jakub Pawlowski's avatar Jakub Pawlowski Committed by Myles Watson
Browse files

Return the outgoing L2CAP packet directly

Fix flaky test

Bug: 150054218
Test: PairingHandlerUnitTest
Change-Id: I34c6e26a477d2a22b03b442c26304313bcd2824f
parent 10252e31
Loading
Loading
Loading
Loading
+51 −32
Original line number Diff line number Diff line
@@ -45,18 +45,6 @@ CommandView BuilderToView(std::unique_ptr<BasePacketBuilder> builder) {
  return CommandView::Create(temp_cmd_view);
}

std::condition_variable outgoing_l2cap_blocker_;
std::optional<bluetooth::security::CommandView> outgoing_l2cap_packet_;

bool WaitForOutgoingL2capPacket() {
  std::mutex mutex;
  std::unique_lock<std::mutex> lock(mutex);
  if (outgoing_l2cap_blocker_.wait_for(lock, std::chrono::seconds(5)) == std::cv_status::timeout) {
    return false;
  }
  return true;
}

class PairingResultHandlerMock {
 public:
  MOCK_CONST_METHOD1(OnPairingFinished, void(PairingResultOrFailure));
@@ -111,11 +99,34 @@ class PairingHandlerUnitTest : public testing::Test {
    outgoing_l2cap_blocker_.notify_one();
  }

  std::optional<bluetooth::security::CommandView> WaitForOutgoingL2capPacket() {
    std::mutex mutex;
    std::unique_lock<std::mutex> lock(mutex);

    // It is possible that we lost wakeup from condition_variable, check if data is already waiting to be processed
    if (outgoing_l2cap_packet_ != std::nullopt) {
      std::optional<bluetooth::security::CommandView> tmp = std::nullopt;
      outgoing_l2cap_packet_.swap(tmp);
      return tmp;
    }

    // Data not ready yet, wait for it.
    if (outgoing_l2cap_blocker_.wait_for(lock, std::chrono::seconds(5)) == std::cv_status::timeout) {
      return std::nullopt;
    }

    std::optional<bluetooth::security::CommandView> tmp = std::nullopt;
    outgoing_l2cap_packet_.swap(tmp);
    return tmp;
  }

 public:
  os::Thread* thread_;
  os::Handler* handler_;
  std::unique_ptr<common::BidiQueue<packet::PacketView<packet::kLittleEndian>, packet::BasePacketBuilder>> bidi_queue_;
  std::unique_ptr<os::EnqueueBuffer<packet::BasePacketBuilder>> up_buffer_;
  std::condition_variable outgoing_l2cap_blocker_;
  std::optional<bluetooth::security::CommandView> outgoing_l2cap_packet_ = std::nullopt;
};

InitialInformations initial_informations{
@@ -144,8 +155,9 @@ TEST_F(PairingHandlerUnitTest, test_phase_1_failure) {
  std::unique_ptr<PairingHandlerLe> pairing_handler =
      std::make_unique<PairingHandlerLe>(PairingHandlerLe::PHASE1, initial_informations);

  EXPECT_TRUE(WaitForOutgoingL2capPacket());
  EXPECT_EQ(outgoing_l2cap_packet_->GetCode(), Code::PAIRING_REQUEST);
  std::optional<bluetooth::security::CommandView> pairing_request = WaitForOutgoingL2capPacket();
  EXPECT_TRUE(pairing_request.has_value());
  EXPECT_EQ(pairing_request->GetCode(), Code::PAIRING_REQUEST);

  EXPECT_CALL(*pairingResult, OnPairingFinished(VariantWith<PairingFailure>(_))).Times(1);

@@ -154,8 +166,9 @@ TEST_F(PairingHandlerUnitTest, test_phase_1_failure) {
  bad_pairing_response.IsValid();
  pairing_handler->OnCommandView(bad_pairing_response);

  EXPECT_TRUE(WaitForOutgoingL2capPacket());
  EXPECT_EQ(outgoing_l2cap_packet_->GetCode(), Code::PAIRING_FAILED);
  std::optional<bluetooth::security::CommandView> pairing_failure = WaitForOutgoingL2capPacket();
  EXPECT_TRUE(pairing_failure.has_value());
  EXPECT_EQ(pairing_failure->GetCode(), Code::PAIRING_FAILED);
}

TEST_F(PairingHandlerUnitTest, test_secure_connections_just_works) {
@@ -168,9 +181,10 @@ TEST_F(PairingHandlerUnitTest, test_secure_connections_just_works) {
  std::unique_ptr<PairingHandlerLe> pairing_handler =
      std::make_unique<PairingHandlerLe>(PairingHandlerLe::PHASE1, initial_informations);

  EXPECT_TRUE(WaitForOutgoingL2capPacket());
  EXPECT_EQ(outgoing_l2cap_packet_->GetCode(), Code::PAIRING_REQUEST);
  CommandView pairing_request = outgoing_l2cap_packet_.value();
  std::optional<bluetooth::security::CommandView> pairing_request_pkt = WaitForOutgoingL2capPacket();
  EXPECT_TRUE(pairing_request_pkt.has_value());
  EXPECT_EQ(pairing_request_pkt->GetCode(), Code::PAIRING_REQUEST);
  CommandView pairing_request = pairing_request_pkt.value();

  auto pairing_response = BuilderToView(
      PairingResponseBuilder::Create(IoCapability::KEYBOARD_DISPLAY, OobDataFlag::NOT_PRESENT,
@@ -179,10 +193,11 @@ TEST_F(PairingHandlerUnitTest, test_secure_connections_just_works) {
  // Phase 1 finished.

  // pairing public key
  EXPECT_TRUE(WaitForOutgoingL2capPacket());
  EXPECT_EQ(Code::PAIRING_PUBLIC_KEY, outgoing_l2cap_packet_->GetCode());
  std::optional<bluetooth::security::CommandView> public_key_pkt = WaitForOutgoingL2capPacket();
  EXPECT_TRUE(public_key_pkt.has_value());
  EXPECT_EQ(Code::PAIRING_PUBLIC_KEY, public_key_pkt->GetCode());
  EcdhPublicKey my_public_key;
  auto ppkv = PairingPublicKeyView::Create(outgoing_l2cap_packet_.value());
  auto ppkv = PairingPublicKeyView::Create(public_key_pkt.value());
  ppkv.IsValid();
  my_public_key.x = ppkv.GetPublicKeyX();
  my_public_key.y = ppkv.GetPublicKeyY();
@@ -205,9 +220,10 @@ TEST_F(PairingHandlerUnitTest, test_secure_connections_just_works) {
  pairing_handler->OnCommandView(BuilderToView(PairingConfirmBuilder::Create(Cb)));

  // random
  EXPECT_TRUE(WaitForOutgoingL2capPacket());
  EXPECT_EQ(Code::PAIRING_RANDOM, outgoing_l2cap_packet_->GetCode());
  auto prv = PairingRandomView::Create(outgoing_l2cap_packet_.value());
  std::optional<bluetooth::security::CommandView> random_pkt = WaitForOutgoingL2capPacket();
  EXPECT_TRUE(random_pkt.has_value());
  EXPECT_EQ(Code::PAIRING_RANDOM, random_pkt->GetCode());
  auto prv = PairingRandomView::Create(random_pkt.value());
  prv.IsValid();
  Octet16 Na = prv.GetRandomValue();

@@ -237,9 +253,10 @@ TEST_F(PairingHandlerUnitTest, test_secure_connections_just_works) {
  Octet16 Ea = crypto_toolbox::f6(mac_key, Na, Nb, rb, iocapA.data(), a, b);
  Octet16 Eb = crypto_toolbox::f6(mac_key, Nb, Na, ra, iocapB.data(), b, a);

  EXPECT_TRUE(WaitForOutgoingL2capPacket());
  EXPECT_EQ(Code::PAIRING_DH_KEY_CHECK, outgoing_l2cap_packet_->GetCode());
  auto pdhkcv = PairingDhKeyCheckView::Create(outgoing_l2cap_packet_.value());
  std::optional<bluetooth::security::CommandView> dh_key_pkt = WaitForOutgoingL2capPacket();
  EXPECT_TRUE(dh_key_pkt.has_value());
  EXPECT_EQ(Code::PAIRING_DH_KEY_CHECK, dh_key_pkt->GetCode());
  auto pdhkcv = PairingDhKeyCheckView::Create(dh_key_pkt.value());
  pdhkcv.IsValid();
  EXPECT_EQ(pdhkcv.GetDhKeyCheck(), Ea);

@@ -280,8 +297,9 @@ TEST_F(PairingHandlerUnitTest, test_remote_slave_initiating) {
  // Simulate user accepting the pairing in UI
  pairing_handler->OnUiAction(PairingEvent::PAIRING_ACCEPTED, 0x01 /* Non-zero value means success */);

  EXPECT_TRUE(WaitForOutgoingL2capPacket());
  EXPECT_EQ(Code::PAIRING_REQUEST, outgoing_l2cap_packet_->GetCode());
  std::optional<bluetooth::security::CommandView> pairing_request_pkt = WaitForOutgoingL2capPacket();
  EXPECT_TRUE(pairing_request_pkt.has_value());
  EXPECT_EQ(Code::PAIRING_REQUEST, pairing_request_pkt->GetCode());

  // We don't care for the rest of the flow, let it die.
  pairing_handler.reset();
@@ -322,8 +340,9 @@ TEST_F(PairingHandlerUnitTest, test_remote_master_initiating) {
  // Simulate user accepting the pairing in UI
  pairing_handler->OnUiAction(PairingEvent::PAIRING_ACCEPTED, 0x01 /* Non-zero value means success */);

  EXPECT_TRUE(WaitForOutgoingL2capPacket());
  EXPECT_EQ(Code::PAIRING_RESPONSE, outgoing_l2cap_packet_->GetCode());
  std::optional<bluetooth::security::CommandView> pairing_response_pkt = WaitForOutgoingL2capPacket();
  EXPECT_TRUE(pairing_response_pkt.has_value());
  EXPECT_EQ(Code::PAIRING_RESPONSE, pairing_response_pkt->GetCode());
  // Phase 1 finished.

  // We don't care for the rest of the flow, it's handled in in other tests. let it die.