blob: 826baef0e824fd61a68c6c44a11355f18c19ac38 [file] [log] [blame]
// Copyright 2019 The Chromium 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 "ash/power/gatt_battery_controller.h"
#include "ash/power/fake_gatt_battery_poller.h"
#include "ash/power/gatt_battery_poller.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/containers/flat_map.h"
#include "base/memory/scoped_refptr.h"
#include "base/timer/timer.h"
#include "device/bluetooth/test/mock_bluetooth_adapter.h"
#include "device/bluetooth/test/mock_bluetooth_device.h"
#include "testing/gtest/include/gtest/gtest.h"
using testing::NiceMock;
using testing::Return;
namespace ash {
namespace {
class FakeGattBatteryPollerFactory : public GattBatteryPoller::Factory {
public:
FakeGattBatteryPollerFactory() = default;
~FakeGattBatteryPollerFactory() override = default;
FakeGattBatteryPoller* GetFakeBatteryPoller(const std::string& address) {
auto it = poller_map_.find(address);
return it != poller_map_.end() ? it->second : nullptr;
}
int pollers_created_count() { return pollers_created_count_; }
private:
std::unique_ptr<GattBatteryPoller> BuildInstance(
scoped_refptr<device::BluetoothAdapter> adapter,
const std::string& device_address,
std::unique_ptr<base::OneShotTimer> poll_timer) override {
++pollers_created_count_;
auto fake_gatt_battery_poller = std::make_unique<FakeGattBatteryPoller>(
device_address,
base::BindOnce(&FakeGattBatteryPollerFactory::OnPollerDestroyed,
base::Unretained(this), device_address));
poller_map_[device_address] = fake_gatt_battery_poller.get();
return std::move(fake_gatt_battery_poller);
}
void OnPollerDestroyed(const std::string address) {
poller_map_.erase(address);
}
// Map of fake Pollers, indexed by the address of their Bluetooth device.
base::flat_map<std::string, FakeGattBatteryPoller*> poller_map_;
int pollers_created_count_ = 0;
DISALLOW_COPY_AND_ASSIGN(FakeGattBatteryPollerFactory);
};
} // namespace
class GattBatteryControllerTest : public testing::Test {
public:
GattBatteryControllerTest() = default;
~GattBatteryControllerTest() override = default;
void SetUp() override {
mock_adapter_ =
base::MakeRefCounted<NiceMock<device::MockBluetoothAdapter>>();
mock_device_1_ =
std::make_unique<testing::NiceMock<device::MockBluetoothDevice>>(
nullptr /* adapter */, 0 /* bluetooth_class */, "name_1",
"address_1", true /* paired */, true /* connected */);
mock_device_2_ =
std::make_unique<testing::NiceMock<device::MockBluetoothDevice>>(
nullptr /* adapter */, 0 /* bluetooth_class */, "name_2",
"address_2", true /* paired */, true /* connected */);
fake_gatt_battery_poller_factory_ =
std::make_unique<FakeGattBatteryPollerFactory>();
GattBatteryPoller::Factory::SetFactoryForTesting(
fake_gatt_battery_poller_factory_.get());
gatt_controller_ = std::make_unique<GattBatteryController>(mock_adapter_);
}
void TearDown() override {
GattBatteryPoller::Factory::SetFactoryForTesting(nullptr);
}
void NotifyConnectedStateChanged(device::BluetoothDevice* device,
bool is_connected) {
DCHECK(gatt_controller_);
gatt_controller_->DeviceConnectedStateChanged(mock_adapter_.get(), device,
is_connected);
}
void NotifyDeviceAdded(device::BluetoothDevice* device) {
DCHECK(gatt_controller_);
gatt_controller_->DeviceAdded(mock_adapter_.get(), device);
}
void NotifyDeviceRemoved(device::BluetoothDevice* device) {
DCHECK(gatt_controller_);
gatt_controller_->DeviceRemoved(mock_adapter_.get(), device);
}
FakeGattBatteryPoller* GetFakeBatteryPoller(
device::MockBluetoothDevice* mock_device) {
return fake_gatt_battery_poller_factory_->GetFakeBatteryPoller(
mock_device->GetAddress());
}
int pollers_created_count() {
return fake_gatt_battery_poller_factory_->pollers_created_count();
}
protected:
scoped_refptr<NiceMock<device::MockBluetoothAdapter>> mock_adapter_;
std::unique_ptr<device::MockBluetoothDevice> mock_device_1_;
std::unique_ptr<device::MockBluetoothDevice> mock_device_2_;
std::unique_ptr<FakeGattBatteryPollerFactory>
fake_gatt_battery_poller_factory_;
std::unique_ptr<GattBatteryController> gatt_controller_;
private:
DISALLOW_COPY_AND_ASSIGN(GattBatteryControllerTest);
};
TEST_F(GattBatteryControllerTest,
CreatesPollerForNewConnectedDevices_ConnectedStateChanged) {
// Indicate a connection to a device was made. A Poller should be created.
NotifyConnectedStateChanged(mock_device_1_.get(), true /* is_connected */);
EXPECT_TRUE(GetFakeBatteryPoller(mock_device_1_.get()));
EXPECT_EQ(1, pollers_created_count());
// Another device connected. Should create another poller.
NotifyConnectedStateChanged(mock_device_2_.get(), true /* is_connected */);
EXPECT_TRUE(GetFakeBatteryPoller(mock_device_1_.get()));
EXPECT_TRUE(GetFakeBatteryPoller(mock_device_2_.get()));
EXPECT_EQ(2, pollers_created_count());
}
TEST_F(GattBatteryControllerTest,
CreatesPollerForNewConnectedDevices_DeviceAdded) {
NotifyDeviceAdded(mock_device_1_.get());
EXPECT_TRUE(GetFakeBatteryPoller(mock_device_1_.get()));
EXPECT_EQ(1, pollers_created_count());
NotifyDeviceAdded(mock_device_2_.get());
EXPECT_TRUE(GetFakeBatteryPoller(mock_device_1_.get()));
EXPECT_TRUE(GetFakeBatteryPoller(mock_device_2_.get()));
EXPECT_EQ(2, pollers_created_count());
}
TEST_F(GattBatteryControllerTest,
DoesntCreatePollerForAlreadyConnectedDevices_ConnectedStateChanged) {
// Simulate a device connected, should create a poller.
NotifyConnectedStateChanged(mock_device_1_.get(), true /* is_connected */);
EXPECT_TRUE(GetFakeBatteryPoller(mock_device_1_.get()));
EXPECT_EQ(1, pollers_created_count());
// Calls to DeviceConnectedStateChanged() with a connected device doesn't
// create new instances.
NotifyConnectedStateChanged(mock_device_1_.get(), true /* is_connected */);
EXPECT_EQ(1, pollers_created_count());
}
TEST_F(GattBatteryControllerTest,
DoesntCreatePollerForAlreadyConnectedDevices_DeviceAdded) {
NotifyConnectedStateChanged(mock_device_1_.get(), true /* is_connected */);
EXPECT_TRUE(GetFakeBatteryPoller(mock_device_1_.get()));
EXPECT_EQ(1, pollers_created_count());
// Calls to DeviceAdded() with a connected device doesn't create new
// instances.
NotifyDeviceAdded(mock_device_1_.get());
EXPECT_EQ(1, pollers_created_count());
}
TEST_F(GattBatteryControllerTest,
RemovesDisconnectedDevices_ConnectedStateChanged) {
NotifyConnectedStateChanged(mock_device_1_.get(), true /* is_connected */);
NotifyConnectedStateChanged(mock_device_2_.get(), true /* is_connected */);
EXPECT_TRUE(GetFakeBatteryPoller(mock_device_1_.get()));
EXPECT_TRUE(GetFakeBatteryPoller(mock_device_2_.get()));
EXPECT_EQ(2, pollers_created_count());
// Indicate a device is no longer connected.
NotifyConnectedStateChanged(mock_device_1_.get(), false /* is_connected */);
// Should stop tracking just that device.
EXPECT_FALSE(GetFakeBatteryPoller(mock_device_1_.get()));
EXPECT_TRUE(GetFakeBatteryPoller(mock_device_2_.get()));
// Disconnect the second device.
NotifyConnectedStateChanged(mock_device_2_.get(), false /* is_connected */);
EXPECT_FALSE(GetFakeBatteryPoller(mock_device_2_.get()));
EXPECT_EQ(2, pollers_created_count());
}
TEST_F(GattBatteryControllerTest, RemovesDisconnectedDevices_DeviceRemoved) {
NotifyConnectedStateChanged(mock_device_1_.get(), true /* is_connected */);
NotifyConnectedStateChanged(mock_device_2_.get(), true /* is_connected */);
EXPECT_TRUE(GetFakeBatteryPoller(mock_device_1_.get()));
EXPECT_TRUE(GetFakeBatteryPoller(mock_device_2_.get()));
EXPECT_EQ(2, pollers_created_count());
// Indicate a device is no longer connected.
NotifyDeviceRemoved(mock_device_1_.get());
// Should stop tracking just that device.
EXPECT_FALSE(GetFakeBatteryPoller(mock_device_1_.get()));
EXPECT_TRUE(GetFakeBatteryPoller(mock_device_2_.get()));
// Disconnect the second device.
NotifyDeviceRemoved(mock_device_2_.get());
EXPECT_FALSE(GetFakeBatteryPoller(mock_device_2_.get()));
EXPECT_EQ(2, pollers_created_count());
}
TEST_F(GattBatteryControllerTest,
DoesntDoAnythingRemovingUntrackedDevices_ConnectedStateChanged) {
// Indicate a device is no longer connected.
NotifyConnectedStateChanged(mock_device_1_.get(), false /* is_connected */);
// Should not create any poller nor crash.
EXPECT_EQ(0, pollers_created_count());
}
TEST_F(GattBatteryControllerTest,
DoesntDoAnythingRemovingUntrackedDevices_DeviceRemoved) {
// Indicate a device is no longer connected.
NotifyDeviceRemoved(mock_device_1_.get());
// Should not create any poller nor crash.
EXPECT_EQ(0, pollers_created_count());
}
TEST_F(GattBatteryControllerTest,
CreatesNewPollerAfterDeviceReconnects_ConnectedStateChanged) {
// Simulate a device connected.
NotifyConnectedStateChanged(mock_device_1_.get(), true /* is_connected */);
EXPECT_TRUE(GetFakeBatteryPoller(mock_device_1_.get()));
EXPECT_EQ(1, pollers_created_count());
// Indicate the device is no longer connected.
NotifyConnectedStateChanged(mock_device_1_.get(), false /* is_connected */);
EXPECT_FALSE(GetFakeBatteryPoller(mock_device_1_.get()));
// Reconnect the device.
NotifyConnectedStateChanged(mock_device_1_.get(), true /* is_connected */);
EXPECT_TRUE(GetFakeBatteryPoller(mock_device_1_.get()));
EXPECT_EQ(2, pollers_created_count());
}
TEST_F(GattBatteryControllerTest,
CreatesNewPollerAfterDeviceReconnects_DeviceAdded_DeviceRemoved) {
NotifyDeviceAdded(mock_device_1_.get());
EXPECT_TRUE(GetFakeBatteryPoller(mock_device_1_.get()));
EXPECT_EQ(1, pollers_created_count());
// Indicate the device is no longer connected.
NotifyDeviceRemoved(mock_device_1_.get());
EXPECT_FALSE(GetFakeBatteryPoller(mock_device_1_.get()));
// Reconnect the device.
NotifyDeviceAdded(mock_device_1_.get());
EXPECT_TRUE(GetFakeBatteryPoller(mock_device_1_.get()));
EXPECT_EQ(2, pollers_created_count());
}
} // namespace ash