blob: b2f996358e3833e16989e61d90dc8763df8008b9 [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "device/bluetooth/floss/floss_dbus_manager.h"
#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/test/task_environment.h"
#include "base/test/test_future.h"
#include "device/bluetooth/floss/floss_dbus_client.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace floss {
namespace {
// This has to be different from FlossDBusManager::Get()->active_adapter_;
const int kMockAdapterIndex = 1;
} // namespace
using testing::DoAll;
class FlossDBusManagerTest : public testing::Test {
public:
FlossDBusManagerTest() = default;
void SetUp() override { FlossDBusManager::InitializeFake(); }
void TearDown() override { FlossDBusManager::Shutdown(); }
void SwitchAdapterOnTest() {
base::test::TestFuture<void> ready;
FlossDBusManager::Get()->SwitchAdapter(kMockAdapterIndex,
ready.GetCallback());
// Callback is not called since not all clients interface are present
EXPECT_FALSE(ready.IsReady());
PresentAllClients();
// Callback is called since all clients interface are present
EXPECT_TRUE(ready.Wait());
}
void SwitchAdapterOnTimeoutTest() {
base::test::TestFuture<void> ready;
FlossDBusManager::Get()->SwitchAdapter(kMockAdapterIndex,
ready.GetCallback());
// Callback is not called since not all clients interface are present
EXPECT_FALSE(ready.IsReady());
TriggerClientInitializerTimeout();
// Callback is called because of timeout
EXPECT_TRUE(ready.Wait());
}
void SwitchAdapterOnPartiallyPresentTimeoutTest() {
base::test::TestFuture<void> ready;
FlossDBusManager::Get()->SwitchAdapter(kMockAdapterIndex,
ready.GetCallback());
// Callback is not called since not all clients interface are present
EXPECT_FALSE(ready.IsReady());
PresentAllClientsExceptForGatt();
// Callback is not called since not all clients interface are present
EXPECT_FALSE(ready.IsReady());
TriggerClientInitializerTimeout();
// Callback is called because of timeout
EXPECT_TRUE(ready.Wait());
// If the client API is present later, we shouldn't crash.
PresentGattClient();
base::RunLoop().RunUntilIdle();
}
void SwitchAdapterOffTest() {
base::test::TestFuture<void> ready;
FlossDBusManager::Get()->SwitchAdapter(FlossDBusManager::kInvalidAdapter,
ready.GetCallback());
// Callback should be called immediately.
EXPECT_TRUE(ready.Wait());
UnpresentAllClients();
}
protected:
void PresentAllClients() {
FlossDBusManager::Get()->ObjectAdded(
FlossDBusClient::GenerateAdapterPath(kMockAdapterIndex),
kAdapterInterface);
FlossDBusManager::Get()->ObjectAdded(
FlossDBusClient::GenerateLoggingPath(kMockAdapterIndex),
kAdapterLoggingInterface);
#if BUILDFLAG(IS_CHROMEOS)
FlossDBusManager::Get()->ObjectAdded(
FlossDBusClient::GenerateAdminPath(kMockAdapterIndex), kAdminInterface);
#endif
FlossDBusManager::Get()->ObjectAdded(
FlossDBusClient::GenerateBatteryManagerPath(kMockAdapterIndex),
kBatteryManagerInterface);
FlossDBusManager::Get()->ObjectAdded(
FlossDBusClient::GenerateBluetoothTelephonyPath(kMockAdapterIndex),
kBluetoothTelephonyInterface);
FlossDBusManager::Get()->ObjectAdded(
FlossDBusClient::GenerateGattPath(kMockAdapterIndex), kGattInterface);
FlossDBusManager::Get()->ObjectAdded(
FlossDBusClient::GenerateAdapterPath(kMockAdapterIndex),
kSocketManagerInterface);
}
void PresentAllClientsExceptForGatt() {
FlossDBusManager::Get()->ObjectAdded(
FlossDBusClient::GenerateAdapterPath(kMockAdapterIndex),
kAdapterInterface);
FlossDBusManager::Get()->ObjectAdded(
FlossDBusClient::GenerateLoggingPath(kMockAdapterIndex),
kAdapterLoggingInterface);
#if BUILDFLAG(IS_CHROMEOS)
FlossDBusManager::Get()->ObjectAdded(
FlossDBusClient::GenerateAdminPath(kMockAdapterIndex), kAdminInterface);
#endif
FlossDBusManager::Get()->ObjectAdded(
FlossDBusClient::GenerateBatteryManagerPath(kMockAdapterIndex),
kBatteryManagerInterface);
FlossDBusManager::Get()->ObjectAdded(
FlossDBusClient::GenerateBluetoothTelephonyPath(kMockAdapterIndex),
kBluetoothTelephonyInterface);
FlossDBusManager::Get()->ObjectAdded(
FlossDBusClient::GenerateAdapterPath(kMockAdapterIndex),
kSocketManagerInterface);
}
void PresentGattClient() {
FlossDBusManager::Get()->ObjectAdded(
FlossDBusClient::GenerateGattPath(kMockAdapterIndex), kGattInterface);
}
void UnpresentAllClients() {
FlossDBusManager::Get()->ObjectRemoved(
FlossDBusClient::GenerateAdapterPath(kMockAdapterIndex),
kAdapterInterface);
FlossDBusManager::Get()->ObjectRemoved(
FlossDBusClient::GenerateLoggingPath(kMockAdapterIndex),
kAdapterLoggingInterface);
#if BUILDFLAG(IS_CHROMEOS)
FlossDBusManager::Get()->ObjectRemoved(
FlossDBusClient::GenerateAdminPath(kMockAdapterIndex), kAdminInterface);
#endif
FlossDBusManager::Get()->ObjectRemoved(
FlossDBusClient::GenerateBatteryManagerPath(kMockAdapterIndex),
kBatteryManagerInterface);
FlossDBusManager::Get()->ObjectRemoved(
FlossDBusClient::GenerateBluetoothTelephonyPath(kMockAdapterIndex),
kBluetoothTelephonyInterface);
FlossDBusManager::Get()->ObjectRemoved(
FlossDBusClient::GenerateGattPath(kMockAdapterIndex), kGattInterface);
FlossDBusManager::Get()->ObjectRemoved(
FlossDBusClient::GenerateAdapterPath(kMockAdapterIndex),
kSocketManagerInterface);
}
void TriggerClientInitializerTimeout() {
task_environment_.FastForwardBy(
base::Milliseconds(FlossDBusManager::kClientReadyTimeoutMs));
}
base::test::SingleThreadTaskEnvironment task_environment_{
base::test::TaskEnvironment::TimeSource::MOCK_TIME};
};
// Make sure callback is called after all clients API present
TEST_F(FlossDBusManagerTest, AllClientsReadyBeforeTimeout) {
SwitchAdapterOnTest();
}
// Make sure callback is not called until timeout
TEST_F(FlossDBusManagerTest, NotAllClientsReadyBeforeTimeout) {
SwitchAdapterOnPartiallyPresentTimeoutTest();
}
// Make sure callback is called immediately after switch adapter off.
TEST_F(FlossDBusManagerTest, AdapterOffCallImmediately) {
SwitchAdapterOnTest();
SwitchAdapterOffTest();
}
// Make sure callback is called correctly after an adapter power cycle.
TEST_F(FlossDBusManagerTest, RestartAdapterClientPresent) {
SwitchAdapterOnTest();
SwitchAdapterOffTest();
SwitchAdapterOnTest();
}
// Make sure callback is called correctly after an adapter power cycle.
TEST_F(FlossDBusManagerTest, RestartAdapterTriggerTimeout) {
SwitchAdapterOnTest();
SwitchAdapterOffTest();
SwitchAdapterOnTimeoutTest();
}
} // namespace floss