// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <iostream>
#include <sstream>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/location.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
#include "base/thread_task_runner_handle.h"
#include "base/values.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/mock_shill_manager_client.h"
#include "chromeos/dbus/mock_shill_profile_client.h"
#include "chromeos/dbus/mock_shill_service_client.h"
#include "chromeos/dbus/shill_client_helper.h"
#include "chromeos/network/managed_network_configuration_handler_impl.h"
#include "chromeos/network/network_configuration_handler.h"
#include "chromeos/network/network_policy_observer.h"
#include "chromeos/network/network_profile_handler.h"
#include "chromeos/network/network_state_handler.h"
#include "chromeos/network/onc/onc_test_utils.h"
#include "chromeos/network/onc/onc_utils.h"
#include "dbus/object_path.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/cros_system_api/dbus/service_constants.h"

using ::testing::AnyNumber;
using ::testing::Invoke;
using ::testing::Mock;
using ::testing::Pointee;
using ::testing::Return;
using ::testing::SaveArg;
using ::testing::StrEq;
using ::testing::StrictMock;
using ::testing::_;

namespace test_utils = ::chromeos::onc::test_utils;

namespace chromeos {

namespace {

std::string ValueToString(const base::Value* value) {
  std::stringstream str;
  str << *value;
  return str.str();
}

void DereferenceAndCall(
    base::Callback<void(const base::DictionaryValue& result)> callback,
    const base::DictionaryValue* value) {
  callback.Run(*value);
}

const char kUser1[] = "user1";
const char kUser1ProfilePath[] = "/profile/user1/shill";

// Matcher to match base::Value.
MATCHER_P(IsEqualTo,
          value,
          std::string(negation ? "isn't" : "is") + " equal to " +
              ValueToString(value)) {
  return value->Equals(&arg);
}

// Match properties in |value| to |arg|. |arg| may contain extra properties).
MATCHER_P(MatchesProperties,
          value,
          std::string(negation ? "does't match " : "matches ") +
              ValueToString(value)) {
  for (base::DictionaryValue::Iterator iter(*value); !iter.IsAtEnd();
       iter.Advance()) {
    const base::Value* property;
    if (!arg.GetWithoutPathExpansion(iter.key(), &property) ||
        !iter.value().Equals(property)) {
      return false;
    }
  }
  return true;
}

class ShillProfileTestClient {
 public:
  typedef ShillClientHelper::DictionaryValueCallbackWithoutStatus
      DictionaryValueCallbackWithoutStatus;
  typedef ShillClientHelper::ErrorCallback ErrorCallback;

  void AddProfile(const std::string& profile_path,
                  const std::string& userhash) {
    if (profile_entries_.HasKey(profile_path))
      return;

    base::DictionaryValue* profile = new base::DictionaryValue;
    profile_entries_.SetWithoutPathExpansion(profile_path, profile);
    profile_to_user_[profile_path] = userhash;
  }

  void AddEntry(const std::string& profile_path,
                const std::string& entry_path,
                const base::DictionaryValue& entry) {
    base::DictionaryValue* entries = NULL;
    profile_entries_.GetDictionaryWithoutPathExpansion(profile_path, &entries);
    ASSERT_TRUE(entries);

    base::DictionaryValue* new_entry = entry.DeepCopy();
    new_entry->SetStringWithoutPathExpansion(shill::kProfileProperty,
                                             profile_path);
    entries->SetWithoutPathExpansion(entry_path, new_entry);
  }

  void GetProperties(const dbus::ObjectPath& profile_path,
                     const DictionaryValueCallbackWithoutStatus& callback,
                     const ErrorCallback& error_callback) {
    base::DictionaryValue* entries = NULL;
    profile_entries_.GetDictionaryWithoutPathExpansion(profile_path.value(),
                                                       &entries);
    ASSERT_TRUE(entries);

    scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue);
    base::ListValue* entry_paths = new base::ListValue;
    result->SetWithoutPathExpansion(shill::kEntriesProperty, entry_paths);
    for (base::DictionaryValue::Iterator it(*entries); !it.IsAtEnd();
         it.Advance()) {
      entry_paths->AppendString(it.key());
    }

    ASSERT_TRUE(ContainsKey(profile_to_user_, profile_path.value()));
    const std::string& userhash = profile_to_user_[profile_path.value()];
    result->SetStringWithoutPathExpansion(shill::kUserHashProperty, userhash);

    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE, base::Bind(base::Bind(&DereferenceAndCall, callback),
                              base::Owned(result.release())));
  }

