blob: c4e314c19f2aa2c99ce33cae7fd07210c8868687 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "socket_factory.h"
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <memory>
#include <type_traits>
#include <gtest/gtest.h>
#include "src/connectivity/bluetooth/core/bt-host/l2cap/channel.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/fake_channel.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/l2cap_defs.h"
#include "src/connectivity/bluetooth/core/bt-host/sco/sco_connection.h"
namespace bt::socket {
namespace {
// We'll test the template just for L2CAP channels.
using FactoryT = SocketFactory<l2cap::Channel>;
constexpr l2cap::ChannelId kDynamicChannelIdMin = 0x0040;
constexpr l2cap::ChannelId kRemoteChannelId = 0x0050;
constexpr hci_spec::ConnectionHandle kDefaultConnectionHandle = 0x0001;
constexpr hci_spec::ConnectionHandle kAnotherConnectionHandle = 0x0002;
class SocketFactoryTest : public ::testing::Test {
public:
SocketFactoryTest() : loop_(&kAsyncLoopConfigAttachToCurrentThread) {
EXPECT_EQ(ASYNC_LOOP_RUNNABLE, loop_.GetState());
channel_ = fbl::MakeRefCounted<l2cap::testing::FakeChannel>(
kDynamicChannelIdMin, kRemoteChannelId, kDefaultConnectionHandle, bt::LinkType::kACL);
EXPECT_TRUE(channel_);
}
void TearDown() {
// Process any pending events, to tickle any use-after-free bugs.
RunLoopUntilIdle();
}
protected:
fbl::RefPtr<l2cap::testing::FakeChannel> channel() { return channel_; }
async_dispatcher_t* dispatcher() { return loop_.dispatcher(); }
void RunLoopUntilIdle() { loop_.RunUntilIdle(); }
private:
async::Loop loop_;
fbl::RefPtr<l2cap::testing::FakeChannel> channel_;
};
TEST_F(SocketFactoryTest, TemplatesCompile) { socket::SocketFactory<l2cap::Channel> l2cap_factory; }
TEST_F(SocketFactoryTest, CanCreateSocket) {
FactoryT socket_factory;
EXPECT_TRUE(socket_factory.MakeSocketForChannel(channel()));
}
TEST_F(SocketFactoryTest, SocketCreationFailsIfChannelIsNullptr) {
FactoryT socket_factory;
EXPECT_FALSE(socket_factory.MakeSocketForChannel(nullptr));
}
TEST_F(SocketFactoryTest, SocketCreationFailsIfChannelAlreadyHasASocket) {
FactoryT socket_factory;
zx::socket socket = socket_factory.MakeSocketForChannel(channel());
ASSERT_TRUE(socket);
EXPECT_FALSE(socket_factory.MakeSocketForChannel(channel()));
}
TEST_F(SocketFactoryTest, SocketCreationFailsIfChannelActivationFails) {
channel()->set_activate_fails(true);
EXPECT_FALSE(FactoryT().MakeSocketForChannel(channel()));
}
TEST_F(SocketFactoryTest, CanCreateSocketForNewChannelWithRecycledId) {
FactoryT socket_factory;
auto original_channel = fbl::MakeRefCounted<l2cap::testing::FakeChannel>(
kDynamicChannelIdMin + 1, kRemoteChannelId, kDefaultConnectionHandle, bt::LinkType::kACL);
zx::socket socket = socket_factory.MakeSocketForChannel(original_channel);
ASSERT_TRUE(socket);
original_channel->Close();
RunLoopUntilIdle(); // Process any events related to channel closure.
auto new_channel = fbl::MakeRefCounted<l2cap::testing::FakeChannel>(
kDynamicChannelIdMin + 1, kRemoteChannelId, kDefaultConnectionHandle, bt::LinkType::kACL);
EXPECT_TRUE(socket_factory.MakeSocketForChannel(new_channel));
}
TEST_F(SocketFactoryTest, DestructionWithActiveRelayDoesNotCrash) {
FactoryT socket_factory;
zx::socket socket = socket_factory.MakeSocketForChannel(channel());
ASSERT_TRUE(socket);
// |socket_factory| is destroyed implicitly.
}
TEST_F(SocketFactoryTest, DestructionAfterDeactivatingRelayDoesNotCrash) {
FactoryT socket_factory;
zx::socket socket = socket_factory.MakeSocketForChannel(channel());
ASSERT_TRUE(socket);
channel()->Close();
RunLoopUntilIdle(); // Process any events related to channel closure.
// |socket_factory| is destroyed implicitly.
}
TEST_F(SocketFactoryTest, SameChannelIdDifferentHandles) {
FactoryT socket_factory;
EXPECT_TRUE(socket_factory.MakeSocketForChannel(channel()));
auto another_channel = fbl::MakeRefCounted<l2cap::testing::FakeChannel>(
kDynamicChannelIdMin, kRemoteChannelId, kAnotherConnectionHandle, bt::LinkType::kACL);
EXPECT_TRUE(socket_factory.MakeSocketForChannel(another_channel));
}
} // namespace
} // namespace bt::socket