// 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/bind_helpers.h"
#include "base/command_line.h"
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/scoped_task_environment.h"
#include "base/values.h"
#include "chromeos/constants/chromeos_switches.h"
#include "chromeos/dbus/shill/shill_clients.h"
#include "chromeos/dbus/shill/shill_device_client.h"
#include "chromeos/dbus/shill/shill_ipconfig_client.h"
#include "chromeos/dbus/shill/shill_manager_client.h"
#include "chromeos/dbus/shill/shill_profile_client.h"
#include "chromeos/dbus/shill/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/network_ui_data.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 {

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;

const char kProfilePath[] = "/network/test";

void ErrorCallbackFunction(const std::string& error_name,
                           const std::string& error_message) {
  LOG(ERROR) << "Shill Error: " << error_name << " : " << error_message;
}

std::vector<std::string> GetNetworkPaths(
    const std::vector<const NetworkState*>& networks) {
  std::vector<std::string> result;
  for (const auto* network : networks)
    result.push_back(network->path());
  return result;
}

bool NetworkListContainsPath(const NetworkStateHandler::NetworkStateList& list,
                             const std::string& path) {
  return std::find_if(list.begin(), list.end(),
                      [path](const NetworkState* network) {
                        return network->path() == path;
                      }) != list.end();
}

class TestObserver final : public chromeos::NetworkStateHandlerObserver {
 public:
  explicit TestObserver(NetworkStateHandler* handler) : handler_(handler) {}
  ~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();
    ++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 ActiveNetworksChanged(
      const std::vector<const NetworkState*>& active_networks) override {
    ++active_network_change_count_;
    active_network_paths_ = GetNetworkPaths(active_networks);
  }

  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(const NetworkTypePattern& type) override {
    scan_requests_.push_back(type);
  }

  void ScanCompleted(const DeviceState* device) override {
    DCHECK(device);
    scan_completed_count_++;
  }