  void GetEntry(const dbus::ObjectPath& profile_path,
                const std::string& entry_path,
                const DictionaryValueCallbackWithoutStatus& callback,
                const ErrorCallback& error_callback) {
    base::DictionaryValue* entries = NULL;
    profile_entries_.GetDictionaryWithoutPathExpansion(profile_path.value(),
                                                       &entries);
    ASSERT_TRUE(entries);

    base::DictionaryValue* entry = NULL;
    entries->GetDictionaryWithoutPathExpansion(entry_path, &entry);
    ASSERT_TRUE(entry);
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE, base::Bind(base::Bind(&DereferenceAndCall, callback),
                              base::Owned(entry->DeepCopy())));
  }

 protected:
  base::DictionaryValue profile_entries_;
  std::map<std::string, std::string> profile_to_user_;
};

class ShillServiceTestClient {
 public:
  typedef ShillClientHelper::DictionaryValueCallback DictionaryValueCallback;
  void SetFakeProperties(const base::DictionaryValue& service_properties) {
    service_properties_.Clear();
    service_properties_.MergeDictionary(&service_properties);
  }

  void GetProperties(const dbus::ObjectPath& service_path,
                     const DictionaryValueCallback& callback) {
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS,
                              base::ConstRef(service_properties_)));
  }

 protected:
  base::DictionaryValue service_properties_;
};

class TestNetworkProfileHandler : public NetworkProfileHandler {
 public:
  TestNetworkProfileHandler() {
    Init();
  }
  ~TestNetworkProfileHandler() override {}

  void AddProfileForTest(const NetworkProfile& profile) {
    AddProfile(profile);
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(TestNetworkProfileHandler);
};

class TestNetworkPolicyObserver : public NetworkPolicyObserver {
 public:
  TestNetworkPolicyObserver() : policies_applied_count_(0) {}

  void PoliciesApplied(const std::string& userhash) override {
    policies_applied_count_++;
  };

  int GetPoliciesAppliedCountAndReset() {
    int count = policies_applied_count_;
    policies_applied_count_ = 0;
    return count;
  }

 private:
  int policies_applied_count_;

  DISALLOW_COPY_AND_ASSIGN(TestNetworkPolicyObserver);
};

}  // namespace

class ManagedNetworkConfigurationHandlerTest : public testing::Test {
 public:
  ManagedNetworkConfigurationHandlerTest()
      : mock_manager_client_(NULL),
        mock_profile_client_(NULL),
        mock_service_client_(NULL) {
  }

  ~ManagedNetworkConfigurationHandlerTest() override {}

  void SetUp() override {
    scoped_ptr<DBusThreadManagerSetter> dbus_setter =
        DBusThreadManager::GetSetterForTesting();
    mock_manager_client_ = new StrictMock<MockShillManagerClient>();
    mock_profile_client_ = new StrictMock<MockShillProfileClient>();
    mock_service_client_ = new StrictMock<MockShillServiceClient>();
    dbus_setter->SetShillManagerClient(
        scoped_ptr<ShillManagerClient>(mock_manager_client_).Pass());
    dbus_setter->SetShillProfileClient(
        scoped_ptr<ShillProfileClient>(mock_profile_client_).Pass());
    dbus_setter->SetShillServiceClient(
        scoped_ptr<ShillServiceClient>(mock_service_client_).Pass());

    SetNetworkConfigurationHandlerExpectations();

    ON_CALL(*mock_profile_client_, GetProperties(_,_,_))
        .WillByDefault(Invoke(&profiles_stub_,
                              &ShillProfileTestClient::GetProperties));

    ON_CALL(*mock_profile_client_, GetEntry(_,_,_,_))
        .WillByDefault(Invoke(&profiles_stub_,
                              &ShillProfileTestClient::GetEntry));

    ON_CALL(*mock_service_client_, GetProperties(_,_))
        .WillByDefault(Invoke(&services_stub_,
                              &ShillServiceTestClient::GetProperties));

    network_state_handler_.reset(NetworkStateHandler::InitializeForTest());
    network_profile_handler_.reset(new TestNetworkProfileHandler());
    network_configuration_handler_.reset(
        NetworkConfigurationHandler::InitializeForTest(
            network_state_handler_.get(),
            nullptr /* no NetworkDeviceHandler */));
    managed_network_configuration_handler_.reset(
        new ManagedNetworkConfigurationHandlerImpl());
    managed_network_configuration_handler_->Init(
        network_state_handler_.get(), network_profile_handler_.get(),
        network_configuration_handler_.get(), nullptr /* no DeviceHandler */,
        nullptr /* no ProhibitedTechnologiesHandler */);
    managed_network_configuration_handler_->AddObserver(&policy_observer_);

    message_loop_.RunUntilIdle();
  }

  void TearDown() override {
    if (managed_network_configuration_handler_)
      managed_network_configuration_handler_->RemoveObserver(&policy_observer_);
    network_state_handler_.reset();
    managed_network_configuration_handler_.reset();
    network_configuration_handler_.reset();
    network_profile_handler_.reset();
    DBusThreadManager::Shutdown();
  }

