// Copyright 2021 The Chromium OS 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 <string>
#include <vector>

#include <brillo/dbus/mock_dbus_method_response.h>
#include <brillo/errors/error_codes.h>
#include <brillo/message_loops/fake_message_loop.h>
#include <dbus/shill/dbus-constants.h>
#include <gtest/gtest.h>

#include "minios/minios.h"
#include "minios/mock_network_manager.h"
#include "minios/mock_shill_proxy.h"
#include "minios/network_manager.h"
#include "minios/shill_utils.h"

using ::testing::_;
using ::testing::ElementsAre;
using ::testing::IsNull;
using ::testing::NotNull;
using ::testing::StrictMock;

namespace minios {

class NetworkManagerTest : public ::testing::Test {
 public:
  void SetUp() override {
    loop_.SetAsCurrent();

    auto mock_shill_proxy_ptr = std::make_unique<MockShillProxy>();
    mock_shill_proxy_ptr_ = mock_shill_proxy_ptr.get();
    network_manager_ =
        std::make_unique<NetworkManager>(std::move(mock_shill_proxy_ptr));
    network_manager_->AddObserver(&mock_network_manager_observer_);
  }

 protected:
  MockShillProxy* mock_shill_proxy_ptr_;
  StrictMock<MockNetworkManagerObserver> mock_network_manager_observer_;
  std::unique_ptr<NetworkManager> network_manager_;

