blob: 83a7190916c70e710ac2a2aabe5622e7f8a296ba [file] [log] [blame]
#include "pairing_channel.h"
#include <memory>
#include "fbl/ref_ptr.h"
#include "src/connectivity/bluetooth/core/bt-host/common/byte_buffer.h"
#include "src/connectivity/bluetooth/core/bt-host/common/test_helpers.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/connection.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/hci.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/fake_channel_test.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/smp.h"
#include "src/lib/fxl/memory/weak_ptr.h"
namespace bt {
namespace sm {
namespace {
class FakeChannelHandler : public PairingChannel::Handler {
public:
FakeChannelHandler() : weak_ptr_factory_(this) {}
void OnRxBFrame(ByteBufferPtr data) override {
last_rx_data_ = std::move(data);
frames_received_++;
}
void OnChannelClosed() override { channel_closed_count_++; }
ByteBuffer* last_rx_data() { return last_rx_data_.get(); }
int frames_received() const { return frames_received_; }
int channel_closed_count() const { return channel_closed_count_; }
fxl::WeakPtr<PairingChannel::Handler> as_weak_handler() { return weak_ptr_factory_.GetWeakPtr(); }
private:
ByteBufferPtr last_rx_data_ = nullptr;
int frames_received_ = 0;
int channel_closed_count_ = 0;
fxl::WeakPtrFactory<PairingChannel::Handler> weak_ptr_factory_;
};
class SMP_PairingChannelTest : public l2cap::testing::FakeChannelTest {
protected:
void SetUp() override { NewPairingChannel(); }
void TearDown() override { sm_chan_ = nullptr; }
void NewPairingChannel(hci::Connection::LinkType ll_type = hci::Connection::LinkType::kLE,
uint16_t mtu = kNoSecureConnectionsMtu) {
l2cap::ChannelId cid =
ll_type == hci::Connection::LinkType::kLE ? l2cap::kLESMPChannelId : l2cap::kSMPChannelId;
ChannelOptions options(cid, mtu);
options.link_type = ll_type;
sm_chan_ = std::make_unique<PairingChannel>(CreateFakeChannel(options));
}
PairingChannel* sm_chan() { return sm_chan_.get(); }
private:
std::unique_ptr<PairingChannel> sm_chan_;
};
using SMP_PairingChannelDeathTest = SMP_PairingChannelTest;
TEST_F(SMP_PairingChannelDeathTest, L2capChannelMtuTooSmallDies) {
ASSERT_DEATH_IF_SUPPORTED(
NewPairingChannel(hci::Connection::LinkType::kLE, kNoSecureConnectionsMtu - 1),
".*max.*_sdu_size.*");
}
// This checks that PairingChannel doesn't crash when receiving events without a handler set.
TEST_F(SMP_PairingChannelTest, NoHandlerSetDataDropped) {
ASSERT_TRUE(sm_chan());
const auto kSmPacket = CreateStaticByteBuffer(kPairingFailed, ErrorCode::kPairingNotSupported);
fake_chan()->Receive(kSmPacket);
RunLoopUntilIdle();
fake_chan()->Close();
RunLoopUntilIdle();
}
TEST_F(SMP_PairingChannelTest, SetHandlerReceivesData) {
ASSERT_TRUE(sm_chan());
const auto kSmPacket1 = CreateStaticByteBuffer(kPairingFailed, ErrorCode::kPairingNotSupported);
const auto kSmPacket2 = CreateStaticByteBuffer(kPairingFailed, ErrorCode::kConfirmValueFailed);
FakeChannelHandler handler;
sm_chan()->SetChannelHandler(handler.as_weak_handler());
ASSERT_EQ(handler.last_rx_data(), nullptr);
ASSERT_EQ(handler.frames_received(), 0);
fake_chan()->Receive(kSmPacket1);
RunLoopUntilIdle();
ASSERT_NE(handler.last_rx_data(), nullptr);
EXPECT_TRUE(ContainersEqual(*handler.last_rx_data(), kSmPacket1));
ASSERT_EQ(handler.frames_received(), 1);
fake_chan()->Receive(kSmPacket2);
RunLoopUntilIdle();
ASSERT_NE(handler.last_rx_data(), nullptr);
EXPECT_TRUE(ContainersEqual(*handler.last_rx_data(), kSmPacket2));
ASSERT_EQ(handler.frames_received(), 2);
fake_chan()->Close();
RunLoopUntilIdle();
ASSERT_EQ(handler.channel_closed_count(), 1);
}
TEST_F(SMP_PairingChannelTest, ChangeHandlerNewHandlerReceivesData) {
ASSERT_TRUE(sm_chan());
const auto kSmPacket1 = CreateStaticByteBuffer(kPairingFailed, ErrorCode::kPairingNotSupported);
const auto kSmPacket2 = CreateStaticByteBuffer(kPairingFailed, ErrorCode::kConfirmValueFailed);
FakeChannelHandler handler;
sm_chan()->SetChannelHandler(handler.as_weak_handler());
ASSERT_EQ(handler.last_rx_data(), nullptr);
ASSERT_EQ(handler.frames_received(), 0);
fake_chan()->Receive(kSmPacket1);
RunLoopUntilIdle();
ASSERT_NE(handler.last_rx_data(), nullptr);
EXPECT_TRUE(ContainersEqual(*handler.last_rx_data(), kSmPacket1));
ASSERT_EQ(handler.frames_received(), 1);
FakeChannelHandler new_handler;
ASSERT_EQ(new_handler.last_rx_data(), nullptr);
sm_chan()->SetChannelHandler(new_handler.as_weak_handler());
fake_chan()->Receive(kSmPacket2);
RunLoopUntilIdle();
ASSERT_NE(new_handler.last_rx_data(), nullptr);
EXPECT_TRUE(ContainersEqual(*new_handler.last_rx_data(), kSmPacket2));
ASSERT_EQ(new_handler.frames_received(), 1);
// Check handler's data hasn't changed.
EXPECT_TRUE(ContainersEqual(*handler.last_rx_data(), kSmPacket1));
ASSERT_EQ(handler.frames_received(), 1);
fake_chan()->Close();
RunLoopUntilIdle();
ASSERT_EQ(new_handler.channel_closed_count(), 1);
ASSERT_EQ(handler.channel_closed_count(), 0);
}
} // namespace
} // namespace sm
} // namespace bt