  size_t active_network_change_count() { return active_network_change_count_; }
  size_t default_network_change_count() {
    return default_network_change_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 scan_requested_count() { return scan_requests_.size(); }
  const std::vector<NetworkTypePattern>& scan_requests() {
    return scan_requests_;
  }
  size_t scan_completed_count() { return scan_completed_count_; }
  void reset_change_counts() {
    VLOG(1) << "=== RESET CHANGE COUNTS ===";
    active_network_change_count_ = 0;
    default_network_change_count_ = 0;
    device_list_changed_count_ = 0;
    network_list_changed_count_ = 0;
    scan_requests_.clear();
    scan_completed_count_ = 0;
    connection_state_changes_.clear();
  }
  void reset_updates() {
    property_updates_.clear();
    device_property_updates_.clear();
  }
  const std::vector<std::string>& active_network_paths() {
    return active_network_paths_;
  }
  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 active_network_change_count_ = 0;
  size_t default_network_change_count_ = 0;
  size_t device_list_changed_count_ = 0;
  size_t device_count_ = 0;
  size_t network_list_changed_count_ = 0;
  size_t network_count_ = 0;
  std::vector<NetworkTypePattern> scan_requests_;
  size_t scan_completed_count_ = 0;
  std::vector<std::string> active_network_paths_;
  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 {
    shill_clients::InitializeFakes();
    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();
    shill_clients::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_ = ShillDeviceClient::Get()->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_ = ShillManagerClient::Get()->GetTestInterface();
    ASSERT_TRUE(manager_test_);

    profile_test_ = ShillProfileClient::Get()->GetTestInterface();
    ASSERT_TRUE(profile_test_);
    profile_test_->ClearProfiles();

    service_test_ = ShillServiceClient::Get()->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) {
    ShillServiceClient::Get()->SetProperty(dbus::ObjectPath(service_path), key,
                                           value, base::DoNothing(),
                                           base::Bind(&ErrorCallbackFunction));
  }

  void SetProperties(NetworkState* network, const base::Value& properties) {
    // UpdateNetworkStateProperties expects 'Type' and 'WiFi.HexSSID' to always
    // be set.
    base::Value properties_to_set(properties.Clone());
    properties_to_set.SetKey(shill::kTypeProperty,
                             base::Value(network->type()));
    properties_to_set.SetKey(shill::kWifiHexSsid,
                             base::Value(network->GetHexSsid()));
    network_state_handler_->UpdateNetworkStateProperties(network,
                                                         properties_to_set);
  }

  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, NetworkStateHandlerStubActiveNetworks) {
  NetworkStateHandler::NetworkStateList active_networks;
  network_state_handler_->GetActiveNetworkListByType(
      NetworkTypePattern::Default(), &active_networks);
  std::vector<std::string> active_network_paths =
      GetNetworkPaths(active_networks);
  std::vector<std::string> expected_active_network_paths = {
      kShillManagerClientStubDefaultService,
      kShillManagerClientStubDefaultWifi};
  EXPECT_EQ(expected_active_network_paths, active_network_paths);

  EXPECT_EQ(
      kShillManagerClientStubDefaultService,
      network_state_handler_->ActiveNetworkByType(NetworkTypePattern::Default())
          ->path());
  EXPECT_EQ(kShillManagerClientStubDefaultService,
            network_state_handler_
                ->ActiveNetworkByType(NetworkTypePattern::Ethernet())
                ->path());
  EXPECT_EQ(
      kShillManagerClientStubDefaultWifi,
      network_state_handler_->ActiveNetworkByType(NetworkTypePattern::WiFi())
          ->path());

  // Activating Cellular should show up in the active list.
  service_test_->SetServiceProperty(
      kShillManagerClientStubCellular, shill::kActivationStateProperty,
      base::Value(shill::kActivationStateActivating));
  base::RunLoop().RunUntilIdle();
  expected_active_network_paths = {kShillManagerClientStubDefaultService,
                                   kShillManagerClientStubDefaultWifi,
                                   kShillManagerClientStubCellular};
  network_state_handler_->GetActiveNetworkListByType(
      NetworkTypePattern::Default(), &active_networks);
  active_network_paths = GetNetworkPaths(active_networks);
  EXPECT_EQ(expected_active_network_paths, active_network_paths);
}

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());

  // Get active networks.
  network_state_handler_->GetActiveNetworkListByType(
      NetworkTypePattern::Default(), &list);
  std::vector<std::string> active_network_paths = GetNetworkPaths(list);
  const std::vector<std::string> expected_active_network_paths = {
      kShillManagerClientStubDefaultService, kTetherGuid1,
      kShillManagerClientStubCellular};
  EXPECT_EQ(expected_active_network_paths, active_network_paths);
  EXPECT_EQ(
      kTetherGuid1,
      network_state_handler_->ActiveNetworkByType(NetworkTypePattern::Tether())
          ->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. No additional notification should be received when
  // Shill updates the enabled technologies since the state remains AVAILABLE.
  test_observer_->reset_change_counts();
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(0u, 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());
  EXPECT_EQ(0u, test_observer_->active_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());
  EXPECT_EQ(0u, test_observer_->active_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(1u, test_observer_->active_network_change_count());
  // Signal strength changes do not trigger a default network change.
  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->tether_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->tether_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,
       EthernetIsDefaultNetwork_ThenTetherConnects_ThenEthernetDisconnects) {
  network_state_handler_->SetTetherTechnologyState(
      NetworkStateHandler::TECHNOLOGY_ENABLED);

  // The ethernet corresponding to |eth1| starts out connected, then ends up
  // becoming disconnected.
  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));

  // No default network changes should have occurred, since the Ethernet
  // network should still be considered the default network.
  EXPECT_EQ(0u, test_observer_->default_network_change_count());

  // Disconnect from the Ethernet network.
  service_test_->SetServiceProperty(eth1, shill::kStateProperty,
                                    base::Value(shill::kStateIdle));
  base::RunLoop().RunUntilIdle();

  // The Tether network should now be the default network. However, there should
  // have been two updates to the default network: one which changed it from
  // |eth1| to null, then one from null to |kTetherGuid1"|.
  EXPECT_EQ(2u, test_observer_->default_network_change_count());
  EXPECT_EQ(kTetherGuid1, 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, NetworkActiveNetworksStateChanged) {
  // Initial state is just connected to Ethernet.
  std::vector<std::string> expected_active_network_paths = {
      kShillManagerClientStubDefaultService,
      kShillManagerClientStubDefaultWifi};
  EXPECT_EQ(expected_active_network_paths,
            test_observer_->active_network_paths());

  // Remove Ethernet.
  service_test_->RemoveService(kShillManagerClientStubDefaultService);
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(1u, test_observer_->active_network_change_count());
  expected_active_network_paths = {kShillManagerClientStubDefaultWifi};
  EXPECT_EQ(expected_active_network_paths,
            test_observer_->active_network_paths());

  // Modify the wifi signal strength, an observer update should occur.
  test_observer_->reset_change_counts();
  service_test_->SetServiceProperty(kShillManagerClientStubDefaultWifi,
                                    shill::kSignalStrengthProperty,
                                    base::Value(100));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(1u, test_observer_->active_network_change_count());

  // A small change should not trigger an update.
  test_observer_->reset_change_counts();
  service_test_->SetServiceProperty(kShillManagerClientStubDefaultWifi,
                                    shill::kSignalStrengthProperty,
                                    base::Value(99));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(0u, test_observer_->active_network_change_count());

  // Disconnect Wifi1.
  test_observer_->reset_change_counts();
  service_test_->SetServiceProperty(kShillManagerClientStubDefaultWifi,
                                    shill::kStateProperty,
                                    base::Value(shill::kStateIdle));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(1u, test_observer_->active_network_change_count());
  expected_active_network_paths = {};
  EXPECT_EQ(expected_active_network_paths,
            test_observer_->active_network_paths());

  // Confirm that changing the connection state to the same value does *not*
  // signal the observer.
  service_test_->SetServiceProperty(kShillManagerClientStubDefaultWifi,
                                    shill::kStateProperty,
                                    base::Value(shill::kStateIdle));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(1u, test_observer_->active_network_change_count());

  // Add two Tether networks.
  test_observer_->reset_change_counts();
  network_state_handler_->SetTetherTechnologyState(
      NetworkStateHandler::TECHNOLOGY_ENABLED);
  network_state_handler_->AddTetherNetworkState(
      kTetherGuid1, kTetherName1, kTetherCarrier1, kTetherBatteryPercentage1,
      kTetherSignalStrength1, kTetherHasConnectedToHost1);
  network_state_handler_->AddTetherNetworkState(
      kTetherGuid2, kTetherName2, kTetherCarrier2, kTetherBatteryPercentage2,
      kTetherSignalStrength2, kTetherHasConnectedToHost2);
  network_state_handler_->SetTetherNetworkStateConnecting(kTetherGuid1);
  network_state_handler_->AssociateTetherNetworkStateWithWifiNetwork(
      kTetherGuid1, "wifi2_guid");
  service_test_->SetServiceProperty(kShillManagerClientStubWifi2,
                                    shill::kStateProperty,
                                    base::Value(shill::kStateOnline));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(1u, test_observer_->active_network_change_count());

  // Connect the first Tether network.
  test_observer_->reset_change_counts();
  network_state_handler_->SetTetherNetworkStateConnected(kTetherGuid1);
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(1u, test_observer_->active_network_change_count());
  expected_active_network_paths = {kTetherGuid1};
  EXPECT_EQ(expected_active_network_paths,
            test_observer_->active_network_paths());

  // Reconnect Ethernet
  test_observer_->reset_change_counts();
  AddService(kShillManagerClientStubDefaultService, "eth1_guid", "eth1",
             shill::kTypeEthernet, shill::kStateOnline);
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(1u, test_observer_->active_network_change_count());
  expected_active_network_paths = {kShillManagerClientStubDefaultService,
                                   kTetherGuid1};
  EXPECT_EQ(expected_active_network_paths,
            test_observer_->active_network_paths());
}

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());
  network_state_handler_->RequestScan(NetworkTypePattern::Tether());
  EXPECT_EQ(2u, test_observer_->scan_requested_count());
  EXPECT_TRUE(
      NetworkTypePattern::WiFi().Equals(test_observer_->scan_requests()[0]));
  EXPECT_TRUE(
      NetworkTypePattern::Tether().Equals(test_observer_->scan_requests()[1]));

  // Disable wifi, scan request for wifi only should not send a notification.
  test_observer_->reset_change_counts();
  network_state_handler_->SetTechnologyEnabled(
      NetworkTypePattern::WiFi(), false, network_handler::ErrorCallback());
  network_state_handler_->RequestScan(NetworkTypePattern::WiFi());
  EXPECT_EQ(0u, test_observer_->scan_requested_count());
  network_state_handler_->RequestScan(NetworkTypePattern::Default());
  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), /*notify_changed=*/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 =
      ShillIPConfigClient::Get()->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,
                                  /*notify_changed=*/true);
  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, DefaultCellularNetwork) {
  // 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());
}

