#include "services/device/geolocation/wifi_data_provider_common.h"
#include <memory>
#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/task_environment.h"
#include "services/device/geolocation/wifi_data_provider_handle.h"
#include "services/device/public/mojom/geolocation_internals.mojom.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using testing::_;
using testing::AnyNumber;
using testing::AtLeast;
using testing::DoAll;
using testing::Return;
using testing::SetArgPointee;
using testing::WithArgs;
namespace device {
class MockWlanApi : public WifiDataProviderCommon::WlanApiInterface {
public:
MockWlanApi() {
ON_CALL(*this, GetAccessPointData)
.WillByDefault(WithArgs<0>(
[](base::OnceCallback<void(
std::unique_ptr<WifiData::AccessPointDataSet>)> callback) {
std::move(callback).Run(
std::make_unique<WifiData::AccessPointDataSet>());
}));
}
MOCK_METHOD(
void,
GetAccessPointData,
(base::OnceCallback<void(std::unique_ptr<WifiData::AccessPointDataSet>)>),
(override));
};
class MockPollingPolicy : public WifiPollingPolicy {
public:
MockPollingPolicy() {
ON_CALL(*this, InitialInterval()).WillByDefault(Return(0));
ON_CALL(*this, PollingInterval()).WillByDefault(Return(1));
ON_CALL(*this, NoWifiInterval()).WillByDefault(Return(1));
EXPECT_CALL(*this, UpdatePollingInterval(_)).Times(AnyNumber());
}
MOCK_METHOD1(UpdatePollingInterval, void(bool));
MOCK_METHOD0(InitialInterval, int());
MOCK_METHOD0(PollingInterval, int());
MOCK_METHOD0(NoWifiInterval, int());
void FillDiagnostics(mojom::WifiPollingPolicyDiagnostics&) override {}
};
class WifiDataProviderCommonWithMock : public WifiDataProviderCommon {
public:
WifiDataProviderCommonWithMock() : wlan_api_(new MockWlanApi) {}
WifiDataProviderCommonWithMock(const WifiDataProviderCommonWithMock&) =
delete;
WifiDataProviderCommonWithMock& operator=(
const WifiDataProviderCommonWithMock&) = delete;
std::unique_ptr<WlanApiInterface> CreateWlanApi() override {
return std::move(wlan_api_);
}
std::unique_ptr<WifiPollingPolicy> CreatePollingPolicy() override {
auto policy = std::make_unique<MockPollingPolicy>();
polling_policy_ = policy.get();
return std::move(policy);
}
std::unique_ptr<MockWlanApi> wlan_api_;
raw_ptr<MockPollingPolicy, DanglingUntriaged> polling_policy_ = nullptr;
private:
~WifiDataProviderCommonWithMock() override = default;
};
class GeolocationWifiDataProviderCommonTest : public testing::Test {
public:
GeolocationWifiDataProviderCommonTest()
: task_environment_(
base::test::SingleThreadTaskEnvironment::MainThreadType::UI),
wifi_data_callback_(base::DoNothing()) {}
void TearDownProvider() {
provider_->RemoveCallback(&wifi_data_callback_);
provider_->StopDataProvider();
provider_ = nullptr;
wlan_api_ = nullptr;
}
void RecreateProvider() {
if (provider_)
TearDownProvider();
provider_ = new WifiDataProviderCommonWithMock;
provider_->AddCallback(&wifi_data_callback_);
wlan_api_ = provider_->wlan_api_.get();
if (!polling_policy_) {
WifiPollingPolicy::Initialize(provider_->CreatePollingPolicy());
polling_policy_ = provider_->polling_policy_;
}
}
void SetUp() override { RecreateProvider(); }
void TearDown() override {
TearDownProvider();
WifiPollingPolicy::Shutdown();
polling_policy_ = nullptr;
}
protected:
const base::test::SingleThreadTaskEnvironment task_environment_;
WifiDataProviderHandle::WifiDataUpdateCallback wifi_data_callback_;
scoped_refptr<WifiDataProviderCommonWithMock> provider_;
raw_ptr<MockWlanApi, DanglingUntriaged> wlan_api_ = nullptr;
raw_ptr<MockPollingPolicy, DanglingUntriaged> polling_policy_ = nullptr;
};
TEST_F(GeolocationWifiDataProviderCommonTest, CreateDestroy) {
EXPECT_TRUE(provider_);
EXPECT_TRUE(wlan_api_);
EXPECT_TRUE(polling_policy_);
}
TEST_F(GeolocationWifiDataProviderCommonTest, NoWifi) {
base::RunLoop run_loop;
EXPECT_CALL(*polling_policy_, InitialInterval()).Times(1);
EXPECT_CALL(*polling_policy_, NoWifiInterval()).Times(AtLeast(1));
EXPECT_CALL(*wlan_api_, GetAccessPointData)
.WillOnce(WithArgs<0>(
[&run_loop](
base::OnceCallback<void(
std::unique_ptr<WifiData::AccessPointDataSet>)> callback) {
std::move(callback).Run(nullptr);
run_loop.Quit();
}));
provider_->StartDataProvider();
run_loop.Run();
}
TEST_F(GeolocationWifiDataProviderCommonTest, IntermittentWifi) {
base::RunLoop run_loop;
EXPECT_CALL(*polling_policy_, InitialInterval()).Times(1);
EXPECT_CALL(*polling_policy_, PollingInterval()).Times(AtLeast(1));
EXPECT_CALL(*polling_policy_, NoWifiInterval()).Times(1);
EXPECT_CALL(*wlan_api_, GetAccessPointData)
.WillOnce(WithArgs<0>(
[](base::OnceCallback<void(
std::unique_ptr<WifiData::AccessPointDataSet>)> callback) {
std::move(callback).Run(
std::make_unique<WifiData::AccessPointDataSet>());
}))
.WillOnce(WithArgs<0>(
[&run_loop](
base::OnceCallback<void(
std::unique_ptr<WifiData::AccessPointDataSet>)> callback) {
std::move(callback).Run(nullptr);
run_loop.Quit();
}));
provider_->StartDataProvider();
run_loop.Run();
}
TEST_F(GeolocationWifiDataProviderCommonTest, DoAnEmptyScan) {
base::RunLoop run_loop;
EXPECT_CALL(*polling_policy_, InitialInterval()).Times(1);
EXPECT_CALL(*polling_policy_, PollingInterval()).Times(AtLeast(1));
EXPECT_CALL(*wlan_api_, GetAccessPointData)
.WillOnce(WithArgs<0>(
[&run_loop](
base::OnceCallback<void(
std::unique_ptr<WifiData::AccessPointDataSet>)> callback) {
std::move(callback).Run(
std::make_unique<WifiData::AccessPointDataSet>());
run_loop.Quit();
}));
provider_->StartDataProvider();
run_loop.Run();
WifiData data;
EXPECT_TRUE(provider_->GetData(&data));
EXPECT_TRUE(data.access_point_data.empty());
}
TEST_F(GeolocationWifiDataProviderCommonTest, DoScanWithResults) {
base::RunLoop run_loop;
EXPECT_CALL(*polling_policy_, InitialInterval()).Times(1);
EXPECT_CALL(*polling_policy_, PollingInterval()).Times(AtLeast(1));
mojom::AccessPointData single_access_point;
single_access_point.channel = 2;
single_access_point.mac_address = "00:11:22:33:44:55";
single_access_point.radio_signal_strength = 4;
single_access_point.signal_to_noise = 5;
WifiData::AccessPointDataSet data_out({single_access_point});
EXPECT_CALL(*wlan_api_, GetAccessPointData)
.WillOnce(WithArgs<0>(
[&data_out, &run_loop](
base::OnceCallback<void(
std::unique_ptr<WifiData::AccessPointDataSet>)> callback) {
auto new_data = std::make_unique<WifiData::AccessPointDataSet>();
*new_data = data_out;
std::move(callback).Run(std::move(new_data));
run_loop.Quit();
}));
provider_->StartDataProvider();
run_loop.Run();
WifiData data;
EXPECT_TRUE(provider_->GetData(&data));
ASSERT_EQ(1u, data.access_point_data.size());
EXPECT_EQ(single_access_point.mac_address,
data.access_point_data.begin()->mac_address);
}
TEST_F(GeolocationWifiDataProviderCommonTest, DelayedByPolicy) {
static const int kPollingIntervalMillis = 1000;
base::RunLoop run_loop;
EXPECT_CALL(*polling_policy_, InitialInterval())
.WillOnce(Return(0))
.WillOnce(Return(kPollingIntervalMillis));
EXPECT_CALL(*polling_policy_, PollingInterval())
.WillOnce(Return(kPollingIntervalMillis));
EXPECT_CALL(*wlan_api_, GetAccessPointData)
.WillOnce(WithArgs<0>(
[&run_loop](
base::OnceCallback<void(
std::unique_ptr<WifiData::AccessPointDataSet>)> callback) {
std::move(callback).Run(
std::make_unique<WifiData::AccessPointDataSet>());
run_loop.Quit();
}));
provider_->StartDataProvider();
EXPECT_FALSE(provider_->DelayedByPolicy());
run_loop.Run();
EXPECT_TRUE(provider_->DelayedByPolicy());
RecreateProvider();
provider_->StartDataProvider();
EXPECT_TRUE(provider_->DelayedByPolicy());
}
}