blob: d5c16308fe6c5f54901da62fcc4f60b9e240cefe [file] [log] [blame]
// Copyright (c) 2013 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 "chromeos/network/geolocation_handler.h"
#include <memory>
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/test/scoped_task_environment.h"
#include "base/values.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/shill_manager_client.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
namespace chromeos {
class GeolocationHandlerTest : public testing::Test {
public:
GeolocationHandlerTest()
: scoped_task_environment_(
base::test::ScopedTaskEnvironment::MainThreadType::UI) {}
~GeolocationHandlerTest() override = default;
void SetUp() override {
// Initialize DBusThreadManager with a stub implementation.
DBusThreadManager::Initialize();
// Get the test interface for manager / device.
manager_test_ =
DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface();
ASSERT_TRUE(manager_test_);
geolocation_handler_.reset(new GeolocationHandler());
geolocation_handler_->Init();
base::RunLoop().RunUntilIdle();
}
void TearDown() override {
geolocation_handler_.reset();
DBusThreadManager::Shutdown();
}
bool GetWifiAccessPoints() {
return geolocation_handler_->GetWifiAccessPoints(&wifi_access_points_,
nullptr);
}
bool GetCellTowers() {
return geolocation_handler_->GetNetworkInformation(nullptr, &cell_towers_);
}
// This should remain in sync with the format of shill (chromeos) dict entries
// Shill provides us Cell ID and LAC in hex, but all other fields in decimal.
void AddAccessPoint(int idx) {
base::DictionaryValue properties;
std::string mac_address =
base::StringPrintf("%02X:%02X:%02X:%02X:%02X:%02X",
idx, 0, 0, 0, 0, 0);
std::string channel = base::IntToString(idx);
std::string strength = base::IntToString(idx * 10);
properties.SetKey(shill::kGeoMacAddressProperty, base::Value(mac_address));
properties.SetKey(shill::kGeoChannelProperty, base::Value(channel));
properties.SetKey(shill::kGeoSignalStrengthProperty, base::Value(strength));
manager_test_->AddGeoNetwork(shill::kGeoWifiAccessPointsProperty,
properties);
base::RunLoop().RunUntilIdle();
}
// This should remain in sync with the format of shill (chromeos) dict entries
void AddCellTower(int idx) {
base::DictionaryValue properties;
// Multiplications, additions, and string concatenations
// are intended solely to differentiate the various fields
// in a predictable way, while preserving 3 digits for MCC and MNC.
std::string ci = base::IntToString(idx) + "D3A15F2";
std::string lac = "7FF" + base::IntToString(idx);
std::string mcc = base::IntToString(idx * 100);
std::string mnc = base::IntToString(idx * 100 + 1);
properties.SetKey(shill::kGeoCellIdProperty, base::Value(ci));
properties.SetKey(shill::kGeoLocationAreaCodeProperty, base::Value(lac));
properties.SetKey(shill::kGeoMobileCountryCodeProperty, base::Value(mcc));
properties.SetKey(shill::kGeoMobileNetworkCodeProperty, base::Value(mnc));
manager_test_->AddGeoNetwork(shill::kGeoCellTowersProperty, properties);
base::RunLoop().RunUntilIdle();
}
protected:
base::test::ScopedTaskEnvironment scoped_task_environment_;
std::unique_ptr<GeolocationHandler> geolocation_handler_;
ShillManagerClient::TestInterface* manager_test_ = nullptr;
WifiAccessPointVector wifi_access_points_;
CellTowerVector cell_towers_;
private:
DISALLOW_COPY_AND_ASSIGN(GeolocationHandlerTest);
};
TEST_F(GeolocationHandlerTest, NoAccessPoints) {
// Inititial call should return false.
EXPECT_FALSE(GetWifiAccessPoints());
EXPECT_FALSE(GetCellTowers());
base::RunLoop().RunUntilIdle();
// Second call should return false since there are no devices.
EXPECT_FALSE(GetWifiAccessPoints());
EXPECT_FALSE(GetCellTowers());
}
TEST_F(GeolocationHandlerTest, OneAccessPoint) {
// Add an access point.
AddAccessPoint(1);
base::RunLoop().RunUntilIdle();
// Inititial call should return false and request access points.
EXPECT_FALSE(GetWifiAccessPoints());
base::RunLoop().RunUntilIdle();
// Second call should return true since we have an access point.
EXPECT_TRUE(GetWifiAccessPoints());
ASSERT_EQ(1u, wifi_access_points_.size());
EXPECT_EQ("01:00:00:00:00:00", wifi_access_points_[0].mac_address);
EXPECT_EQ(1, wifi_access_points_[0].channel);
}
TEST_F(GeolocationHandlerTest, MultipleAccessPoints) {
// Add several access points.
AddAccessPoint(1);
AddAccessPoint(2);
AddAccessPoint(3);
base::RunLoop().RunUntilIdle();
// Inititial call should return false and request access points.
EXPECT_FALSE(GetWifiAccessPoints());
EXPECT_FALSE(GetCellTowers());
base::RunLoop().RunUntilIdle();
// Second call should return true since we have an access point.
EXPECT_TRUE(GetWifiAccessPoints());
ASSERT_EQ(3u, wifi_access_points_.size());
EXPECT_EQ("02:00:00:00:00:00", wifi_access_points_[1].mac_address);
EXPECT_EQ(3, wifi_access_points_[2].channel);
}
TEST_F(GeolocationHandlerTest, OneCellTower) {
// Add a cell tower.
AddCellTower(1);
base::RunLoop().RunUntilIdle();
// Inititial call should return false and request towers.
EXPECT_FALSE(GetCellTowers());
EXPECT_FALSE(GetWifiAccessPoints());
base::RunLoop().RunUntilIdle();
// Second call should return true since we have a cell tower.
EXPECT_TRUE(GetCellTowers());
EXPECT_FALSE(GetWifiAccessPoints());
ASSERT_EQ(1u, cell_towers_.size());
EXPECT_EQ("490345970", cell_towers_[0].ci);
EXPECT_EQ("32753", cell_towers_[0].lac);
EXPECT_EQ("100", cell_towers_[0].mcc);
EXPECT_EQ("101", cell_towers_[0].mnc);
}
TEST_F(GeolocationHandlerTest, MultipleCellTowers) {
// Add several cell towers.
AddCellTower(1);
AddCellTower(2);
AddCellTower(3);
base::RunLoop().RunUntilIdle();
// Inititial call should return false and request cell towers.
EXPECT_FALSE(GetWifiAccessPoints());
EXPECT_FALSE(GetCellTowers());
base::RunLoop().RunUntilIdle();
// Second call should return true since we have a cell tower.
EXPECT_FALSE(GetWifiAccessPoints());
EXPECT_TRUE(GetCellTowers());
ASSERT_EQ(3u, cell_towers_.size());
EXPECT_EQ("32754", cell_towers_[1].lac);
EXPECT_EQ("301", cell_towers_[2].mnc);
}
TEST_F(GeolocationHandlerTest, MultipleGeolocations) {
// Add both a cell tower and wifi AP.
AddCellTower(1);
AddCellTower(2);
AddAccessPoint(1);
AddAccessPoint(2);
base::RunLoop().RunUntilIdle();
// Inititial call should return false and request towers.
EXPECT_FALSE(GetCellTowers());
EXPECT_FALSE(GetWifiAccessPoints());
base::RunLoop().RunUntilIdle();
// Second call should return true since we have a cell tower.
EXPECT_TRUE(GetCellTowers());
EXPECT_TRUE(GetWifiAccessPoints());
ASSERT_EQ(2u, wifi_access_points_.size());
EXPECT_EQ("02:00:00:00:00:00", wifi_access_points_[1].mac_address);
EXPECT_EQ(1, wifi_access_points_[0].channel);
ASSERT_EQ(2u, cell_towers_.size());
EXPECT_EQ("758781426", cell_towers_[1].ci);
EXPECT_EQ("32753", cell_towers_[0].lac);
EXPECT_EQ("200", cell_towers_[1].mcc);
EXPECT_EQ("101", cell_towers_[0].mnc);
}
} // namespace chromeos