TEST_F(NetworkStateHandlerTest, RemoveDefaultCellularNetwork) {
  // 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());

  // Removing the Cellular device should remove the default cellular network.
  device_test_->RemoveDevice(kShillManagerClientStubCellularDevice);
  base::RunLoop().RunUntilIdle();
  network_state_handler_->GetNetworkListByType(
      NetworkTypePattern::Cellular(), false /* configured_only */,
      false /* visible_only */, 0, &cellular_networks);
  EXPECT_EQ(0u, cellular_networks.size());
}

TEST_F(NetworkStateHandlerTest, UpdateCaptivePortalProvider) {
  constexpr char kProviderId[] = "TestProviderId";
  constexpr char kProviderName[] = "TestProviderName";

  // Verify initial state.
  const NetworkState* wifi1 = network_state_handler_->GetNetworkState(
      kShillManagerClientStubDefaultWifi);
  ASSERT_TRUE(wifi1);
  const NetworkState::CaptivePortalProviderInfo* info =
      wifi1->captive_portal_provider();
  EXPECT_EQ(nullptr, info);

  // Verify that setting a captive portal provider applies to existing networks.
  std::string hex_ssid = wifi1->GetHexSsid();
  ASSERT_FALSE(hex_ssid.empty());
  network_state_handler_->SetCaptivePortalProviderForHexSsid(
      hex_ssid, kProviderId, kProviderName);
  base::RunLoop().RunUntilIdle();

  info = wifi1->captive_portal_provider();
  ASSERT_NE(nullptr, info);
  EXPECT_EQ(kProviderId, info->id);
  EXPECT_EQ(kProviderName, info->name);

  // Verify that adding a new network sets its captive portal provider.
  constexpr char kNewSsid[] = "new_wifi";
  std::string new_hex_ssid = base::HexEncode(kNewSsid, strlen(kNewSsid));
  network_state_handler_->SetCaptivePortalProviderForHexSsid(
      new_hex_ssid, kProviderId, kProviderName);
  AddService("/service/new_wifi", "new_wifi_guid", kNewSsid, shill::kTypeWifi,
             shill::kStateOnline);
  base::RunLoop().RunUntilIdle();

  const NetworkState* new_wifi =
      network_state_handler_->GetNetworkState("/service/new_wifi");
  ASSERT_TRUE(new_wifi);
  info = new_wifi->captive_portal_provider();
  ASSERT_NE(nullptr, info);
  EXPECT_EQ(kProviderId, info->id);
  EXPECT_EQ(kProviderName, info->name);
}