  void VerifyAndClearExpectations() {
    Mock::VerifyAndClearExpectations(mock_manager_client_);
    Mock::VerifyAndClearExpectations(mock_profile_client_);
    SetNetworkConfigurationHandlerExpectations();
  }

  void InitializeStandardProfiles() {
    profiles_stub_.AddProfile(kUser1ProfilePath, kUser1);
    network_profile_handler_->
        AddProfileForTest(NetworkProfile(kUser1ProfilePath, kUser1));

    profiles_stub_.AddProfile(NetworkProfileHandler::GetSharedProfilePath(),
                              std::string() /* no userhash */);
    network_profile_handler_->AddProfileForTest(
        NetworkProfile(NetworkProfileHandler::GetSharedProfilePath(),
                       std::string() /* no userhash */));
  }

  void SetUpEntry(const std::string& path_to_shill_json,
                  const std::string& profile_path,
                  const std::string& entry_path) {
    scoped_ptr<base::DictionaryValue> entry =
        test_utils::ReadTestDictionary(path_to_shill_json);
    profiles_stub_.AddEntry(profile_path, entry_path, *entry);
  }

  void SetPolicy(::onc::ONCSource onc_source,
                 const std::string& userhash,
                 const std::string& path_to_onc) {
    scoped_ptr<base::DictionaryValue> policy;
    if (path_to_onc.empty())
      policy = onc::ReadDictionaryFromJson(onc::kEmptyUnencryptedConfiguration);
    else
      policy = test_utils::ReadTestDictionary(path_to_onc);

    base::ListValue empty_network_configs;
    base::ListValue* network_configs = &empty_network_configs;
    policy->GetListWithoutPathExpansion(
        ::onc::toplevel_config::kNetworkConfigurations, &network_configs);

    base::DictionaryValue empty_global_config;
    base::DictionaryValue* global_network_config = &empty_global_config;
    policy->GetDictionaryWithoutPathExpansion(
        ::onc::toplevel_config::kGlobalNetworkConfiguration,
        &global_network_config);

    managed_handler()->SetPolicy(
        onc_source, userhash, *network_configs, *global_network_config);
  }

  void SetNetworkConfigurationHandlerExpectations() {
    // These calls occur in NetworkConfigurationHandler.
    EXPECT_CALL(*mock_manager_client_, GetProperties(_)).Times(AnyNumber());
    EXPECT_CALL(*mock_manager_client_,
                SetProperty("ProhibitedTechnologies", _, _, _))
        .Times(AnyNumber());
    EXPECT_CALL(*mock_manager_client_, AddPropertyChangedObserver(_))
        .Times(AnyNumber());
    EXPECT_CALL(*mock_manager_client_,
                RemovePropertyChangedObserver(_)).Times(AnyNumber());
  }

  ManagedNetworkConfigurationHandler* managed_handler() {
    return managed_network_configuration_handler_.get();
  }

  void GetManagedProperties(const std::string& userhash,
                            const std::string& service_path) {
    managed_handler()->GetManagedProperties(
        userhash,
        service_path,
        base::Bind(
            &ManagedNetworkConfigurationHandlerTest::GetPropertiesCallback,
            base::Unretained(this)),
        base::Bind(&ManagedNetworkConfigurationHandlerTest::UnexpectedError));
  }

  void GetPropertiesCallback(const std::string& service_path,
                             const base::DictionaryValue& dictionary) {
    get_properties_service_path_ = service_path;
    get_properties_result_.Clear();
    get_properties_result_.MergeDictionary(&dictionary);
  }

  static void UnexpectedError(const std::string& error_name,
                              scoped_ptr<base::DictionaryValue> error_data) {
    ASSERT_FALSE(true);
  }

 protected:
  MockShillManagerClient* mock_manager_client_;
  MockShillProfileClient* mock_profile_client_;
  MockShillServiceClient* mock_service_client_;
  ShillProfileTestClient profiles_stub_;
  ShillServiceTestClient services_stub_;
  TestNetworkPolicyObserver policy_observer_;
  scoped_ptr<NetworkStateHandler> network_state_handler_;
  scoped_ptr<TestNetworkProfileHandler> network_profile_handler_;
  scoped_ptr<NetworkConfigurationHandler> network_configuration_handler_;
  scoped_ptr<ManagedNetworkConfigurationHandlerImpl>
        managed_network_configuration_handler_;
  base::MessageLoop message_loop_;

  std::string get_properties_service_path_;
  base::DictionaryValue get_properties_result_;

 private:
  DISALLOW_COPY_AND_ASSIGN(ManagedNetworkConfigurationHandlerTest);
};

TEST_F(ManagedNetworkConfigurationHandlerTest, ProfileInitialization) {
  InitializeStandardProfiles();
  message_loop_.RunUntilIdle();
}