  base::SimpleTestClock clock_;
  brillo::FakeMessageLoop loop_{&clock_};
};

TEST_F(NetworkManagerTest, Connect) {
  EXPECT_CALL(*mock_shill_proxy_ptr_,
              ManagerRequestScan(WifiTechnologyType::WIFI, _, _));
  network_manager_->Connect("ssid-foo", "passphrase");

  // It's okay to request the same SSID for connection, a no-op.
  network_manager_->Connect("ssid-foo", "passphrase");

  // Passphrase changes for same SSID will be ignored, a no-op.
  network_manager_->Connect("ssid-foo", "passphrase-other");

  // Connecting to a different SSID should be successful.
  EXPECT_CALL(*mock_shill_proxy_ptr_,
              ManagerRequestScan(WifiTechnologyType::WIFI, _, _));
  network_manager_->Connect("ssid-bar", "passphrase");
}

TEST_F(NetworkManagerTest, Connect_RequestScanSuccess_NoPassphrase) {
  network_manager_->connect_map_["ssid"] = NetworkManager::ConnectField();
  auto iter_no_passphrase = network_manager_->connect_map_.begin();
  const brillo::VariantDictionary properties = {
      {shill::kModeProperty, brillo::Any(ToString(WifiStationType::MANAGED))},
      {shill::kNameProperty, brillo::Any(iter_no_passphrase->first)},
      {shill::kSecurityClassProperty,
       brillo::Any(ToString(WifiSecurityType::NONE))},
      {shill::kTypeProperty, brillo::Any(ToString(WifiTechnologyType::WIFI))},
  };
  EXPECT_CALL(*mock_shill_proxy_ptr_,
              ManagerFindMatchingService(properties, _, _));
  network_manager_->RequestScanSuccess(iter_no_passphrase);
}

TEST_F(NetworkManagerTest, Connect_RequestScanSuccess_Passphrase) {
  network_manager_->connect_map_["ssid"] =
      NetworkManager::ConnectField{.passphrase = "passphrase"};
  auto iter_passphrase = network_manager_->connect_map_.begin();
  const brillo::VariantDictionary properties = {
      {shill::kModeProperty, brillo::Any(ToString(WifiStationType::MANAGED))},
      {shill::kNameProperty, brillo::Any(iter_passphrase->first)},
      {shill::kSecurityClassProperty,
       brillo::Any(ToString(WifiSecurityType::PSK))},
      {shill::kTypeProperty, brillo::Any(ToString(WifiTechnologyType::WIFI))},
  };
  EXPECT_CALL(*mock_shill_proxy_ptr_,
              ManagerFindMatchingService(properties, _, _));
  network_manager_->RequestScanSuccess(iter_passphrase);
}

TEST_F(NetworkManagerTest, Connect_GetServiceSuccess_GoodStrength) {
  network_manager_->connect_map_["ssid"] =
      NetworkManager::ConnectField{.passphrase = "passphrase"};
  auto iter = network_manager_->connect_map_.begin();
  const brillo::VariantDictionary input_properties = {
      {shill::kSignalStrengthProperty, brillo::Any(uint8_t(1))},
  };
  const brillo::VariantDictionary expected_properties = {
      {shill::kAutoConnectProperty, brillo::Any(true)},
      {shill::kPassphraseProperty, brillo::Any(iter->second.passphrase)},
  };
  EXPECT_CALL(*mock_shill_proxy_ptr_,
              ServiceSetProperties(_, expected_properties, _, _));
  network_manager_->GetServiceSuccess(iter, input_properties);
}

TEST_F(NetworkManagerTest, Connect_GetServiceSuccess_BadStrength) {
  network_manager_->connect_map_["ssid"] =
      NetworkManager::ConnectField{.passphrase = "passphrase"};
  auto iter = network_manager_->connect_map_.begin();
  const brillo::VariantDictionary input_properties = {
      {shill::kSignalStrengthProperty, brillo::Any(uint8_t(0))},
  };
  EXPECT_CALL(mock_network_manager_observer_, OnConnect("ssid", NotNull()));
  network_manager_->GetServiceSuccess(iter, input_properties);
}

TEST_F(NetworkManagerTest, Connect_GetServiceSuccess_MissingStrength) {
  network_manager_->connect_map_["ssid"] =
      NetworkManager::ConnectField{.passphrase = "passphrase"};
  auto iter = network_manager_->connect_map_.begin();
  EXPECT_CALL(mock_network_manager_observer_, OnConnect("ssid", NotNull()));
  network_manager_->GetServiceSuccess(iter, {});
}

TEST_F(NetworkManagerTest,
       Connect_ConnectToNetworkError_InProgressRetriesConnection) {
  auto error_ptr =
      brillo::Error::Create(FROM_HERE, brillo::errors::dbus::kDomain,
                            shill::kErrorResultInProgress, "");
  network_manager_->connect_map_["ssid"] = NetworkManager::ConnectField{
      .service_path = dbus::ObjectPath("some-service-path")};
  auto iter = network_manager_->connect_map_.begin();
  network_manager_->ConnectToNetworkError(iter, error_ptr.get());

  EXPECT_CALL(*mock_shill_proxy_ptr_,
              ServiceConnect(iter->second.service_path, _, _));
  clock_.Advance(base::TimeDelta::FromSeconds(1));
  loop_.RunOnce(false);
}

TEST_F(NetworkManagerTest, Connect_ConnectToNetworkError_AlreadyConnected) {
  auto error_ptr =
      brillo::Error::Create(FROM_HERE, brillo::errors::dbus::kDomain,
                            shill::kErrorResultAlreadyConnected, "");
  network_manager_->connect_map_["ssid"] = NetworkManager::ConnectField{
      .service_path = dbus::ObjectPath("some-service-path")};
  auto iter = network_manager_->connect_map_.begin();
  EXPECT_CALL(mock_network_manager_observer_, OnConnect("ssid", IsNull()));
  network_manager_->ConnectToNetworkError(iter, error_ptr.get());
}

TEST_F(NetworkManagerTest,
       Connect_ConnectToNetworkError_OtherErrorResponsesFromShill) {
  auto error_ptr = brillo::Error::Create(
      FROM_HERE, brillo::errors::dbus::kDomain, DBUS_ERROR_FAILED, "");
  network_manager_->connect_map_["ssid"] = NetworkManager::ConnectField();
  auto iter = network_manager_->connect_map_.begin();
  EXPECT_CALL(mock_network_manager_observer_, OnConnect("ssid", NotNull()));
  network_manager_->ConnectToNetworkError(iter, error_ptr.get());
}

TEST_F(NetworkManagerTest,
       Connect_GetServiceCheckConnectionSuccess_FailureState) {
  const brillo::VariantDictionary input_properties = {
      {shill::kStateProperty, brillo::Any(std::string(shill::kStateFailure))},
  };
  network_manager_->connect_map_["ssid"] = NetworkManager::ConnectField{
      .service_path = dbus::ObjectPath("some-service-path")};
  auto iter = network_manager_->connect_map_.begin();
  EXPECT_CALL(mock_network_manager_observer_, OnConnect("ssid", NotNull()));
  network_manager_->GetServiceCheckConnectionSuccess(iter, input_properties);
}

TEST_F(NetworkManagerTest,
       Connect_GetServiceCheckConnectionSuccess_OnlineState) {
  const brillo::VariantDictionary input_properties = {
      {shill::kStateProperty, brillo::Any(std::string(shill::kStateOnline))},
  };
  network_manager_->connect_map_["ssid"] = NetworkManager::ConnectField{
      .service_path = dbus::ObjectPath("some-service-path")};
  auto iter = network_manager_->connect_map_.begin();
  EXPECT_CALL(mock_network_manager_observer_, OnConnect("ssid", IsNull()));
  network_manager_->GetServiceCheckConnectionSuccess(iter, input_properties);
}

TEST_F(NetworkManagerTest,
       Connect_GetServiceCheckConnectionSuccess_MissingState) {
  network_manager_->connect_map_["ssid"] = NetworkManager::ConnectField{
      .service_path = dbus::ObjectPath("some-service-path")};
  auto iter = network_manager_->connect_map_.begin();
  EXPECT_CALL(mock_network_manager_observer_, OnConnect("ssid", NotNull()));
  network_manager_->GetServiceCheckConnectionSuccess(iter, {});
}

TEST_F(NetworkManagerTest,
       Connect_GetServiceCheckConnectionSuccess_IntermediateState) {
  const brillo::VariantDictionary input_properties = {
      {shill::kStateProperty, brillo::Any(std::string(shill::kStateReady))},
  };
  network_manager_->connect_map_["ssid"] = NetworkManager::ConnectField{
      .service_path = dbus::ObjectPath("some-service-path")};
  auto iter = network_manager_->connect_map_.begin();
  network_manager_->GetServiceCheckConnectionSuccess(iter, input_properties);

  EXPECT_CALL(*mock_shill_proxy_ptr_,
              ServiceGetProperties(iter->second.service_path, _, _));
  clock_.Advance(base::TimeDelta::FromSeconds(
      NetworkManager::kCheckConnectionRetryMsDelay * 2));
  loop_.RunOnce(false);
}

TEST_F(NetworkManagerTest, GetNetworks) {
  EXPECT_TRUE(network_manager_->get_networks_list_.empty());
  EXPECT_CALL(*mock_shill_proxy_ptr_,
              ManagerRequestScan(WifiTechnologyType::WIFI, _, _));
  network_manager_->GetNetworks();
  EXPECT_EQ(network_manager_->get_networks_list_.size(), 1);

  // Subsequent `GetNetworks()` should be bundled.
  network_manager_->GetNetworks();
  EXPECT_EQ(network_manager_->get_networks_list_.size(), 1);
}

TEST_F(NetworkManagerTest, GetGlobalPropertiesSuccess_MultipleServices) {
  auto iter = network_manager_->get_networks_list_.insert(
      network_manager_->get_networks_list_.begin(),
      NetworkManager::GetNetworksField());

  dbus::ObjectPath object_path("some-service-path");
  dbus::ObjectPath other_object_path("other-some-service-path");
  std::vector<dbus::ObjectPath> object_paths = {other_object_path, object_path};
  const brillo::VariantDictionary input_properties = {
      {shill::kServicesProperty, brillo::Any(object_paths)},
  };

  EXPECT_CALL(*mock_shill_proxy_ptr_, ServiceGetProperties(object_path, _, _));
  network_manager_->GetGlobalPropertiesSuccess(iter, input_properties);
  // Should still hold `other_object_path` to iterate over and get the Service
  // name from as `object_path` was binded into `ServiceGetProperties()`.
  EXPECT_EQ(iter->service_paths.size(), 1);
}

TEST_F(NetworkManagerTest, GetGlobalPropertiesSuccess_EmptyServices) {
  auto iter = network_manager_->get_networks_list_.insert(
      network_manager_->get_networks_list_.begin(),
      NetworkManager::GetNetworksField());
  EXPECT_CALL(mock_network_manager_observer_,
              OnGetNetworks(std::vector<std::string>(), IsNull()));
  network_manager_->GetGlobalPropertiesSuccess(iter, {});
}

TEST_F(NetworkManagerTest, IterateOverServicePropertiesSuccess_EmptyServices) {
  // Explicitly empty the `service_paths`.
  auto iter = network_manager_->get_networks_list_.insert(
      network_manager_->get_networks_list_.begin(),
      NetworkManager::GetNetworksField{.service_paths = {}});
  EXPECT_CALL(mock_network_manager_observer_,
              OnGetNetworks(std::vector<std::string>(), IsNull()));
  network_manager_->IterateOverServicePropertiesSuccess(iter, {});
}

TEST_F(NetworkManagerTest, IterateOverServicePropertiesSuccess_OneService) {
  // Explicitly empty the `service_paths`.
  auto iter = network_manager_->get_networks_list_.insert(
      network_manager_->get_networks_list_.begin(),
      NetworkManager::GetNetworksField{.service_paths = {}});

  const std::string kSsid = "some-ssid-name";
  const brillo::VariantDictionary input_properties = {
      {shill::kNameProperty, brillo::Any(kSsid)},
  };
  EXPECT_CALL(mock_network_manager_observer_,
              OnGetNetworks(std::vector<std::string>{kSsid}, IsNull()));
  network_manager_->IterateOverServicePropertiesSuccess(iter, input_properties);
}

TEST_F(NetworkManagerTest,
       IterateOverServicePropertiesSuccess_MoreServicesToIterate) {
  dbus::ObjectPath object_path("some-service-path");
  auto iter = network_manager_->get_networks_list_.insert(
      network_manager_->get_networks_list_.begin(),
      NetworkManager::GetNetworksField{.service_paths = {object_path}});

  const std::string kSsid = "some-ssid-name";
  const brillo::VariantDictionary input_properties = {
      {shill::kNameProperty, brillo::Any(kSsid)},
  };

  EXPECT_TRUE(iter->networks.empty());
  EXPECT_CALL(*mock_shill_proxy_ptr_, ServiceGetProperties(object_path, _, _));
  network_manager_->IterateOverServicePropertiesSuccess(iter, input_properties);
  EXPECT_THAT(iter->networks, ElementsAre(kSsid));
  EXPECT_TRUE(iter->service_paths.empty());
}

TEST_F(NetworkManagerTest,
       IterateOverServicePropertiesError_MoreServicesToIterate) {
  dbus::ObjectPath object_path("some-service-path");
  auto iter = network_manager_->get_networks_list_.insert(
      network_manager_->get_networks_list_.begin(),
      NetworkManager::GetNetworksField{.service_paths = {object_path}});

  EXPECT_CALL(*mock_shill_proxy_ptr_, ServiceGetProperties(object_path, _, _));
  network_manager_->IterateOverServicePropertiesError(iter, nullptr);
  EXPECT_TRUE(iter->service_paths.empty());
}

TEST_F(NetworkManagerTest,
       IterateOverServicePropertiesError_AlwaysReturnOnEnd) {
  const std::string kSsid = "some-ssid-name";
  // Explicitly empty the `service_paths`.
  // Put `kSsid` into the already parsed `networks` list.
  auto iter = network_manager_->get_networks_list_.insert(
      network_manager_->get_networks_list_.begin(),
      NetworkManager::GetNetworksField{.service_paths = {},
                                       .networks = {kSsid}});

  EXPECT_CALL(mock_network_manager_observer_,
              OnGetNetworks(std::vector<std::string>{kSsid}, IsNull()));
  network_manager_->IterateOverServicePropertiesError(iter, nullptr);
}

}  // namespace minios