TEST_F(NetworkStateHandlerTest, BlockedByPolicyBlacklisted) {
  NetworkState* wifi1 = network_state_handler_->GetModifiableNetworkState(
      kShillManagerClientStubDefaultWifi);
  NetworkState* wifi2 = network_state_handler_->GetModifiableNetworkState(
      kShillManagerClientStubWifi2);

  EXPECT_FALSE(network_state_handler_->OnlyManagedWifiNetworksAllowed());
  EXPECT_FALSE(wifi1->IsManagedByPolicy());
  EXPECT_FALSE(wifi2->IsManagedByPolicy());
  EXPECT_FALSE(wifi1->blocked_by_policy());
  EXPECT_FALSE(wifi2->blocked_by_policy());

  std::vector<std::string> blacklist;
  blacklist.push_back(wifi1->GetHexSsid());
  network_state_handler_->UpdateBlockedWifiNetworks(false, false, blacklist);

  EXPECT_FALSE(network_state_handler_->OnlyManagedWifiNetworksAllowed());
  EXPECT_EQ(blacklist, network_state_handler_->blacklisted_hex_ssids_);
  EXPECT_TRUE(wifi1->blocked_by_policy());
  EXPECT_FALSE(wifi2->blocked_by_policy());

  // Emulate 'wifi1' being a managed network.
  std::unique_ptr<NetworkUIData> ui_data =
      NetworkUIData::CreateFromONC(::onc::ONCSource::ONC_SOURCE_USER_POLICY);
  base::Value properties(base::Value::Type::DICTIONARY);
  properties.SetKey(shill::kProfileProperty, base::Value(kProfilePath));
  properties.SetKey(shill::kUIDataProperty, base::Value(ui_data->GetAsJson()));
  SetProperties(wifi1, properties);

  EXPECT_FALSE(network_state_handler_->OnlyManagedWifiNetworksAllowed());
  EXPECT_EQ(blacklist, network_state_handler_->blacklisted_hex_ssids_);
  EXPECT_TRUE(wifi1->IsManagedByPolicy());
  EXPECT_FALSE(wifi2->IsManagedByPolicy());
  EXPECT_FALSE(wifi1->blocked_by_policy());
  EXPECT_FALSE(wifi2->blocked_by_policy());
}