TEST_F(ManagedNetworkConfigurationHandlerTest, RemoveIrrelevantFields) {
  InitializeStandardProfiles();
  scoped_ptr<base::DictionaryValue> expected_shill_properties =
      test_utils::ReadTestDictionary(
          "policy/shill_policy_on_unconfigured_wifi1.json");

  EXPECT_CALL(*mock_profile_client_,
              GetProperties(dbus::ObjectPath(kUser1ProfilePath), _, _));

  EXPECT_CALL(*mock_manager_client_,
              ConfigureServiceForProfile(
                  dbus::ObjectPath(kUser1ProfilePath),
                  IsEqualTo(expected_shill_properties.get()),
                  _, _));

  SetPolicy(::onc::ONC_SOURCE_USER_POLICY,
            kUser1,
            "policy/policy_wifi1_with_redundant_fields.onc");
  message_loop_.RunUntilIdle();
}

TEST_F(ManagedNetworkConfigurationHandlerTest, SetPolicyManageUnconfigured) {
  InitializeStandardProfiles();
  scoped_ptr<base::DictionaryValue> expected_shill_properties =
      test_utils::ReadTestDictionary(
          "policy/shill_policy_on_unconfigured_wifi1.json");

  EXPECT_CALL(*mock_profile_client_,
              GetProperties(dbus::ObjectPath(kUser1ProfilePath), _, _));

  EXPECT_CALL(*mock_manager_client_,
              ConfigureServiceForProfile(
                  dbus::ObjectPath(kUser1ProfilePath),
                  IsEqualTo(expected_shill_properties.get()),
                  _, _));

  SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc");
  message_loop_.RunUntilIdle();
}

TEST_F(ManagedNetworkConfigurationHandlerTest, EnableManagedCredentialsWiFi) {
  InitializeStandardProfiles();
  scoped_ptr<base::DictionaryValue> expected_shill_properties =
      test_utils::ReadTestDictionary(
          "policy/shill_policy_autoconnect_on_unconfigured_wifi1.json");

  EXPECT_CALL(*mock_profile_client_,
              GetProperties(dbus::ObjectPath(kUser1ProfilePath), _, _));

  EXPECT_CALL(*mock_manager_client_,
              ConfigureServiceForProfile(
                  dbus::ObjectPath(kUser1ProfilePath),
                  IsEqualTo(expected_shill_properties.get()),
                  _, _));

  SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1,
            "policy/policy_wifi1_autoconnect.onc");
  message_loop_.RunUntilIdle();
}

TEST_F(ManagedNetworkConfigurationHandlerTest, EnableManagedCredentialsVPN) {
  InitializeStandardProfiles();
  scoped_ptr<base::DictionaryValue> expected_shill_properties =
      test_utils::ReadTestDictionary(
          "policy/shill_policy_autoconnect_on_unconfigured_vpn.json");

  EXPECT_CALL(*mock_profile_client_,
              GetProperties(dbus::ObjectPath(kUser1ProfilePath), _, _));

  EXPECT_CALL(*mock_manager_client_,
              ConfigureServiceForProfile(
                  dbus::ObjectPath(kUser1ProfilePath),
                  IsEqualTo(expected_shill_properties.get()),
                  _, _));

  SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1,
            "policy/policy_vpn_autoconnect.onc");
  message_loop_.RunUntilIdle();
}

