blob: 5f37a63a18a78eccec6366498005ad4f50c3737e [file] [log] [blame]
// Copyright (c) 2012 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/network_state_handler.h"
#include <stddef.h>
#include <algorithm>
#include <map>
#include <memory>
#include <set>
#include <string>
#include "base/bind.h"
#include "base/command_line.h"
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/test/scoped_task_environment.h"
#include "base/values.h"
#include "chromeos/chromeos_switches.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/shill_device_client.h"
#include "chromeos/dbus/shill_ipconfig_client.h"
#include "chromeos/dbus/shill_manager_client.h"
#include "chromeos/dbus/shill_profile_client.h"
#include "chromeos/dbus/shill_service_client.h"
#include "chromeos/network/device_state.h"
#include "chromeos/network/network_state.h"
#include "chromeos/network/network_state_handler_observer.h"
#include "chromeos/network/tether_constants.h"
#include "dbus/object_path.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
namespace chromeos {
namespace {
void ErrorCallbackFunction(const std::string& error_name,
const std::string& error_message) {
LOG(ERROR) << "Shill Error: " << error_name << " : " << error_message;
}
const char kShillManagerClientStubWifiDevice[] = "/device/stub_wifi_device1";
const char kShillManagerClientStubCellularDevice[] =
"/device/stub_cellular_device1";
const char kShillManagerClientStubDefaultService[] = "/service/eth1";
const char kShillManagerClientStubDefaultWifi[] = "/service/wifi1";
const char kShillManagerClientStubWifi2[] = "/service/wifi2";
const char kShillManagerClientStubCellular[] = "/service/cellular1";
const char kWifiGuid1[] = "wifi1";
const char kWifiName1[] = "WiFi 1";
const char kTetherGuid1[] = "tether1";
const char kTetherGuid2[] = "tether2";
const char kTetherName1[] = "Device1";
const char kTetherName2[] = "Device2";
const char kTetherCarrier1[] = "Carrier1";
const char kTetherCarrier2[] = "Carrier2";
const int kTetherBatteryPercentage1 = 85;
const int kTetherBatteryPercentage2 = 90;
const int kTetherSignalStrength1 = 75;
const int kTetherSignalStrength2 = 80;
const bool kTetherHasConnectedToHost1 = true;
const bool kTetherHasConnectedToHost2 = false;
using chromeos::DeviceState;
using chromeos::NetworkState;
using chromeos::NetworkStateHandler;
class TestObserver final : public chromeos::NetworkStateHandlerObserver {
public:
explicit TestObserver(NetworkStateHandler* handler)
: handler_(handler),
device_list_changed_count_(0),
device_count_(0),
network_list_changed_count_(0),
network_count_(0),
default_network_change_count_(0),
scan_requested_count_(0),
scan_completed_count_(0) {}
~TestObserver() override = default;
void DeviceListChanged() override {
NetworkStateHandler::DeviceStateList devices;
handler_->GetDeviceList(&devices);
device_count_ = devices.size();
++device_list_changed_count_;
}
void NetworkListChanged() override {
NetworkStateHandler::NetworkStateList networks;
handler_->GetNetworkListByType(chromeos::NetworkTypePattern::Default(),
false /* configured_only */,
false /* visible_only */,
0 /* no limit */,
&networks);
network_count_ = networks.size();
if (network_count_ == 0) {
default_network_ = "";
default_network_connection_state_ = "";
}
++network_list_changed_count_;
}
void DefaultNetworkChanged(const NetworkState* network) override {
EXPECT_TRUE(!network || network->IsConnectedState());
++default_network_change_count_;
default_network_ = network ? network->path() : "";
default_network_connection_state_ =
network ? network->connection_state() : "";
VLOG(1) << "DefaultNetworkChanged: " << default_network_
<< " State: " << default_network_connection_state_;
}
void NetworkConnectionStateChanged(const NetworkState* network) override {
network_connection_state_[network->path()] = network->connection_state();
connection_state_changes_[network->path()]++;
}
void NetworkPropertiesUpdated(const NetworkState* network) override {
DCHECK(network);
property_updates_[network->path()]++;
}
void DevicePropertiesUpdated(const DeviceState* device) override {
DCHECK(device);
device_property_updates_[device->path()]++;
}
void ScanRequested() override { scan_requested_count_++; }
void ScanCompleted(const DeviceState* device) override {
DCHECK(device);
scan_completed_count_++;
}
size_t device_list_changed_count() { return device_list_changed_count_; }
size_t device_count() { return device_count_; }
size_t network_list_changed_count() { return network_list_changed_count_; }
size_t network_count() { return network_count_; }
size_t default_network_change_count() {
return default_network_change_count_;
}
size_t scan_requested_count() { return scan_requested_count_; }
size_t scan_completed_count() { return scan_completed_count_; }
void reset_change_counts() {
VLOG(1) << "=== RESET CHANGE COUNTS ===";
default_network_change_count_ = 0;
device_list_changed_count_ = 0;
network_list_changed_count_ = 0;
scan_requested_count_ = 0;
scan_completed_count_ = 0;
connection_state_changes_.clear();
}
void reset_updates() {
property_updates_.clear();
device_property_updates_.clear();
}
std::string default_network() { return default_network_; }
std::string default_network_connection_state() {
return default_network_connection_state_;
}
int PropertyUpdatesForService(const std::string& service_path) {
return property_updates_[service_path];
}
int PropertyUpdatesForDevice(const std::string& device_path) {
return device_property_updates_[device_path];
}
int ConnectionStateChangesForService(const std::string& service_path) {
return connection_state_changes_[service_path];
}
std::string NetworkConnectionStateForService(
const std::string& service_path) {
return network_connection_state_[service_path];
}
private:
NetworkStateHandler* handler_;
size_t device_list_changed_count_;
size_t device_count_;
size_t network_list_changed_count_;
size_t network_count_;
size_t default_network_change_count_;
size_t scan_requested_count_;
size_t scan_completed_count_;
std::string default_network_;
std::string default_network_connection_state_;
std::map<std::string, int> property_updates_;
std::map<std::string, int> device_property_updates_;
std::map<std::string, int> connection_state_changes_;
std::map<std::string, std::string> network_connection_state_;
DISALLOW_COPY_AND_ASSIGN(TestObserver);
};
class TestTetherSortDelegate : public NetworkStateHandler::TetherSortDelegate {
public:
TestTetherSortDelegate() = default;
~TestTetherSortDelegate() = default;
// NetworkStateHandler::TetherSortDelegate:
void SortTetherNetworkList(
NetworkStateHandler::ManagedStateList* tether_networks) const override {
std::sort(tether_networks->begin(), tether_networks->end(),
[](const std::unique_ptr<ManagedState>& first,
const std::unique_ptr<ManagedState>& second) {
const NetworkState* first_network =
static_cast<const NetworkState*>(first.get());
const NetworkState* second_network =
static_cast<const NetworkState*>(second.get());
// Sort by reverse-alphabetical order of GUIDs.
return first_network->guid() >= second_network->guid();
});
}
private:
DISALLOW_COPY_AND_ASSIGN(TestTetherSortDelegate);
};
} // namespace
class NetworkStateHandlerTest : public testing::Test {
public:
NetworkStateHandlerTest()
: scoped_task_environment_(
base::test::ScopedTaskEnvironment::MainThreadType::UI),
device_test_(nullptr),
manager_test_(nullptr),
profile_test_(nullptr),
service_test_(nullptr) {}
~NetworkStateHandlerTest() override = default;
void SetUp() override {
// Initialize DBusThreadManager with a stub implementation.
DBusThreadManager::Initialize();
SetupDefaultShillState();
network_state_handler_.reset(new NetworkStateHandler);
test_observer_.reset(new TestObserver(network_state_handler_.get()));
network_state_handler_->AddObserver(test_observer_.get(), FROM_HERE);
network_state_handler_->InitShillPropertyHandler();
base::RunLoop().RunUntilIdle();
test_observer_->reset_change_counts();
}
void TearDown() override {
network_state_handler_->RemoveObserver(test_observer_.get(), FROM_HERE);
network_state_handler_->Shutdown();
test_observer_.reset();
network_state_handler_.reset();
DBusThreadManager::Shutdown();
}
protected:
void AddService(const std::string& service_path,
const std::string& guid,
const std::string& name,
const std::string& type,
const std::string& state) {
service_test_->AddService(service_path, guid, name, type, state,
true /* add_to_visible */);
}
void SetupDefaultShillState() {
base::RunLoop().RunUntilIdle(); // Process any pending updates
device_test_ =
DBusThreadManager::Get()->GetShillDeviceClient()->GetTestInterface();
ASSERT_TRUE(device_test_);
device_test_->ClearDevices();
device_test_->AddDevice(kShillManagerClientStubWifiDevice,
shill::kTypeWifi, "stub_wifi_device1");
device_test_->AddDevice(kShillManagerClientStubCellularDevice,
shill::kTypeCellular, "stub_cellular_device1");
manager_test_ =
DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface();
ASSERT_TRUE(manager_test_);
profile_test_ =
DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface();
ASSERT_TRUE(profile_test_);
profile_test_->ClearProfiles();
service_test_ =
DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
ASSERT_TRUE(service_test_);
service_test_->ClearServices();
AddService(kShillManagerClientStubDefaultService,
"eth1_guid",
"eth1",
shill::kTypeEthernet,
shill::kStateOnline);
AddService(kShillManagerClientStubDefaultWifi,
"wifi1_guid",
"wifi1",
shill::kTypeWifi,
shill::kStateOnline);
AddService(kShillManagerClientStubWifi2,
"wifi2_guid",
"wifi2",
shill::kTypeWifi,
shill::kStateIdle);
AddService(kShillManagerClientStubCellular,
"cellular1_guid",
"cellular1",
shill::kTypeCellular,
shill::kStateIdle);
}
void UpdateManagerProperties() { base::RunLoop().RunUntilIdle(); }
void SetServiceProperty(const std::string& service_path,
const std::string& key,
const base::Value& value) {
DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
dbus::ObjectPath(service_path), key, value,
base::Bind(&base::DoNothing), base::Bind(&ErrorCallbackFunction));
}
void GetTetherNetworkList(int limit,
NetworkStateHandler::NetworkStateList* list) {
network_state_handler_->GetNetworkListByType(
NetworkTypePattern::Tether(), false /* configured_only */,
false /* visible_only */, limit, list);
}
base::test::ScopedTaskEnvironment scoped_task_environment_;
std::unique_ptr<NetworkStateHandler> network_state_handler_;
std::unique_ptr<TestObserver> test_observer_;
ShillDeviceClient::TestInterface* device_test_;
ShillManagerClient::TestInterface* manager_test_;
ShillProfileClient::TestInterface* profile_test_;
ShillServiceClient::TestInterface* service_test_;
private:
DISALLOW_COPY_AND_ASSIGN(NetworkStateHandlerTest);
};
TEST_F(NetworkStateHandlerTest, NetworkStateHandlerStub) {
// Ensure that the device and network list are the expected size.
const size_t kNumShillManagerClientStubImplDevices = 2;
EXPECT_EQ(kNumShillManagerClientStubImplDevices,
test_observer_->device_count());
const size_t kNumShillManagerClientStubImplServices = 4;
EXPECT_EQ(kNumShillManagerClientStubImplServices,
test_observer_->network_count());
// Ensure that the first stub network is the default network.
EXPECT_EQ(kShillManagerClientStubDefaultService,
test_observer_->default_network());
ASSERT_TRUE(network_state_handler_->DefaultNetwork());
EXPECT_EQ(kShillManagerClientStubDefaultService,
network_state_handler_->DefaultNetwork()->path());
EXPECT_EQ(kShillManagerClientStubDefaultService,
network_state_handler_->ConnectedNetworkByType(
NetworkTypePattern::Ethernet())->path());
EXPECT_EQ(kShillManagerClientStubDefaultWifi,
network_state_handler_->ConnectedNetworkByType(
NetworkTypePattern::WiFi())->path());
EXPECT_EQ(kShillManagerClientStubCellular,
network_state_handler_->FirstNetworkByType(
NetworkTypePattern::Mobile())->path());
EXPECT_EQ(
kShillManagerClientStubCellular,
network_state_handler_->FirstNetworkByType(NetworkTypePattern::Cellular())
->path());
EXPECT_EQ(shill::kStateOnline,
test_observer_->default_network_connection_state());
}
TEST_F(NetworkStateHandlerTest, GetNetworkList) {
network_state_handler_->SetTetherTechnologyState(
NetworkStateHandler::TECHNOLOGY_ENABLED);
// Ensure that the network list is the expected size.
const size_t kNumShillManagerClientStubImplServices = 4;
EXPECT_EQ(kNumShillManagerClientStubImplServices,
test_observer_->network_count());
// Add a non-visible network to the profile.
const std::string profile = "/profile/profile1";
const std::string wifi_favorite_path = "/service/wifi_faviorite";
service_test_->AddService(wifi_favorite_path,
"wifi_faviorite_guid",
"wifi_faviorite",
shill::kTypeWifi,
shill::kStateIdle,
false /* add_to_visible */);
profile_test_->AddProfile(profile, "" /* userhash */);
EXPECT_TRUE(profile_test_->AddService(profile, wifi_favorite_path));
UpdateManagerProperties();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(kNumShillManagerClientStubImplServices + 1,
test_observer_->network_count());
// Add two Tether networks.
const size_t kNumTetherNetworks = 2;
network_state_handler_->AddTetherNetworkState(
kTetherGuid1, kTetherName1, kTetherCarrier1, kTetherBatteryPercentage1,
kTetherSignalStrength1, kTetherHasConnectedToHost1);
network_state_handler_->AddTetherNetworkState(
kTetherGuid2, kTetherName2, kTetherCarrier2, kTetherBatteryPercentage2,
kTetherSignalStrength2, kTetherHasConnectedToHost2);
EXPECT_EQ(kNumShillManagerClientStubImplServices + 3,
test_observer_->network_count());
// Get all networks.
NetworkStateHandler::NetworkStateList networks;
network_state_handler_->GetNetworkListByType(NetworkTypePattern::Default(),
false /* configured_only */,
false /* visible_only */,
0 /* no limit */,
&networks);
EXPECT_EQ(kNumShillManagerClientStubImplServices + kNumTetherNetworks + 1,
networks.size());
// Limit number of results, including only Tether networks.
network_state_handler_->GetNetworkListByType(NetworkTypePattern::Default(),
false /* configured_only */,
false /* visible_only */,
2 /* limit */,
&networks);
EXPECT_EQ(2u, networks.size());
// Limit number of results, including more than only Tether networks.
network_state_handler_->GetNetworkListByType(
NetworkTypePattern::Default(), false /* configured_only */,
false /* visible_only */, 4 /* limit */, &networks);
EXPECT_EQ(4u, networks.size());
// Get all Tether networks.
network_state_handler_->GetNetworkListByType(
NetworkTypePattern::Tether(), false /* configured_only */,
false /* visible_only */, 0 /* no limit */, &networks);
EXPECT_EQ(2u, networks.size());
// Get all wifi networks.
network_state_handler_->GetNetworkListByType(NetworkTypePattern::WiFi(),
false /* configured_only */,
false /* visible_only */,
0 /* no limit */,
&networks);
EXPECT_EQ(3u, networks.size());
// Get visible networks.
network_state_handler_->GetNetworkListByType(NetworkTypePattern::Default(),
false /* configured_only */,
true /* visible_only */,
0 /* no limit */,
&networks);
EXPECT_EQ(kNumShillManagerClientStubImplServices + kNumTetherNetworks,
networks.size());
network_state_handler_->GetVisibleNetworkList(&networks);
EXPECT_EQ(kNumShillManagerClientStubImplServices + kNumTetherNetworks,
networks.size());
// Get configured (profile) networks.
network_state_handler_->GetNetworkListByType(NetworkTypePattern::Default(),
true /* configured_only */,
false /* visible_only */,
0 /* no limit */,
&networks);
EXPECT_EQ(kNumTetherNetworks + 1u, networks.size());
}
TEST_F(NetworkStateHandlerTest, GetTetherNetworkList) {
network_state_handler_->SetTetherTechnologyState(
NetworkStateHandler::TECHNOLOGY_ENABLED);
NetworkStateHandler::NetworkStateList tether_networks;
GetTetherNetworkList(0 /* no limit */, &tether_networks);
EXPECT_EQ(0u, tether_networks.size());
network_state_handler_->AddTetherNetworkState(
kTetherGuid1, kTetherName1, kTetherCarrier1, kTetherBatteryPercentage1,
kTetherSignalStrength1, kTetherHasConnectedToHost1);
GetTetherNetworkList(0 /* no limit */, &tether_networks);
EXPECT_EQ(1u, tether_networks.size());
network_state_handler_->AddTetherNetworkState(
kTetherGuid2, kTetherName2, kTetherCarrier2, kTetherBatteryPercentage2,
kTetherSignalStrength2, kTetherHasConnectedToHost2);
GetTetherNetworkList(0 /* no limit */, &tether_networks);
EXPECT_EQ(2u, tether_networks.size());
GetTetherNetworkList(1 /* no limit */, &tether_networks);
EXPECT_EQ(1u, tether_networks.size());
}
TEST_F(NetworkStateHandlerTest, SortTetherNetworkList) {
network_state_handler_->SetTetherTechnologyState(
NetworkStateHandler::TECHNOLOGY_ENABLED);
TestTetherSortDelegate sort_delegate;
network_state_handler_->set_tether_sort_delegate(&sort_delegate);
network_state_handler_->AddTetherNetworkState(
kTetherGuid1, kTetherName1, kTetherCarrier1, kTetherBatteryPercentage1,
kTetherSignalStrength1, kTetherHasConnectedToHost1);
network_state_handler_->AddTetherNetworkState(
kTetherGuid2, kTetherName2, kTetherCarrier2, kTetherBatteryPercentage2,
kTetherSignalStrength2, kTetherHasConnectedToHost2);
// Note: GetVisibleNetworkListByType() sorts before outputting networks.
NetworkStateHandler::NetworkStateList tether_networks;
network_state_handler_->GetVisibleNetworkListByType(
NetworkTypePattern::Tether(), &tether_networks);
// The list should have been reversed due to reverse-alphabetical sorting.
EXPECT_EQ(2u, tether_networks.size());
EXPECT_EQ(kTetherGuid2, tether_networks[0]->guid());
EXPECT_EQ(kTetherGuid1, tether_networks[1]->guid());
}
TEST_F(NetworkStateHandlerTest, SortTetherNetworkList_NoSortingDelegate) {
network_state_handler_->SetTetherTechnologyState(
NetworkStateHandler::TECHNOLOGY_ENABLED);
// Do not set a TetherSortDelegate.
network_state_handler_->AddTetherNetworkState(
kTetherGuid1, kTetherName1, kTetherCarrier1, kTetherBatteryPercentage1,
kTetherSignalStrength1, kTetherHasConnectedToHost1);
network_state_handler_->AddTetherNetworkState(
kTetherGuid2, kTetherName2, kTetherCarrier2, kTetherBatteryPercentage2,
kTetherSignalStrength2, kTetherHasConnectedToHost2);
// Note: GetVisibleNetworkListByType() sorts before outputting networks.
NetworkStateHandler::NetworkStateList tether_networks;
network_state_handler_->GetVisibleNetworkListByType(
NetworkTypePattern::Tether(), &tether_networks);
// The list should be in the original order.
EXPECT_EQ(2u, tether_networks.size());
EXPECT_EQ(kTetherGuid1, tether_networks[0]->guid());
EXPECT_EQ(kTetherGuid2, tether_networks[1]->guid());
}
TEST_F(NetworkStateHandlerTest,
GetNetworks_TetherIncluded_ActiveBeforeInactive) {
network_state_handler_->SetTetherTechnologyState(
NetworkStateHandler::TECHNOLOGY_ENABLED);
TestTetherSortDelegate sort_delegate;
network_state_handler_->set_tether_sort_delegate(&sort_delegate);
// To start the test, |eth1| and |wifi1| are connected, while |wifi2| and
// |cellular| are not.
const std::string eth1 = kShillManagerClientStubDefaultService;
const std::string wifi1 = kShillManagerClientStubDefaultWifi;
const std::string wifi2 = kShillManagerClientStubWifi2;
const std::string cellular = kShillManagerClientStubCellular;
// Disconnect |wifi1|, which will serve as the underlying connection
// for the Tether network under test.
service_test_->SetServiceProperty(wifi1, shill::kStateProperty,
base::Value(shill::kStateIdle));
// Connect |cellular| for this test.
service_test_->SetServiceProperty(cellular, shill::kStateProperty,
base::Value(shill::kStateOnline));
base::RunLoop().RunUntilIdle();
// Add two Tether networks. Neither is connected yet.
network_state_handler_->AddTetherNetworkState(
kTetherGuid1, kTetherName1, kTetherCarrier1, kTetherBatteryPercentage1,
kTetherSignalStrength1, kTetherHasConnectedToHost1);
network_state_handler_->AddTetherNetworkState(
kTetherGuid2, kTetherName2, kTetherCarrier2, kTetherBatteryPercentage2,
kTetherSignalStrength2, kTetherHasConnectedToHost2);
// Connect to the first Tether network (and the underlying Wi-Fi hotspot
// network, |wifi1|).
network_state_handler_->SetTetherNetworkStateConnecting(kTetherGuid1);
network_state_handler_->AssociateTetherNetworkStateWithWifiNetwork(
kTetherGuid1, "wifi1_guid");
service_test_->SetServiceProperty(wifi1, shill::kStateProperty,
base::Value(shill::kStateOnline));
base::RunLoop().RunUntilIdle();
network_state_handler_->SetTetherNetworkStateConnected(kTetherGuid1);
// At this point, |eth1|, |cellular|, and |kTetherGuid1| are connected.
// |wifi1| is also connected, but it is not considered visible since it is the
// underlying network for the Tether connection.
NetworkStateHandler::NetworkStateList list;
// Get Tether networks. Even though the networks should be sorted according to
// reverse-alphabetical order, |kTetherGuid1| should be listed first since it
// is active.
network_state_handler_->GetVisibleNetworkListByType(
NetworkTypePattern::Tether(), &list);
ASSERT_EQ(2u, list.size());
EXPECT_EQ(kTetherGuid1, list[0]->guid());
EXPECT_EQ(kTetherGuid2, list[1]->guid());
// Get Mobile networks. The connected Tether network should be first, followed
// by the connected Cellular network, followed by the non-connected Tether
// network.
network_state_handler_->GetVisibleNetworkListByType(
NetworkTypePattern::Mobile(), &list);
ASSERT_EQ(3u, list.size());
EXPECT_EQ(kTetherGuid1, list[0]->guid());
EXPECT_EQ(cellular, list[1]->path());
EXPECT_EQ(kTetherGuid2, list[2]->guid());
// Get all networks. The connected Ethernet network should be first, followed
// by the connected Tether network, followed by the connected Cellular
// network, followed by the non-connected Tether network, followed by the
// non-connected Wi-Fi network.
network_state_handler_->GetVisibleNetworkListByType(
NetworkTypePattern::Default(), &list);
EXPECT_EQ(5u, list.size());
EXPECT_EQ(eth1, list[0]->path());
EXPECT_EQ(kTetherGuid1, list[1]->guid());
EXPECT_EQ(cellular, list[2]->path());
EXPECT_EQ(kTetherGuid2, list[3]->guid());
EXPECT_EQ(wifi2, list[4]->path());
}
TEST_F(NetworkStateHandlerTest, NetworkListChanged) {
size_t stub_network_count = test_observer_->network_count();
// Set up two additional visible networks.
const std::string wifi3 = "/service/wifi3";
const std::string wifi4 = "/service/wifi4";
service_test_->SetServiceProperties(
wifi3, "wifi3_guid", "wifi3",
shill::kTypeWifi, shill::kStateIdle, true /* visible */);
service_test_->SetServiceProperties(
wifi4, "wifi4_guid", "wifi4",
shill::kTypeWifi, shill::kStateIdle, true /* visible */);
// Add the services to the Manager. Only notify when the second service is
// added.
manager_test_->AddManagerService(wifi3, false);
manager_test_->AddManagerService(wifi4, true);
UpdateManagerProperties();
// Expect two service updates and one list update.
EXPECT_EQ(stub_network_count + 2, test_observer_->network_count());
EXPECT_EQ(1, test_observer_->PropertyUpdatesForService(wifi3));
EXPECT_EQ(1, test_observer_->PropertyUpdatesForService(wifi4));
EXPECT_EQ(1u, test_observer_->network_list_changed_count());
}
TEST_F(NetworkStateHandlerTest, GetVisibleNetworks) {
// Ensure that the network list is the expected size.
const size_t kNumShillManagerClientStubImplServices = 4;
EXPECT_EQ(kNumShillManagerClientStubImplServices,
test_observer_->network_count());
// Add a non-visible network to the profile.
const std::string profile = "/profile/profile1";
const std::string wifi_favorite_path = "/service/wifi_faviorite";
service_test_->AddService(wifi_favorite_path,
"wifi_faviorite_guid",
"wifi_faviorite",
shill::kTypeWifi,
shill::kStateIdle,
false /* add_to_visible */);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(kNumShillManagerClientStubImplServices + 1,
test_observer_->network_count());
// Get visible networks.
NetworkStateHandler::NetworkStateList networks;
network_state_handler_->GetVisibleNetworkList(&networks);
EXPECT_EQ(kNumShillManagerClientStubImplServices, networks.size());
// Change the visible state of a network.
SetServiceProperty(kShillManagerClientStubWifi2, shill::kVisibleProperty,
base::Value(false));
base::RunLoop().RunUntilIdle();
network_state_handler_->GetVisibleNetworkList(&networks);
EXPECT_EQ(kNumShillManagerClientStubImplServices - 1, networks.size());
}
TEST_F(NetworkStateHandlerTest, TechnologyChanged) {
// Disable a technology. Will immediately set the state to AVAILABLE and
// notify observers.
network_state_handler_->SetTechnologyEnabled(
NetworkTypePattern::WiFi(), false, network_handler::ErrorCallback());
EXPECT_EQ(1u, test_observer_->device_list_changed_count());
EXPECT_EQ(
NetworkStateHandler::TECHNOLOGY_AVAILABLE,
network_state_handler_->GetTechnologyState(NetworkTypePattern::WiFi()));
// Run the message loop. An additional notification will be received when
// Shill updates the enabled technologies. The state should remain AVAILABLE.
test_observer_->reset_change_counts();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1u, test_observer_->device_list_changed_count());
EXPECT_EQ(
NetworkStateHandler::TECHNOLOGY_AVAILABLE,
network_state_handler_->GetTechnologyState(NetworkTypePattern::WiFi()));
// Enable a technology. Will immediately set the state to ENABLING and
// notify observers.
test_observer_->reset_change_counts();
network_state_handler_->SetTechnologyEnabled(
NetworkTypePattern::WiFi(), true, network_handler::ErrorCallback());
EXPECT_EQ(1u, test_observer_->device_list_changed_count());
EXPECT_EQ(
NetworkStateHandler::TECHNOLOGY_ENABLING,
network_state_handler_->GetTechnologyState(NetworkTypePattern::WiFi()));
// Run the message loop. State should change to ENABLED.
test_observer_->reset_change_counts();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1u, test_observer_->device_list_changed_count());
EXPECT_EQ(
NetworkStateHandler::TECHNOLOGY_ENABLED,
network_state_handler_->GetTechnologyState(NetworkTypePattern::WiFi()));
}
TEST_F(NetworkStateHandlerTest, TechnologyState) {
manager_test_->RemoveTechnology(shill::kTypeWimax);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(
NetworkStateHandler::TECHNOLOGY_UNAVAILABLE,
network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
manager_test_->AddTechnology(shill::kTypeWimax, false);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(
NetworkStateHandler::TECHNOLOGY_AVAILABLE,
network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
manager_test_->SetTechnologyInitializing(shill::kTypeWimax, true);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(
NetworkStateHandler::TECHNOLOGY_UNINITIALIZED,
network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
manager_test_->SetTechnologyInitializing(shill::kTypeWimax, false);
network_state_handler_->SetTechnologyEnabled(
NetworkTypePattern::Wimax(), true, network_handler::ErrorCallback());
base::RunLoop().RunUntilIdle();
EXPECT_EQ(
NetworkStateHandler::TECHNOLOGY_ENABLED,
network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
manager_test_->RemoveTechnology(shill::kTypeWimax);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(
NetworkStateHandler::TECHNOLOGY_UNAVAILABLE,
network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
}
TEST_F(NetworkStateHandlerTest, TetherTechnologyState) {
EXPECT_EQ(
NetworkStateHandler::TECHNOLOGY_UNAVAILABLE,
network_state_handler_->GetTechnologyState(NetworkTypePattern::Tether()));
EXPECT_FALSE(network_state_handler_->GetDeviceState(kTetherDevicePath));
EXPECT_FALSE(network_state_handler_->GetDeviceStateByType(
NetworkTypePattern::Tether()));
// Test SetTetherTechnologyState():
network_state_handler_->SetTetherTechnologyState(
NetworkStateHandler::TECHNOLOGY_AVAILABLE);
EXPECT_EQ(1u, test_observer_->device_list_changed_count());
EXPECT_EQ(
NetworkStateHandler::TECHNOLOGY_AVAILABLE,
network_state_handler_->GetTechnologyState(NetworkTypePattern::Tether()));
const DeviceState* tether_device_state =
network_state_handler_->GetDeviceState(kTetherDevicePath);
EXPECT_TRUE(tether_device_state);
EXPECT_EQ(tether_device_state, network_state_handler_->GetDeviceStateByType(
NetworkTypePattern::Tether()));
// Test SetTechnologyEnabled() with a Tether network:
network_state_handler_->SetTechnologyEnabled(
NetworkTypePattern::Tether(), true, network_handler::ErrorCallback());
EXPECT_EQ(2u, test_observer_->device_list_changed_count());
EXPECT_EQ(
NetworkStateHandler::TECHNOLOGY_ENABLED,
network_state_handler_->GetTechnologyState(NetworkTypePattern::Tether()));
EXPECT_EQ(tether_device_state,
network_state_handler_->GetDeviceState(kTetherDevicePath));
EXPECT_EQ(tether_device_state, network_state_handler_->GetDeviceStateByType(
NetworkTypePattern::Tether()));
// Test SetProhibitedTechnologies() with a Tether network:
network_state_handler_->SetProhibitedTechnologies(
std::vector<std::string>{kTypeTether}, network_handler::ErrorCallback());
EXPECT_EQ(3u, test_observer_->device_list_changed_count());
EXPECT_EQ(
NetworkStateHandler::TECHNOLOGY_PROHIBITED,
network_state_handler_->GetTechnologyState(NetworkTypePattern::Tether()));
EXPECT_EQ(tether_device_state,
network_state_handler_->GetDeviceState(kTetherDevicePath));
EXPECT_EQ(tether_device_state, network_state_handler_->GetDeviceStateByType(
NetworkTypePattern::Tether()));
// Set back to TECHNOLOGY_UNAVAILABLE; this should result in nullptr being
// returned by getters.
network_state_handler_->SetTetherTechnologyState(
NetworkStateHandler::TECHNOLOGY_UNAVAILABLE);
EXPECT_FALSE(network_state_handler_->GetDeviceState(kTetherDevicePath));
EXPECT_FALSE(network_state_handler_->GetDeviceStateByType(
NetworkTypePattern::Tether()));
}
TEST_F(NetworkStateHandlerTest, TetherScanningState) {
network_state_handler_->SetTetherTechnologyState(
NetworkStateHandler::TECHNOLOGY_ENABLED);
const DeviceState* tether_device_state =
network_state_handler_->GetDeviceStateByType(
NetworkTypePattern::Tether());
EXPECT_TRUE(tether_device_state);
EXPECT_FALSE(tether_device_state->scanning());
EXPECT_EQ(0u, test_observer_->scan_completed_count());
network_state_handler_->SetTetherScanState(true /* is_scanning */);
tether_device_state = network_state_handler_->GetDeviceStateByType(
NetworkTypePattern::Tether());
EXPECT_TRUE(tether_device_state);
EXPECT_TRUE(tether_device_state->scanning());
EXPECT_EQ(0u, test_observer_->scan_completed_count());
network_state_handler_->SetTetherScanState(false /* is_scanning */);
tether_device_state = network_state_handler_->GetDeviceStateByType(
NetworkTypePattern::Tether());
EXPECT_TRUE(tether_device_state);
EXPECT_FALSE(tether_device_state->scanning());
EXPECT_EQ(1u, test_observer_->scan_completed_count());
}
TEST_F(NetworkStateHandlerTest, ServicePropertyChangedDefaultNetwork) {
// Set a service property on the default network.
const std::string eth1 = kShillManagerClientStubDefaultService;
const NetworkState* ethernet = network_state_handler_->GetNetworkState(eth1);
ASSERT_TRUE(ethernet);
EXPECT_EQ("", ethernet->security_class());
EXPECT_EQ(1, test_observer_->PropertyUpdatesForService(eth1));
EXPECT_EQ(0u, test_observer_->default_network_change_count());
base::Value security_class_value("TestSecurityClass");
SetServiceProperty(eth1, shill::kSecurityClassProperty, security_class_value);
base::RunLoop().RunUntilIdle();
ethernet = network_state_handler_->GetNetworkState(eth1);
EXPECT_EQ("TestSecurityClass", ethernet->security_class());
EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(eth1));
EXPECT_EQ(1u, test_observer_->default_network_change_count());
// Changing a service to the existing value should not trigger an update.
SetServiceProperty(eth1, shill::kSecurityClassProperty, security_class_value);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(eth1));
EXPECT_EQ(1u, test_observer_->default_network_change_count());
}
TEST_F(NetworkStateHandlerTest, ServicePropertyChangedNotIneterstingActive) {
// Set an uninteresting service property on an active network.
const std::string wifi1 = kShillManagerClientStubDefaultWifi;
const NetworkState* wifi = network_state_handler_->GetNetworkState(wifi1);
ASSERT_TRUE(wifi);
EXPECT_EQ(1, wifi->signal_strength());
EXPECT_EQ(1, test_observer_->PropertyUpdatesForService(wifi1));
EXPECT_EQ(0u, test_observer_->default_network_change_count());
base::Value signal_strength_value(11);
SetServiceProperty(wifi1, shill::kSignalStrengthProperty,
signal_strength_value);
base::RunLoop().RunUntilIdle();
wifi = network_state_handler_->GetNetworkState(wifi1);
EXPECT_EQ(11, wifi->signal_strength());
// The change should trigger an additional properties updated event.
EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(wifi1));
EXPECT_EQ(0u, test_observer_->default_network_change_count());
}
TEST_F(NetworkStateHandlerTest, ServicePropertyChangedNotIneterstingInactive) {
// Set an uninteresting service property on an inactive network.
const std::string wifi2 = kShillManagerClientStubWifi2;
const NetworkState* wifi = network_state_handler_->GetNetworkState(wifi2);
ASSERT_TRUE(wifi);
EXPECT_EQ(1, wifi->signal_strength());
EXPECT_EQ(1, test_observer_->PropertyUpdatesForService(wifi2));
base::Value signal_strength_value(11);
SetServiceProperty(wifi2, shill::kSignalStrengthProperty,
signal_strength_value);
base::RunLoop().RunUntilIdle();
wifi = network_state_handler_->GetNetworkState(wifi2);
EXPECT_EQ(11, wifi->signal_strength());
// The change should *not* trigger an additional properties updated event.
EXPECT_EQ(1, test_observer_->PropertyUpdatesForService(wifi2));
}
TEST_F(NetworkStateHandlerTest, GetState) {
const std::string profile = "/profile/profile1";
const std::string wifi_path = kShillManagerClientStubDefaultWifi;
// Add a wifi service to a Profile.
profile_test_->AddProfile(profile, "" /* userhash */);
EXPECT_TRUE(profile_test_->AddService(profile, wifi_path));
UpdateManagerProperties();
// Ensure that a NetworkState exists.
const NetworkState* wifi_network =
network_state_handler_->GetNetworkStateFromServicePath(
wifi_path, true /* configured_only */);
ASSERT_TRUE(wifi_network);
// Test looking up by GUID.
ASSERT_FALSE(wifi_network->guid().empty());
const NetworkState* wifi_network_guid =
network_state_handler_->GetNetworkStateFromGuid(wifi_network->guid());
EXPECT_EQ(wifi_network, wifi_network_guid);
// Remove the service, verify that there is no longer a NetworkState for it.
service_test_->RemoveService(wifi_path);
UpdateManagerProperties();
EXPECT_FALSE(network_state_handler_->GetNetworkState(wifi_path));
}
TEST_F(NetworkStateHandlerTest, TetherNetworkState) {
network_state_handler_->SetTetherTechnologyState(
NetworkStateHandler::TECHNOLOGY_ENABLED);
EXPECT_EQ(0u, test_observer_->network_list_changed_count());
EXPECT_EQ(0, test_observer_->PropertyUpdatesForService(kTetherGuid1));
network_state_handler_->AddTetherNetworkState(
kTetherGuid1, kTetherName1, kTetherCarrier1, kTetherBatteryPercentage1,
kTetherSignalStrength1, false /* has_connected_to_network */);
EXPECT_EQ(1u, test_observer_->network_list_changed_count());
EXPECT_EQ(0, test_observer_->PropertyUpdatesForService(kTetherGuid1));
const NetworkState* tether_network =
network_state_handler_->GetNetworkStateFromGuid(kTetherGuid1);
ASSERT_TRUE(tether_network);
EXPECT_EQ(kTetherName1, tether_network->name());
EXPECT_EQ(kTetherGuid1, tether_network->path());
EXPECT_EQ(kTetherCarrier1, tether_network->carrier());
EXPECT_EQ(kTetherBatteryPercentage1, tether_network->battery_percentage());
EXPECT_EQ(kTetherSignalStrength1, tether_network->signal_strength());
EXPECT_FALSE(tether_network->tether_has_connected_to_host());
// Update the Tether properties and verify the changes.
EXPECT_TRUE(network_state_handler_->UpdateTetherNetworkProperties(
kTetherGuid1, "NewCarrier", 5 /* battery_percentage */,
10 /* signal_strength */));
EXPECT_EQ(1u, test_observer_->network_list_changed_count());
EXPECT_EQ(1, test_observer_->PropertyUpdatesForService(kTetherGuid1));
tether_network =
network_state_handler_->GetNetworkStateFromGuid(kTetherGuid1);
ASSERT_TRUE(tether_network);
EXPECT_EQ(kTetherName1, tether_network->name());
EXPECT_EQ(kTetherGuid1, tether_network->path());
EXPECT_EQ("NewCarrier", tether_network->carrier());
EXPECT_EQ(5, tether_network->battery_percentage());
EXPECT_EQ(10, tether_network->signal_strength());
EXPECT_FALSE(tether_network->tether_has_connected_to_host());
// Now, set the HasConnectedToHost property to true.
EXPECT_TRUE(
network_state_handler_->SetTetherNetworkHasConnectedToHost(kTetherGuid1));
EXPECT_EQ(1u, test_observer_->network_list_changed_count());
EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(kTetherGuid1));
// Try calling that function again. It should return false and should not
// trigger a NetworkListChanged() callback for observers.
EXPECT_FALSE(
network_state_handler_->SetTetherNetworkHasConnectedToHost(kTetherGuid1));
EXPECT_EQ(1u, test_observer_->network_list_changed_count());
EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(kTetherGuid1));
network_state_handler_->RemoveTetherNetworkState(kTetherGuid1);
EXPECT_EQ(2u, test_observer_->network_list_changed_count());
EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(kTetherGuid1));
ASSERT_FALSE(network_state_handler_->GetNetworkStateFromGuid(kTetherGuid1));
// Updating Tether properties should fail since the network was removed.
EXPECT_FALSE(network_state_handler_->UpdateTetherNetworkProperties(
kTetherGuid1, "NewNewCarrier", 15 /* battery_percentage */,
20 /* signal_strength */));
}
TEST_F(NetworkStateHandlerTest, TetherNetworkStateAssociation) {
network_state_handler_->SetTetherTechnologyState(
NetworkStateHandler::TECHNOLOGY_ENABLED);
const std::string profile = "/profile/profile1";
const std::string wifi_path = "/service/wifi_with_guid";
AddService(wifi_path, kWifiGuid1, kWifiName1, shill::kTypeWifi,
shill::kStateOnline);
profile_test_->AddProfile(profile, "" /* userhash */);
EXPECT_TRUE(profile_test_->AddService(profile, wifi_path));
UpdateManagerProperties();
test_observer_->reset_updates();
EXPECT_EQ(1u, test_observer_->network_list_changed_count());
EXPECT_EQ(0, test_observer_->PropertyUpdatesForService(kTetherGuid1));
EXPECT_EQ(0, test_observer_->PropertyUpdatesForService(wifi_path));
network_state_handler_->AddTetherNetworkState(
kTetherGuid1, kTetherName1, kTetherCarrier1, kTetherBatteryPercentage1,
kTetherSignalStrength1, kTetherHasConnectedToHost1);
EXPECT_EQ(2u, test_observer_->network_list_changed_count());
EXPECT_EQ(0, test_observer_->PropertyUpdatesForService(kTetherGuid1));
EXPECT_EQ(0, test_observer_->PropertyUpdatesForService(wifi_path));
EXPECT_TRUE(
network_state_handler_->AssociateTetherNetworkStateWithWifiNetwork(
kTetherGuid1, kWifiGuid1));
EXPECT_EQ(2u, test_observer_->network_list_changed_count());
EXPECT_EQ(1, test_observer_->PropertyUpdatesForService(kTetherGuid1));
EXPECT_EQ(1, test_observer_->PropertyUpdatesForService(wifi_path));
const NetworkState* wifi_network =
network_state_handler_->GetNetworkStateFromGuid(kWifiGuid1);
EXPECT_EQ(kTetherGuid1, wifi_network->tether_guid());
const NetworkState* tether_network =
network_state_handler_->GetNetworkStateFromGuid(kTetherGuid1);
EXPECT_EQ(kWifiGuid1, tether_network->tether_guid());
// Try associating again. The function call should return true since the
// association was successful, but no new observer updates should occur since
// no changes happened.
EXPECT_TRUE(
network_state_handler_->AssociateTetherNetworkStateWithWifiNetwork(
kTetherGuid1, kWifiGuid1));
EXPECT_EQ(kTetherGuid1, wifi_network->tether_guid());
EXPECT_EQ(kWifiGuid1, tether_network->tether_guid());
EXPECT_EQ(2u, test_observer_->network_list_changed_count());
EXPECT_EQ(1, test_observer_->PropertyUpdatesForService(kTetherGuid1));
EXPECT_EQ(1, test_observer_->PropertyUpdatesForService(wifi_path));
network_state_handler_->RemoveTetherNetworkState(kTetherGuid1);
EXPECT_EQ(3u, test_observer_->network_list_changed_count());
EXPECT_EQ(1, test_observer_->PropertyUpdatesForService(kTetherGuid1));
EXPECT_EQ(1, test_observer_->PropertyUpdatesForService(wifi_path));
wifi_network = network_state_handler_->GetNetworkStateFromGuid(kWifiGuid1);
EXPECT_TRUE(wifi_network->tether_guid().empty());
}
TEST_F(NetworkStateHandlerTest, TetherNetworkStateDisassociation) {
network_state_handler_->SetTetherTechnologyState(
NetworkStateHandler::TECHNOLOGY_ENABLED);
const std::string profile = "/profile/profile1";
const std::string wifi_path = "/service/wifi_with_guid";
AddService(wifi_path, kWifiGuid1, kWifiName1, shill::kTypeWifi,
shill::kStateOnline);
profile_test_->AddProfile(profile, "" /* userhash */);
EXPECT_TRUE(profile_test_->AddService(profile, wifi_path));
UpdateManagerProperties();
test_observer_->reset_updates();
EXPECT_EQ(1u, test_observer_->network_list_changed_count());
EXPECT_EQ(0, test_observer_->PropertyUpdatesForService(kTetherGuid1));
EXPECT_EQ(0, test_observer_->PropertyUpdatesForService(wifi_path));
network_state_handler_->AddTetherNetworkState(
kTetherGuid1, kTetherName1, kTetherCarrier1, kTetherBatteryPercentage1,
kTetherSignalStrength1, kTetherHasConnectedToHost1);
EXPECT_EQ(2u, test_observer_->network_list_changed_count());
EXPECT_EQ(0, test_observer_->PropertyUpdatesForService(kTetherGuid1));
EXPECT_EQ(0, test_observer_->PropertyUpdatesForService(wifi_path));
EXPECT_TRUE(
network_state_handler_->AssociateTetherNetworkStateWithWifiNetwork(
kTetherGuid1, kWifiGuid1));
EXPECT_EQ(2u, test_observer_->network_list_changed_count());
EXPECT_EQ(1, test_observer_->PropertyUpdatesForService(kTetherGuid1));
EXPECT_EQ(1, test_observer_->PropertyUpdatesForService(wifi_path));
const NetworkState* wifi_network =
network_state_handler_->GetNetworkStateFromGuid(kWifiGuid1);
EXPECT_EQ(kTetherGuid1, wifi_network->tether_guid());
const NetworkState* tether_network =
network_state_handler_->GetNetworkStateFromGuid(kTetherGuid1);
EXPECT_EQ(kWifiGuid1, tether_network->tether_guid());
EXPECT_TRUE(
network_state_handler_->DisassociateTetherNetworkStateFromWifiNetwork(
kTetherGuid1));
EXPECT_TRUE(wifi_network->tether_guid().empty());
EXPECT_TRUE(tether_network->tether_guid().empty());
EXPECT_EQ(2u, test_observer_->network_list_changed_count());
EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(kTetherGuid1));
EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(wifi_path));
}
TEST_F(NetworkStateHandlerTest, TetherNetworkStateAssociationWifiRemoved) {
network_state_handler_->SetTetherTechnologyState(
NetworkStateHandler::TECHNOLOGY_ENABLED);
const std::string profile = "/profile/profile1";
const std::string wifi_path = "/service/wifi_with_guid";
AddService(wifi_path, kWifiGuid1, kWifiName1, shill::kTypeWifi,
shill::kStateOnline);
profile_test_->AddProfile(profile, "" /* userhash */);
EXPECT_TRUE(profile_test_->AddService(profile, wifi_path));
UpdateManagerProperties();
network_state_handler_->AddTetherNetworkState(
kTetherGuid1, kTetherName1, kTetherCarrier1, kTetherBatteryPercentage1,
kTetherSignalStrength1, kTetherHasConnectedToHost1);
EXPECT_TRUE(
network_state_handler_->AssociateTetherNetworkStateWithWifiNetwork(
kTetherGuid1, kWifiGuid1));
const NetworkState* wifi_network =
network_state_handler_->GetNetworkStateFromGuid(kWifiGuid1);
EXPECT_EQ(kTetherGuid1, wifi_network->tether_guid());
const NetworkState* tether_network =
network_state_handler_->GetNetworkStateFromGuid(kTetherGuid1);
EXPECT_EQ(kWifiGuid1, tether_network->tether_guid());
service_test_->RemoveService(wifi_path);
UpdateManagerProperties();
tether_network =
network_state_handler_->GetNetworkStateFromGuid(kTetherGuid1);
ASSERT_TRUE(tether_network->tether_guid().empty());
}
TEST_F(NetworkStateHandlerTest, TetherNetworkStateAssociation_NoWifiNetwork) {
network_state_handler_->SetTetherTechnologyState(
NetworkStateHandler::TECHNOLOGY_ENABLED);
network_state_handler_->AddTetherNetworkState(
kTetherGuid1, kTetherName1, kTetherCarrier1, kTetherBatteryPercentage1,
kTetherSignalStrength1, kTetherHasConnectedToHost1);
EXPECT_FALSE(
network_state_handler_->AssociateTetherNetworkStateWithWifiNetwork(
kTetherGuid1, kWifiGuid1));
}
TEST_F(NetworkStateHandlerTest, TetherNetworkStateAssociation_NoTetherNetwork) {
network_state_handler_->SetTetherTechnologyState(
NetworkStateHandler::TECHNOLOGY_ENABLED);
const std::string profile = "/profile/profile1";
const std::string wifi_path = "/service/wifi_with_guid";
AddService(wifi_path, kWifiGuid1, kWifiName1, shill::kTypeWifi,
shill::kStateOnline);
profile_test_->AddProfile(profile, "" /* userhash */);
EXPECT_TRUE(profile_test_->AddService(profile, wifi_path));
UpdateManagerProperties();
ASSERT_FALSE(
network_state_handler_->AssociateTetherNetworkStateWithWifiNetwork(
kTetherGuid1, kWifiGuid1));
}
TEST_F(NetworkStateHandlerTest,
SetTetherNetworkStateConnectionState_NoDefaultNetworkToStart) {
network_state_handler_->SetTetherTechnologyState(
NetworkStateHandler::TECHNOLOGY_ENABLED);
// Disconnect Ethernet and Wi-Fi so that there is no default network. For the
// purpose of this test, the default Wi-Fi network will serve as the Tether
// network's underlying Wi-Fi hotspot.
const std::string eth1 = kShillManagerClientStubDefaultService;
const std::string wifi1 = kShillManagerClientStubDefaultWifi;
service_test_->SetServiceProperty(eth1, shill::kStateProperty,
base::Value(shill::kStateIdle));
service_test_->SetServiceProperty(wifi1, shill::kStateProperty,
base::Value(shill::kStateIdle));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(std::string(), test_observer_->default_network());
// Simulate a host scan, and reset the change counts for the connection flow.
network_state_handler_->AddTetherNetworkState(
kTetherGuid1, kTetherName1, kTetherCarrier1, kTetherBatteryPercentage1,
kTetherSignalStrength1, kTetherHasConnectedToHost1);
test_observer_->reset_change_counts();
test_observer_->reset_updates();
// Preconditions.
EXPECT_EQ(0, test_observer_->ConnectionStateChangesForService(kTetherGuid1));
EXPECT_EQ(0, test_observer_->PropertyUpdatesForService(kTetherGuid1));
EXPECT_EQ(0u, test_observer_->default_network_change_count());
EXPECT_EQ("", test_observer_->default_network());
EXPECT_EQ("", test_observer_->default_network_connection_state());
EXPECT_EQ(nullptr, network_state_handler_->DefaultNetwork());
// Set the Tether network state to "connecting." This is expected to be called
// before the connection to the underlying hotspot Wi-Fi network begins.
const NetworkState* tether_network =
network_state_handler_->GetNetworkStateFromGuid(kTetherGuid1);
network_state_handler_->SetTetherNetworkStateConnecting(kTetherGuid1);
EXPECT_TRUE(tether_network->IsConnectingState());
EXPECT_EQ(1, test_observer_->ConnectionStateChangesForService(kTetherGuid1));
EXPECT_EQ(1, test_observer_->PropertyUpdatesForService(kTetherGuid1));
EXPECT_EQ(0u, test_observer_->default_network_change_count());
EXPECT_EQ(tether_network, network_state_handler_->DefaultNetwork());
// Associate Tether and Wi-Fi networks.
network_state_handler_->AssociateTetherNetworkStateWithWifiNetwork(
kTetherGuid1, "wifi1_guid");
EXPECT_EQ(1, test_observer_->ConnectionStateChangesForService(kTetherGuid1));
EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(kTetherGuid1));
// Connect to the underlying Wi-Fi network. The default network should not
// change yet.
service_test_->SetServiceProperty(wifi1, shill::kStateProperty,
base::Value(shill::kStateOnline));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(0u, test_observer_->default_network_change_count());
// Now, set the Tether network state to "connected." This should result in a
// default network change event.
network_state_handler_->SetTetherNetworkStateConnected(kTetherGuid1);
EXPECT_TRUE(tether_network->IsConnectedState());
EXPECT_EQ(2, test_observer_->ConnectionStateChangesForService(kTetherGuid1));
EXPECT_EQ(3, test_observer_->PropertyUpdatesForService(kTetherGuid1));
EXPECT_EQ(1u, test_observer_->default_network_change_count());
EXPECT_EQ(kTetherGuid1, test_observer_->default_network());
EXPECT_EQ(shill::kStateOnline,
test_observer_->default_network_connection_state());
EXPECT_EQ(tether_network, network_state_handler_->DefaultNetwork());
// Disconnect from the underlying Wi-Fi network. The default network should
// not change yet.
service_test_->SetServiceProperty(wifi1, shill::kStateProperty,
base::Value(shill::kStateIdle));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1u, test_observer_->default_network_change_count());
// Now, set the Tether network state to "disconnected." This should result in
// a default network change event.
network_state_handler_->SetTetherNetworkStateDisconnected(kTetherGuid1);
EXPECT_FALSE(tether_network->IsConnectingState());
EXPECT_FALSE(tether_network->IsConnectedState());
EXPECT_EQ(3, test_observer_->ConnectionStateChangesForService(kTetherGuid1));
EXPECT_EQ(4, test_observer_->PropertyUpdatesForService(kTetherGuid1));
EXPECT_EQ(2u, test_observer_->default_network_change_count());
EXPECT_EQ("", test_observer_->default_network());
EXPECT_EQ("", test_observer_->default_network_connection_state());
EXPECT_EQ(nullptr, network_state_handler_->DefaultNetwork());
}
TEST_F(NetworkStateHandlerTest,
SetTetherNetworkStateConnectionState_EthernetIsDefaultNetwork) {
network_state_handler_->SetTetherTechnologyState(
NetworkStateHandler::TECHNOLOGY_ENABLED);
// The ethernet corresponding to |eth1| will be left connected this entire
// test. It should be expected to remain the default network during the Tether
// connection.
const std::string eth1 = kShillManagerClientStubDefaultService;
// Disconnect the Wi-Fi network, which will serve as the underlying connection
// for the Tether network under test.
const std::string wifi1 = kShillManagerClientStubDefaultWifi;
service_test_->SetServiceProperty(wifi1, shill::kStateProperty,
base::Value(shill::kStateIdle));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(eth1, test_observer_->default_network());
// Simulate a host scan, and reset the change counts for the connection flow.
network_state_handler_->AddTetherNetworkState(
kTetherGuid1, kTetherName1, kTetherCarrier1, kTetherBatteryPercentage1,
kTetherSignalStrength1, kTetherHasConnectedToHost1);
test_observer_->reset_change_counts();
test_observer_->reset_updates();
// Preconditions.
EXPECT_EQ(0, test_observer_->ConnectionStateChangesForService(kTetherGuid1));
EXPECT_EQ(0, test_observer_->PropertyUpdatesForService(kTetherGuid1));
EXPECT_EQ(0u, test_observer_->default_network_change_count());
EXPECT_EQ(eth1, test_observer_->default_network());
EXPECT_EQ(shill::kStateOnline,
test_observer_->default_network_connection_state());
// Set the Tether network state to "connecting." This is expected to be called
// before the connection to the underlying hotspot Wi-Fi network begins.
const NetworkState* tether_network =
network_state_handler_->GetNetworkStateFromGuid(kTetherGuid1);
network_state_handler_->SetTetherNetworkStateConnecting(kTetherGuid1);
EXPECT_TRUE(tether_network->IsConnectingState());
EXPECT_EQ(1, test_observer_->ConnectionStateChangesForService(kTetherGuid1));
EXPECT_EQ(1, test_observer_->PropertyUpdatesForService(kTetherGuid1));
// Associate Tether and Wi-Fi networks.
network_state_handler_->AssociateTetherNetworkStateWithWifiNetwork(
kTetherGuid1, "wifi1_guid");
EXPECT_EQ(1, test_observer_->ConnectionStateChangesForService(kTetherGuid1));
EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(kTetherGuid1));
// Connect to the underlying Wi-Fi network.
service_test_->SetServiceProperty(wifi1, shill::kStateProperty,
base::Value(shill::kStateOnline));
base::RunLoop().RunUntilIdle();
// Now, set the Tether network state to "connected."
network_state_handler_->SetTetherNetworkStateConnected(kTetherGuid1);
EXPECT_TRUE(tether_network->IsConnectedState());
EXPECT_EQ(2, test_observer_->ConnectionStateChangesForService(kTetherGuid1));
EXPECT_EQ(3, test_observer_->PropertyUpdatesForService(kTetherGuid1));
// Disconnect from the underlying Wi-Fi network.
service_test_->SetServiceProperty(wifi1, shill::kStateProperty,
base::Value(shill::kStateIdle));
base::RunLoop().RunUntilIdle();
// Now, set the Tether network state to "disconnected."
network_state_handler_->SetTetherNetworkStateDisconnected(kTetherGuid1);
EXPECT_FALSE(tether_network->IsConnectingState());
EXPECT_FALSE(tether_network->IsConnectedState());
EXPECT_EQ(3, test_observer_->ConnectionStateChangesForService(kTetherGuid1));
EXPECT_EQ(4, test_observer_->PropertyUpdatesForService(kTetherGuid1));
// The Ethernet network should still be the default network, and no changes
// should have occurred during this test.
EXPECT_EQ(0u, test_observer_->default_network_change_count());
EXPECT_EQ(eth1, test_observer_->default_network());
EXPECT_EQ(shill::kStateOnline,
test_observer_->default_network_connection_state());
}
TEST_F(NetworkStateHandlerTest,
SetTetherNetworkStateConnectionState_NoDefaultThenTetherThenEthernet) {
network_state_handler_->SetTetherTechnologyState(
NetworkStateHandler::TECHNOLOGY_ENABLED);
// Disconnect Ethernet and Wi-Fi so that there is no default network. For the
// purpose of this test, the default Wi-Fi network will serve as the Tether
// network's underlying Wi-Fi hotspot.
const std::string eth1 = kShillManagerClientStubDefaultService;
const std::string wifi1 = kShillManagerClientStubDefaultWifi;
service_test_->SetServiceProperty(eth1, shill::kStateProperty,
base::Value(shill::kStateIdle));
service_test_->SetServiceProperty(wifi1, shill::kStateProperty,
base::Value(shill::kStateIdle));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(std::string(), test_observer_->default_network());
// Simulate a host scan, and reset the change counts for the connection flow.
network_state_handler_->AddTetherNetworkState(
kTetherGuid1, kTetherName1, kTetherCarrier1, kTetherBatteryPercentage1,
kTetherSignalStrength1, kTetherHasConnectedToHost1);
test_observer_->reset_change_counts();
test_observer_->reset_updates();
// Preconditions.
EXPECT_EQ(0, test_observer_->ConnectionStateChangesForService(kTetherGuid1));
EXPECT_EQ(0, test_observer_->PropertyUpdatesForService(kTetherGuid1));
EXPECT_EQ(0u, test_observer_->default_network_change_count());
EXPECT_EQ("", test_observer_->default_network());
EXPECT_EQ("", test_observer_->default_network_connection_state());
EXPECT_EQ(nullptr, network_state_handler_->DefaultNetwork());
// Set the Tether network state to "connecting." This is expected to be called
// before the connection to the underlying hotspot Wi-Fi network begins.
const NetworkState* tether_network =
network_state_handler_->GetNetworkStateFromGuid(kTetherGuid1);
network_state_handler_->SetTetherNetworkStateConnecting(kTetherGuid1);
EXPECT_TRUE(tether_network->IsConnectingState());
EXPECT_EQ(1, test_observer_->ConnectionStateChangesForService(kTetherGuid1));
EXPECT_EQ(1, test_observer_->PropertyUpdatesForService(kTetherGuid1));
EXPECT_EQ(0u, test_observer_->default_network_change_count());
EXPECT_EQ(tether_network, network_state_handler_->DefaultNetwork());
// Associate Tether and Wi-Fi networks.
network_state_handler_->AssociateTetherNetworkStateWithWifiNetwork(
kTetherGuid1, "wifi1_guid");
EXPECT_EQ(1, test_observer_->ConnectionStateChangesForService(kTetherGuid1));
EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(kTetherGuid1));
// Connect to the underlying Wi-Fi network. The default network should not
// change yet.
service_test_->SetServiceProperty(wifi1, shill::kStateProperty,
base::Value(shill::kStateOnline));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(0u, test_observer_->default_network_change_count());
// Now, set the Tether network state to "connected." This should result in a
// default network change event.
network_state_handler_->SetTetherNetworkStateConnected(kTetherGuid1);
EXPECT_TRUE(tether_network->IsConnectedState());
EXPECT_EQ(2, test_observer_->ConnectionStateChangesForService(kTetherGuid1));
EXPECT_EQ(3, test_observer_->PropertyUpdatesForService(kTetherGuid1));
EXPECT_EQ(1u, test_observer_->default_network_change_count());
EXPECT_EQ(kTetherGuid1, test_observer_->default_network());
EXPECT_EQ(shill::kStateOnline,
test_observer_->default_network_connection_state());
EXPECT_EQ(tether_network, network_state_handler_->DefaultNetwork());
// Now, connect the Ethernet network. This should be the new default network.
service_test_->SetServiceProperty(eth1, shill::kStateProperty,
base::Value(shill::kStateOnline));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(2u, test_observer_->default_network_change_count());
EXPECT_EQ(eth1, test_observer_->default_network());
EXPECT_EQ(shill::kStateOnline,
test_observer_->default_network_connection_state());
// Disconnect from the underlying Wi-Fi network. The default network should
// still be the Ethernet network.
service_test_->SetServiceProperty(wifi1, shill::kStateProperty,
base::Value(shill::kStateIdle));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(2u, test_observer_->default_network_change_count());
// Now, set the Tether network state to "disconnected." The default network
// should still be the Ethernet network.
network_state_handler_->SetTetherNetworkStateDisconnected(kTetherGuid1);
EXPECT_FALSE(tether_network->IsConnectingState());
EXPECT_FALSE(tether_network->IsConnectedState());
EXPECT_EQ(3, test_observer_->ConnectionStateChangesForService(kTetherGuid1));
EXPECT_EQ(4, test_observer_->PropertyUpdatesForService(kTetherGuid1));
EXPECT_EQ(2u, test_observer_->default_network_change_count());
EXPECT_EQ(eth1, test_observer_->default_network());
EXPECT_EQ(shill::kStateOnline,
test_observer_->default_network_connection_state());
}
TEST_F(NetworkStateHandlerTest, NetworkConnectionStateChanged) {
const std::string eth1 = kShillManagerClientStubDefaultService;
EXPECT_EQ(0, test_observer_->ConnectionStateChangesForService(eth1));
// Change a network state.
base::Value connection_state_idle_value(shill::kStateIdle);
service_test_->SetServiceProperty(eth1, shill::kStateProperty,
connection_state_idle_value);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(shill::kStateIdle,
test_observer_->NetworkConnectionStateForService(eth1));
EXPECT_EQ(1, test_observer_->ConnectionStateChangesForService(eth1));
// Confirm that changing the connection state to the same value does *not*
// signal the observer.
service_test_->SetServiceProperty(eth1, shill::kStateProperty,
connection_state_idle_value);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, test_observer_->ConnectionStateChangesForService(eth1));
}
TEST_F(NetworkStateHandlerTest, DefaultServiceDisconnected) {
const std::string eth1 = kShillManagerClientStubDefaultService;
const std::string wifi1 = kShillManagerClientStubDefaultWifi;
EXPECT_EQ(0u, test_observer_->default_network_change_count());
// Disconnect ethernet.
base::Value connection_state_idle_value(shill::kStateIdle);
service_test_->SetServiceProperty(eth1, shill::kStateProperty,
connection_state_idle_value);
base::RunLoop().RunUntilIdle();
// Expect two changes: first when eth1 becomes disconnected, second when
// wifi1 becomes the default.
EXPECT_EQ(2u, test_observer_->default_network_change_count());
EXPECT_EQ(wifi1, test_observer_->default_network());
// Disconnect wifi.
test_observer_->reset_change_counts();
service_test_->SetServiceProperty(wifi1, shill::kStateProperty,
connection_state_idle_value);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1u, test_observer_->default_network_change_count());
EXPECT_EQ("", test_observer_->default_network());
}
TEST_F(NetworkStateHandlerTest, DefaultServiceConnected) {
const std::string eth1 = kShillManagerClientStubDefaultService;
const std::string wifi1 = kShillManagerClientStubDefaultWifi;
// Disconnect ethernet and wifi.
base::Value connection_state_idle_value(shill::kStateIdle);
service_test_->SetServiceProperty(eth1, shill::kStateProperty,
connection_state_idle_value);
service_test_->SetServiceProperty(wifi1, shill::kStateProperty,
connection_state_idle_value);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(std::string(), test_observer_->default_network());
// Connect ethernet, should become the default network.
test_observer_->reset_change_counts();
base::Value connection_state_ready_value(shill::kStateReady);
service_test_->SetServiceProperty(eth1, shill::kStateProperty,
connection_state_ready_value);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(eth1, test_observer_->default_network());
EXPECT_EQ(shill::kStateReady,
test_observer_->default_network_connection_state());
EXPECT_EQ(1u, test_observer_->default_network_change_count());
}
TEST_F(NetworkStateHandlerTest, DefaultServiceChanged) {
const std::string eth1 = kShillManagerClientStubDefaultService;
// The default service should be eth1.
EXPECT_EQ(eth1, test_observer_->default_network());
// Change the default network by changing Manager.DefaultService.
// This should only generate one default network notification when the
// DefaultService property changes.
const std::string wifi1 = kShillManagerClientStubDefaultWifi;
SetServiceProperty(eth1, shill::kStateProperty,
base::Value(shill::kStateIdle));
manager_test_->SetManagerProperty(shill::kDefaultServiceProperty,
base::Value(wifi1));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(wifi1, test_observer_->default_network());
EXPECT_EQ(1u, test_observer_->default_network_change_count());
// Change the state of the default network. This should generate a
// default network notification.
test_observer_->reset_change_counts();
service_test_->SetServiceProperty(wifi1, shill::kStateProperty,
base::Value(shill::kStateReady));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(shill::kStateReady,
test_observer_->default_network_connection_state());
EXPECT_EQ(1u, test_observer_->default_network_change_count());
// Updating a property on the default network should also trigger
// a default network change.
test_observer_->reset_change_counts();
SetServiceProperty(wifi1, shill::kSecurityClassProperty,
base::Value("TestSecurityClass"));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1u, test_observer_->default_network_change_count());
// No default network updates for signal strength changes.
test_observer_->reset_change_counts();
SetServiceProperty(wifi1, shill::kSignalStrengthProperty, base::Value(32));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(0u, test_observer_->default_network_change_count());
// Change the default network to a Connecting network, then set the
// state to Connected. The DefaultNetworkChange notification should only
// fire once when the network is connected.
test_observer_->reset_change_counts();
SetServiceProperty(wifi1, shill::kStateProperty,
base::Value(shill::kStateIdle));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1u, test_observer_->default_network_change_count());
EXPECT_EQ(std::string(), test_observer_->default_network());
const std::string wifi2 = kShillManagerClientStubWifi2;
manager_test_->SetManagerProperty(shill::kDefaultServiceProperty,
base::Value(wifi2));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1u, test_observer_->default_network_change_count());
// Change the connection state of the default network, observer should fire.
SetServiceProperty(wifi2, shill::kStateProperty,
base::Value(shill::kStateReady));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(wifi2, test_observer_->default_network());
EXPECT_EQ(2u, test_observer_->default_network_change_count());
}
TEST_F(NetworkStateHandlerTest, RequestUpdate) {
// Request an update for kShillManagerClientStubDefaultWifi.
EXPECT_EQ(1, test_observer_->PropertyUpdatesForService(
kShillManagerClientStubDefaultWifi));
network_state_handler_->RequestUpdateForNetwork(
kShillManagerClientStubDefaultWifi);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(
kShillManagerClientStubDefaultWifi));
}
TEST_F(NetworkStateHandlerTest, RequestScan) {
EXPECT_EQ(0u, test_observer_->scan_requested_count());
network_state_handler_->RequestScan(NetworkTypePattern::WiFi());
EXPECT_EQ(1u, test_observer_->scan_requested_count());
}
TEST_F(NetworkStateHandlerTest, NetworkGuidInProfile) {
const std::string profile = "/profile/profile1";
const std::string wifi_path = "/service/wifi_with_guid";
const bool is_service_configured = true;
profile_test_->AddProfile(profile, std::string() /* userhash */);
// Add a network to the default Profile with a specified GUID.
AddService(wifi_path, kWifiGuid1, kWifiName1, shill::kTypeWifi,
shill::kStateOnline);
ASSERT_TRUE(profile_test_->AddService(profile, wifi_path));
UpdateManagerProperties();
// Verify that a NetworkState exists with a matching GUID.
const NetworkState* network =
network_state_handler_->GetNetworkStateFromServicePath(
wifi_path, is_service_configured);
ASSERT_TRUE(network);
EXPECT_EQ(kWifiGuid1, network->guid());
// Remove the service (simulating a network going out of range).
service_test_->RemoveService(wifi_path);
UpdateManagerProperties();
EXPECT_FALSE(network_state_handler_->GetNetworkState(wifi_path));
// Add the service (simulating a network coming back in range) and verify that
// the NetworkState was created with the same GUID.
AddService(wifi_path, std::string() /* guid */, kWifiName1, shill::kTypeWifi,
shill::kStateOnline);
profile_test_->UpdateService(profile, wifi_path);
UpdateManagerProperties();
network = network_state_handler_->GetNetworkStateFromServicePath(
wifi_path, is_service_configured);
ASSERT_TRUE(network);
EXPECT_EQ(kWifiGuid1, network->guid());
}
TEST_F(NetworkStateHandlerTest, NetworkGuidNotInProfile) {
const std::string wifi_path = "/service/wifi_with_guid";
const bool is_service_configured = false;
// Add a network without specifying a GUID or adding it to a profile.
AddService(wifi_path, "" /* guid */, kWifiName1, shill::kTypeWifi,
shill::kStateOnline);
UpdateManagerProperties();
// Verify that a NetworkState exists with an assigned GUID.
const NetworkState* network =
network_state_handler_->GetNetworkStateFromServicePath(
wifi_path, is_service_configured);
ASSERT_TRUE(network);
std::string wifi_guid = network->guid();
EXPECT_FALSE(wifi_guid.empty());
// Remove the service (simulating a network going out of range).
service_test_->RemoveService(wifi_path);
UpdateManagerProperties();
EXPECT_FALSE(network_state_handler_->GetNetworkState(wifi_path));
// Add the service (simulating a network coming back in range) and verify that
// the NetworkState was created with the same GUID.
AddService(wifi_path, "" /* guid */, kWifiName1, shill::kTypeWifi,
shill::kStateOnline);
UpdateManagerProperties();
network = network_state_handler_->GetNetworkStateFromServicePath(
wifi_path, is_service_configured);
ASSERT_TRUE(network);
EXPECT_EQ(wifi_guid, network->guid());
}
TEST_F(NetworkStateHandlerTest, DeviceListChanged) {
size_t stub_device_count = test_observer_->device_count();
// Add an additional device.
const std::string wifi_device = "/service/stub_wifi_device2";
device_test_->AddDevice(wifi_device, shill::kTypeWifi, "stub_wifi_device2");
UpdateManagerProperties();
// Expect a device list update.
EXPECT_EQ(stub_device_count + 1, test_observer_->device_count());
EXPECT_EQ(0, test_observer_->PropertyUpdatesForDevice(wifi_device));
// Change a device property.
device_test_->SetDeviceProperty(wifi_device, shill::kScanningProperty,
base::Value(true));
UpdateManagerProperties();
EXPECT_EQ(1, test_observer_->PropertyUpdatesForDevice(wifi_device));
}
TEST_F(NetworkStateHandlerTest, IPConfigChanged) {
test_observer_->reset_updates();
EXPECT_EQ(0, test_observer_->PropertyUpdatesForDevice(
kShillManagerClientStubWifiDevice));
EXPECT_EQ(0, test_observer_->PropertyUpdatesForService(
kShillManagerClientStubDefaultWifi));
// Change IPConfigs property.
ShillIPConfigClient::TestInterface* ip_config_test =
DBusThreadManager::Get()->GetShillIPConfigClient()->GetTestInterface();
const std::string kIPConfigPath = "test_ip_config";
base::DictionaryValue ip_config_properties;
ip_config_test->AddIPConfig(kIPConfigPath, ip_config_properties);
base::ListValue device_ip_configs;
device_ip_configs.AppendString(kIPConfigPath);
device_test_->SetDeviceProperty(
kShillManagerClientStubWifiDevice, shill::kIPConfigsProperty,
device_ip_configs);
service_test_->SetServiceProperty(kShillManagerClientStubDefaultWifi,
shill::kIPConfigProperty,
base::Value(kIPConfigPath));
UpdateManagerProperties();
EXPECT_EQ(1, test_observer_->PropertyUpdatesForDevice(
kShillManagerClientStubWifiDevice));
EXPECT_EQ(1, test_observer_->PropertyUpdatesForService(
kShillManagerClientStubDefaultWifi));
}
TEST_F(NetworkStateHandlerTest, UpdateGuid) {
const NetworkState* wifi1 = network_state_handler_->GetNetworkState(
kShillManagerClientStubDefaultWifi);
ASSERT_TRUE(wifi1);
EXPECT_EQ("wifi1_guid", wifi1->guid());
// Remove the wifi service.
service_test_->RemoveService(kShillManagerClientStubDefaultWifi);
base::RunLoop().RunUntilIdle();
wifi1 = network_state_handler_->GetNetworkState(
kShillManagerClientStubDefaultWifi);
EXPECT_FALSE(wifi1);
// Add the wifi service but do not specify a guid; the same guid should be
// reused.
AddService(kShillManagerClientStubDefaultWifi, "", "wifi1", shill::kTypeWifi,
shill::kStateOnline);
base::RunLoop().RunUntilIdle();
wifi1 = network_state_handler_->GetNetworkState(
kShillManagerClientStubDefaultWifi);
ASSERT_TRUE(wifi1);
EXPECT_EQ("wifi1_guid", wifi1->guid());
const NetworkState* cellular =
network_state_handler_->GetNetworkState(kShillManagerClientStubCellular);
ASSERT_TRUE(cellular);
EXPECT_EQ("cellular1_guid", cellular->guid());
// Remove the cellular service. This should create a default network with the
// same GUID.
service_test_->RemoveService(kShillManagerClientStubCellular);
base::RunLoop().RunUntilIdle();
// No service matching kShillManagerClientStubCellular.
EXPECT_FALSE(
network_state_handler_->GetNetworkState(kShillManagerClientStubCellular));
// The default cellular network should have the same guid as before.
cellular = network_state_handler_->FirstNetworkByType(
NetworkTypePattern::Cellular());
ASSERT_TRUE(cellular);
EXPECT_EQ("cellular1_guid", cellular->guid());
}
TEST_F(NetworkStateHandlerTest, EnsureCellularNetwork) {
// ClearServices will trigger a kServiceCompleteListProperty property change
// which will create a default Cellular network.
service_test_->ClearServices();
base::RunLoop().RunUntilIdle();
NetworkStateHandler::NetworkStateList cellular_networks;
network_state_handler_->GetNetworkListByType(
NetworkTypePattern::Cellular(), false /* configured_only */,
false /* visible_only */, 0, &cellular_networks);
ASSERT_EQ(1u, cellular_networks.size());
EXPECT_TRUE(cellular_networks[0]->IsDefaultCellular());
// Add a Cellular service. This should replace the default cellular network.
AddService(kShillManagerClientStubCellular, "cellular1_guid", "cellular1",
shill::kTypeCellular, shill::kStateIdle);
base::RunLoop().RunUntilIdle();
network_state_handler_->GetNetworkListByType(
NetworkTypePattern::Cellular(), false /* configured_only */,
false /* visible_only */, 0, &cellular_networks);
ASSERT_EQ(1u, cellular_networks.size());
EXPECT_FALSE(cellular_networks[0]->IsDefaultCellular());
EXPECT_EQ("/service/cellular1", cellular_networks[0]->path());
}
} // namespace chromeos