TEST_F(NetworkStateHandlerTest, BlockedByPolicyOnlyManaged) {
  NetworkState* wifi1 = network_state_handler_->GetModifiableNetworkState(
      kShillManagerClientStubDefaultWifi);
  NetworkState* wifi2 = network_state_handler_->GetModifiableNetworkState(
      kShillManagerClientStubWifi2);

  EXPECT_FALSE(network_state_handler_->OnlyManagedWifiNetworksAllowed());
  EXPECT_FALSE(wifi1->IsManagedByPolicy());
  EXPECT_FALSE(wifi2->IsManagedByPolicy());
  EXPECT_FALSE(wifi1->blocked_by_policy());
  EXPECT_FALSE(wifi2->blocked_by_policy());

  network_state_handler_->UpdateBlockedWifiNetworks(true, false,
                                                    std::vector<std::string>());

  EXPECT_TRUE(network_state_handler_->OnlyManagedWifiNetworksAllowed());
  EXPECT_TRUE(wifi1->blocked_by_policy());
  EXPECT_TRUE(wifi2->blocked_by_policy());

  // Emulate 'wifi1' being a managed network.
  std::unique_ptr<NetworkUIData> ui_data =
      NetworkUIData::CreateFromONC(::onc::ONCSource::ONC_SOURCE_USER_POLICY);
  base::Value properties(base::Value::Type::DICTIONARY);
  properties.SetKey(shill::kProfileProperty, base::Value(kProfilePath));
  properties.SetKey(shill::kUIDataProperty, base::Value(ui_data->GetAsJson()));
  SetProperties(wifi1, properties);

  EXPECT_TRUE(network_state_handler_->OnlyManagedWifiNetworksAllowed());
  EXPECT_TRUE(wifi1->IsManagedByPolicy());
  EXPECT_FALSE(wifi2->IsManagedByPolicy());
  EXPECT_FALSE(wifi1->blocked_by_policy());
  EXPECT_TRUE(wifi2->blocked_by_policy());
}