// Ensure that EAP settings for ethernet are matched with the right profile
// entry and written to the dedicated EthernetEAP service.
TEST_F(ManagedNetworkConfigurationHandlerTest,
       SetPolicyManageUnmanagedEthernetEAP) {
  InitializeStandardProfiles();
  scoped_ptr<base::DictionaryValue> expected_shill_properties =
      test_utils::ReadTestDictionary(
          "policy/"
          "shill_policy_on_unmanaged_ethernet_eap.json");

  SetUpEntry("policy/shill_unmanaged_ethernet_eap.json",
             kUser1ProfilePath,
             "eth_entry");

  // Also setup an unrelated WiFi configuration to verify that the right entry
  // is matched.
  SetUpEntry("policy/shill_unmanaged_wifi1.json",
             kUser1ProfilePath,
             "wifi_entry");

  EXPECT_CALL(*mock_profile_client_,
              GetProperties(dbus::ObjectPath(kUser1ProfilePath), _, _));

  EXPECT_CALL(*mock_profile_client_,
              GetEntry(dbus::ObjectPath(kUser1ProfilePath), _, _, _)).Times(2);

  EXPECT_CALL(
      *mock_profile_client_,
      DeleteEntry(dbus::ObjectPath(kUser1ProfilePath), "eth_entry", _, _));

  EXPECT_CALL(
      *mock_manager_client_,
      ConfigureServiceForProfile(dbus::ObjectPath(kUser1ProfilePath),
                                 IsEqualTo(expected_shill_properties.get()),
                                 _, _));

  SetPolicy(
      ::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_ethernet_eap.onc");
  message_loop_.RunUntilIdle();
}

TEST_F(ManagedNetworkConfigurationHandlerTest, SetPolicyIgnoreUnmodified) {
  InitializeStandardProfiles();
  EXPECT_CALL(*mock_profile_client_, GetProperties(_, _, _));

  EXPECT_CALL(*mock_manager_client_, ConfigureServiceForProfile(_, _, _, _));

  SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc");
  message_loop_.RunUntilIdle();
  EXPECT_EQ(1, policy_observer_.GetPoliciesAppliedCountAndReset());
  VerifyAndClearExpectations();

  SetUpEntry("policy/shill_policy_on_unmanaged_wifi1.json",
             kUser1ProfilePath,
             "some_entry_path");

  EXPECT_CALL(*mock_profile_client_, GetProperties(_, _, _));

  EXPECT_CALL(
      *mock_profile_client_,
      GetEntry(dbus::ObjectPath(kUser1ProfilePath), "some_entry_path", _, _));

  SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc");

  message_loop_.RunUntilIdle();
  EXPECT_EQ(1, policy_observer_.GetPoliciesAppliedCountAndReset());
}

TEST_F(ManagedNetworkConfigurationHandlerTest, PolicyApplicationRunning) {
  InitializeStandardProfiles();
  EXPECT_CALL(*mock_profile_client_, GetProperties(_, _, _)).Times(AnyNumber());
  EXPECT_CALL(*mock_manager_client_, ConfigureServiceForProfile(_, _, _, _))
      .Times(AnyNumber());
  EXPECT_CALL(*mock_profile_client_, GetEntry(_, _, _, _)).Times(AnyNumber());

  EXPECT_FALSE(managed_handler()->IsAnyPolicyApplicationRunning());

  SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc");
  managed_handler()->SetPolicy(
      ::onc::ONC_SOURCE_DEVICE_POLICY,
      std::string(),             // no userhash
      base::ListValue(),         // no device network policy
      base::DictionaryValue());  // no device global config

  EXPECT_TRUE(managed_handler()->IsAnyPolicyApplicationRunning());
  message_loop_.RunUntilIdle();
  EXPECT_FALSE(managed_handler()->IsAnyPolicyApplicationRunning());

  SetUpEntry("policy/shill_policy_on_unmanaged_wifi1.json",
             kUser1ProfilePath,
             "some_entry_path");

  SetPolicy(
      ::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1_update.onc");
  EXPECT_TRUE(managed_handler()->IsAnyPolicyApplicationRunning());
  message_loop_.RunUntilIdle();
  EXPECT_FALSE(managed_handler()->IsAnyPolicyApplicationRunning());
}

TEST_F(ManagedNetworkConfigurationHandlerTest, UpdatePolicyAfterFinished) {
  InitializeStandardProfiles();
  EXPECT_CALL(*mock_profile_client_, GetProperties(_, _, _));
  EXPECT_CALL(*mock_manager_client_, ConfigureServiceForProfile(_, _, _, _));

  SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc");
  message_loop_.RunUntilIdle();
  EXPECT_EQ(1, policy_observer_.GetPoliciesAppliedCountAndReset());
  VerifyAndClearExpectations();

  SetUpEntry("policy/shill_policy_on_unmanaged_wifi1.json",
             kUser1ProfilePath,
             "some_entry_path");

  EXPECT_CALL(*mock_profile_client_, GetProperties(_, _, _));
  EXPECT_CALL(
      *mock_profile_client_,
      GetEntry(dbus::ObjectPath(kUser1ProfilePath), "some_entry_path", _, _));
  EXPECT_CALL(*mock_manager_client_, ConfigureServiceForProfile(_, _, _, _));

  SetPolicy(
      ::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1_update.onc");
  message_loop_.RunUntilIdle();
  EXPECT_EQ(1, policy_observer_.GetPoliciesAppliedCountAndReset());
}

TEST_F(ManagedNetworkConfigurationHandlerTest, UpdatePolicyBeforeFinished) {
  InitializeStandardProfiles();
  EXPECT_CALL(*mock_profile_client_, GetProperties(_, _, _)).Times(2);
  EXPECT_CALL(*mock_manager_client_, ConfigureServiceForProfile(_, _, _, _))
      .Times(2);

  SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc");
  // Usually the first call will cause a profile entry to be created, which we
  // don't fake here.
  SetPolicy(
      ::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1_update.onc");

  message_loop_.RunUntilIdle();
  EXPECT_EQ(1, policy_observer_.GetPoliciesAppliedCountAndReset());
}

TEST_F(ManagedNetworkConfigurationHandlerTest, SetPolicyManageUnmanaged) {
  InitializeStandardProfiles();
  SetUpEntry("policy/shill_unmanaged_wifi1.json",
             kUser1ProfilePath,
             "old_entry_path");

  scoped_ptr<base::DictionaryValue> expected_shill_properties =
      test_utils::ReadTestDictionary(
          "policy/shill_policy_on_unmanaged_wifi1.json");

  EXPECT_CALL(*mock_profile_client_,
              GetProperties(dbus::ObjectPath(kUser1ProfilePath), _, _));

  EXPECT_CALL(
      *mock_profile_client_,
      GetEntry(dbus::ObjectPath(kUser1ProfilePath), "old_entry_path", _, _));

  EXPECT_CALL(
      *mock_profile_client_,
      DeleteEntry(dbus::ObjectPath(kUser1ProfilePath), "old_entry_path", _, _));

  EXPECT_CALL(*mock_manager_client_,
              ConfigureServiceForProfile(
                  dbus::ObjectPath(kUser1ProfilePath),
                  IsEqualTo(expected_shill_properties.get()),
                  _, _));

  SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc");
  message_loop_.RunUntilIdle();
}

// Old ChromeOS versions may not have used the UIData property
TEST_F(ManagedNetworkConfigurationHandlerTest,
       SetPolicyManageUnmanagedWithoutUIData) {
  InitializeStandardProfiles();
  SetUpEntry("policy/shill_unmanaged_wifi1.json",
             kUser1ProfilePath,
             "old_entry_path");

  scoped_ptr<base::DictionaryValue> expected_shill_properties =
      test_utils::ReadTestDictionary(
          "policy/shill_policy_on_unmanaged_wifi1.json");

  EXPECT_CALL(*mock_profile_client_,
              GetProperties(dbus::ObjectPath(kUser1ProfilePath), _, _));

  EXPECT_CALL(
      *mock_profile_client_,
      GetEntry(dbus::ObjectPath(kUser1ProfilePath), "old_entry_path", _, _));

  EXPECT_CALL(
      *mock_profile_client_,
      DeleteEntry(dbus::ObjectPath(kUser1ProfilePath), "old_entry_path", _, _));

  EXPECT_CALL(*mock_manager_client_,
              ConfigureServiceForProfile(
                  dbus::ObjectPath(kUser1ProfilePath),
                  IsEqualTo(expected_shill_properties.get()),
                  _, _));

  SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc");
  message_loop_.RunUntilIdle();
}

TEST_F(ManagedNetworkConfigurationHandlerTest, SetPolicyUpdateManagedNewGUID) {
  InitializeStandardProfiles();
  SetUpEntry("policy/shill_managed_wifi1.json",
             kUser1ProfilePath,
             "old_entry_path");

  scoped_ptr<base::DictionaryValue> expected_shill_properties =
      test_utils::ReadTestDictionary(
          "policy/shill_policy_on_unmanaged_wifi1.json");

  // The passphrase isn't sent again, because it's configured by the user and
  // Shill doesn't send it on GetProperties calls.
  expected_shill_properties->RemoveWithoutPathExpansion(
      shill::kPassphraseProperty, NULL);

  EXPECT_CALL(*mock_profile_client_,
              GetProperties(dbus::ObjectPath(kUser1ProfilePath), _, _));

  EXPECT_CALL(
      *mock_profile_client_,
      GetEntry(dbus::ObjectPath(kUser1ProfilePath), "old_entry_path", _, _));

  EXPECT_CALL(
      *mock_profile_client_,
      DeleteEntry(dbus::ObjectPath(kUser1ProfilePath), "old_entry_path", _, _));

  EXPECT_CALL(*mock_manager_client_,
              ConfigureServiceForProfile(
                  dbus::ObjectPath(kUser1ProfilePath),
                  IsEqualTo(expected_shill_properties.get()),
                  _, _));

  SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc");
  message_loop_.RunUntilIdle();
}

TEST_F(ManagedNetworkConfigurationHandlerTest, SetPolicyUpdateManagedVPN) {
  InitializeStandardProfiles();
  SetUpEntry("policy/shill_managed_vpn.json", kUser1ProfilePath, "entry_path");

  scoped_ptr<base::DictionaryValue> expected_shill_properties =
      test_utils::ReadTestDictionary(
          "policy/shill_policy_on_managed_vpn.json");

  EXPECT_CALL(*mock_profile_client_,
              GetProperties(dbus::ObjectPath(kUser1ProfilePath), _, _));

  EXPECT_CALL(
      *mock_profile_client_,
      GetEntry(dbus::ObjectPath(kUser1ProfilePath), "entry_path", _, _));

  EXPECT_CALL(*mock_manager_client_,
              ConfigureServiceForProfile(
                  dbus::ObjectPath(kUser1ProfilePath),
                  IsEqualTo(expected_shill_properties.get()),
                  _, _));

  SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_vpn.onc");
  message_loop_.RunUntilIdle();
  VerifyAndClearExpectations();
}

TEST_F(ManagedNetworkConfigurationHandlerTest, SetPolicyReapplyToManaged) {
  InitializeStandardProfiles();
  SetUpEntry("policy/shill_policy_on_unmanaged_wifi1.json",
             kUser1ProfilePath,
             "old_entry_path");

  scoped_ptr<base::DictionaryValue> expected_shill_properties =
      test_utils::ReadTestDictionary(
          "policy/shill_policy_on_unmanaged_wifi1.json");

  // The passphrase isn't sent again, because it's configured by the user and
  // Shill doesn't send it on GetProperties calls.
  expected_shill_properties->RemoveWithoutPathExpansion(
      shill::kPassphraseProperty, NULL);

  EXPECT_CALL(*mock_profile_client_,
              GetProperties(dbus::ObjectPath(kUser1ProfilePath), _, _));

  EXPECT_CALL(
      *mock_profile_client_,
      GetEntry(dbus::ObjectPath(kUser1ProfilePath), "old_entry_path", _, _));

  EXPECT_CALL(*mock_manager_client_,
              ConfigureServiceForProfile(
                  dbus::ObjectPath(kUser1ProfilePath),
                  IsEqualTo(expected_shill_properties.get()),
                  _, _));

  SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc");
  message_loop_.RunUntilIdle();
  VerifyAndClearExpectations();

  // If we apply the policy again, without change, then the Shill profile will
  // not be modified.
  EXPECT_CALL(*mock_profile_client_,
              GetProperties(dbus::ObjectPath(kUser1ProfilePath), _, _));

  EXPECT_CALL(
      *mock_profile_client_,
      GetEntry(dbus::ObjectPath(kUser1ProfilePath), "old_entry_path", _, _));

  SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc");
  message_loop_.RunUntilIdle();
}

TEST_F(ManagedNetworkConfigurationHandlerTest, SetPolicyUnmanageManaged) {
  InitializeStandardProfiles();
  SetUpEntry("policy/shill_policy_on_unmanaged_wifi1.json",
             kUser1ProfilePath,
             "old_entry_path");

  EXPECT_CALL(*mock_profile_client_,
              GetProperties(dbus::ObjectPath(kUser1ProfilePath), _, _));

  EXPECT_CALL(*mock_profile_client_,
              GetEntry(dbus::ObjectPath(kUser1ProfilePath),
                       "old_entry_path",
                       _, _));

  EXPECT_CALL(*mock_profile_client_,
              DeleteEntry(dbus::ObjectPath(kUser1ProfilePath),
                          "old_entry_path",
                          _, _));

  SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, "");
  message_loop_.RunUntilIdle();
}

TEST_F(ManagedNetworkConfigurationHandlerTest, SetEmptyPolicyIgnoreUnmanaged) {
  InitializeStandardProfiles();
  SetUpEntry("policy/shill_unmanaged_wifi1.json",
             kUser1ProfilePath,
             "old_entry_path");

  EXPECT_CALL(*mock_profile_client_,
              GetProperties(dbus::ObjectPath(kUser1ProfilePath), _, _));

  EXPECT_CALL(*mock_profile_client_,
              GetEntry(dbus::ObjectPath(kUser1ProfilePath),
                       "old_entry_path",
                       _, _));

  SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, "");
  message_loop_.RunUntilIdle();
  EXPECT_EQ(1, policy_observer_.GetPoliciesAppliedCountAndReset());
}

TEST_F(ManagedNetworkConfigurationHandlerTest, SetPolicyIgnoreUnmanaged) {
  InitializeStandardProfiles();
  SetUpEntry("policy/shill_unmanaged_wifi2.json",
             kUser1ProfilePath,
             "wifi2_entry_path");

  EXPECT_CALL(*mock_profile_client_,
              GetProperties(dbus::ObjectPath(kUser1ProfilePath), _, _));

  EXPECT_CALL(
      *mock_profile_client_,
      GetEntry(dbus::ObjectPath(kUser1ProfilePath), "wifi2_entry_path", _, _));

  scoped_ptr<base::DictionaryValue> expected_shill_properties =
      test_utils::ReadTestDictionary(
          "policy/shill_policy_on_unconfigured_wifi1.json");

  EXPECT_CALL(*mock_manager_client_,
              ConfigureServiceForProfile(
                  dbus::ObjectPath(kUser1ProfilePath),
                  IsEqualTo(expected_shill_properties.get()),
                  _, _));

  SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc");
  message_loop_.RunUntilIdle();
}

TEST_F(ManagedNetworkConfigurationHandlerTest, AutoConnectDisallowed) {
  InitializeStandardProfiles();
  // Setup an unmanaged network.
  SetUpEntry("policy/shill_unmanaged_wifi2.json",
             kUser1ProfilePath,
             "wifi2_entry_path");

  // Apply the user policy with global autoconnect config and expect that
  // autoconnect is disabled in the network's profile entry.
  EXPECT_CALL(*mock_profile_client_,
              GetProperties(dbus::ObjectPath(kUser1ProfilePath), _, _));

  EXPECT_CALL(
      *mock_profile_client_,
      GetEntry(dbus::ObjectPath(kUser1ProfilePath), "wifi2_entry_path", _, _));

  scoped_ptr<base::DictionaryValue> expected_shill_properties =
      test_utils::ReadTestDictionary(
          "policy/shill_disallow_autoconnect_on_unmanaged_wifi2.json");

  EXPECT_CALL(*mock_manager_client_,
              ConfigureServiceForProfile(
                  dbus::ObjectPath(kUser1ProfilePath),
                  MatchesProperties(expected_shill_properties.get()), _, _));

  SetPolicy(::onc::ONC_SOURCE_USER_POLICY,
            kUser1,
            "policy/policy_disallow_autoconnect.onc");
  message_loop_.RunUntilIdle();

  // Verify that GetManagedProperties correctly augments the properties with the
  // global config from the user policy.

  // GetManagedProperties requires the device policy to be set or explicitly
  // unset.
  EXPECT_CALL(*mock_profile_client_,
              GetProperties(dbus::ObjectPath(
                                NetworkProfileHandler::GetSharedProfilePath()),
                            _,
                            _));
  managed_handler()->SetPolicy(
      ::onc::ONC_SOURCE_DEVICE_POLICY,
      std::string(),             // no userhash
      base::ListValue(),         // no device network policy
      base::DictionaryValue());  // no device global config

  services_stub_.SetFakeProperties(*expected_shill_properties);
  EXPECT_CALL(*mock_service_client_,
              GetProperties(dbus::ObjectPath(
                                "wifi2"),_));

  GetManagedProperties(kUser1, "wifi2");
  message_loop_.RunUntilIdle();

  EXPECT_EQ("wifi2", get_properties_service_path_);

  scoped_ptr<base::DictionaryValue> expected_managed_onc =
      test_utils::ReadTestDictionary(
          "policy/managed_onc_disallow_autoconnect_on_unmanaged_wifi2.onc");
  EXPECT_TRUE(onc::test_utils::Equals(expected_managed_onc.get(),
                                      &get_properties_result_));
}

TEST_F(ManagedNetworkConfigurationHandlerTest, LateProfileLoading) {
  SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc");

  message_loop_.RunUntilIdle();
  VerifyAndClearExpectations();

  scoped_ptr<base::DictionaryValue> expected_shill_properties =
      test_utils::ReadTestDictionary(
          "policy/shill_policy_on_unconfigured_wifi1.json");

  EXPECT_CALL(*mock_profile_client_,
              GetProperties(dbus::ObjectPath(kUser1ProfilePath), _, _));

  EXPECT_CALL(*mock_manager_client_,
              ConfigureServiceForProfile(
                  dbus::ObjectPath(kUser1ProfilePath),
                  IsEqualTo(expected_shill_properties.get()),
                  _, _));

  InitializeStandardProfiles();
  message_loop_.RunUntilIdle();
}

class ManagedNetworkConfigurationHandlerShutdownTest
    : public ManagedNetworkConfigurationHandlerTest {
 public:
  void SetUp() override {
    ManagedNetworkConfigurationHandlerTest::SetUp();
    ON_CALL(*mock_profile_client_, GetProperties(_, _, _)).WillByDefault(
        Invoke(&ManagedNetworkConfigurationHandlerShutdownTest::GetProperties));
  }

  static void GetProperties(
      const dbus::ObjectPath& profile_path,
      const ShillClientHelper::DictionaryValueCallbackWithoutStatus& callback,
      const ShillClientHelper::ErrorCallback& error_callback) {
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE, base::Bind(ManagedNetworkConfigurationHandlerShutdownTest::
                                  CallbackWithEmptyDictionary,
                              callback));
  }

  static void CallbackWithEmptyDictionary(
      const ShillClientHelper::DictionaryValueCallbackWithoutStatus& callback) {
    callback.Run(base::DictionaryValue());
  }
};

TEST_F(ManagedNetworkConfigurationHandlerShutdownTest,
       DuringPolicyApplication) {
  InitializeStandardProfiles();

  EXPECT_CALL(*mock_profile_client_,
              GetProperties(dbus::ObjectPath(kUser1ProfilePath), _, _));

  SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc");
  managed_network_configuration_handler_->RemoveObserver(&policy_observer_);
  managed_network_configuration_handler_.reset();
  message_loop_.RunUntilIdle();
}

}  // namespace chromeos