TEST_F(NetworkStateHandlerTest, BlockedByPolicyOnlyManagedIfAvailable) {
  NetworkState* wifi1 = network_state_handler_->GetModifiableNetworkState(
      kShillManagerClientStubDefaultWifi);
  NetworkState* wifi2 = network_state_handler_->GetModifiableNetworkState(
      kShillManagerClientStubWifi2);

  EXPECT_FALSE(wifi1->IsManagedByPolicy());
  EXPECT_FALSE(wifi2->IsManagedByPolicy());
  EXPECT_FALSE(wifi1->blocked_by_policy());
  EXPECT_FALSE(wifi2->blocked_by_policy());
  EXPECT_FALSE(network_state_handler_->OnlyManagedWifiNetworksAllowed());

  network_state_handler_->UpdateBlockedWifiNetworks(false, true,
                                                    std::vector<std::string>());

  EXPECT_EQ(nullptr, network_state_handler_->GetAvailableManagedWifiNetwork());
  EXPECT_FALSE(wifi1->blocked_by_policy());
  EXPECT_FALSE(wifi2->blocked_by_policy());
  EXPECT_FALSE(network_state_handler_->OnlyManagedWifiNetworksAllowed());

  // Emulate 'wifi1' being a managed network.
  std::unique_ptr<NetworkUIData> ui_data =
      NetworkUIData::CreateFromONC(::onc::ONCSource::ONC_SOURCE_USER_POLICY);
  base::Value properties(base::Value::Type::DICTIONARY);
  properties.SetKey(shill::kProfileProperty, base::Value(kProfilePath));
  properties.SetKey(shill::kUIDataProperty, base::Value(ui_data->GetAsJson()));
  SetProperties(wifi1, properties);
  network_state_handler_->UpdateManagedWifiNetworkAvailable();

  EXPECT_EQ(wifi1, network_state_handler_->GetAvailableManagedWifiNetwork());
  EXPECT_TRUE(network_state_handler_->OnlyManagedWifiNetworksAllowed());
  EXPECT_TRUE(wifi1->IsManagedByPolicy());
  EXPECT_FALSE(wifi2->IsManagedByPolicy());
  EXPECT_FALSE(wifi1->blocked_by_policy());
  EXPECT_TRUE(wifi2->blocked_by_policy());
}

TEST_F(NetworkStateHandlerTest, SetNetworkConnectRequested) {
  // Verify that wifi2 is not connected or connecting and is not part of the
  // active list.
  const NetworkState* wifi2 =
      network_state_handler_->GetNetworkState(kShillManagerClientStubWifi2);
  EXPECT_FALSE(wifi2->IsConnectingOrConnected());
  NetworkStateHandler::NetworkStateList active_networks;
  network_state_handler_->GetActiveNetworkListByType(
      NetworkTypePattern::Default(), &active_networks);
  EXPECT_FALSE(
      NetworkListContainsPath(active_networks, kShillManagerClientStubWifi2));

  // Set |connect_requested_| for wifi2 and verify that it is connecting and
  // in the active list.
  network_state_handler_->SetNetworkConnectRequested(
      kShillManagerClientStubWifi2, true);
  base::RunLoop().RunUntilIdle();
  EXPECT_TRUE(wifi2->IsConnectingState());
  network_state_handler_->GetActiveNetworkListByType(
      NetworkTypePattern::Default(), &active_networks);
  EXPECT_TRUE(
      NetworkListContainsPath(active_networks, kShillManagerClientStubWifi2));

  // Clear |connect_requested_| for wifi2 and verify that it is not connecting
  // or in the active list.
  network_state_handler_->SetNetworkConnectRequested(
      kShillManagerClientStubWifi2, false);
  base::RunLoop().RunUntilIdle();
  EXPECT_FALSE(wifi2->IsConnectingState());
  network_state_handler_->GetActiveNetworkListByType(
      NetworkTypePattern::Default(), &active_networks);
  EXPECT_FALSE(
      NetworkListContainsPath(active_networks, kShillManagerClientStubWifi2));
}

TEST_F(NetworkStateHandlerTest, SetNetworkChromePortalDetected) {
  const NetworkState* network = network_state_handler_->DefaultNetwork();
  EXPECT_FALSE(network->IsCaptivePortal());

  test_observer_->reset_updates();
  network_state_handler_->SetNetworkChromePortalDetected(network->path(), true);
  base::RunLoop().RunUntilIdle();
  EXPECT_TRUE(network->IsCaptivePortal());
  EXPECT_EQ(1,
            test_observer_->ConnectionStateChangesForService(network->path()));
  network_state_handler_->SetNetworkChromePortalDetected(network->path(),
                                                         false);
  base::RunLoop().RunUntilIdle();
  network = network_state_handler_->DefaultNetwork();
  EXPECT_FALSE(network->IsCaptivePortal());
  EXPECT_EQ(2,
            test_observer_->ConnectionStateChangesForService(network->path()));
}

}  // namespace chromeos
