// 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_NoPassphrase) {
  // Empty password does not send `kPassphraseProperty`.
  network_manager_->connect_map_["ssid"] =
      NetworkManager::ConnectField{.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)},
  };
  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(testing::_, 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(testing::_, 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(testing::_, 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[0].ssid, 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 = {{.ssid = kSsid}}});

  EXPECT_CALL(mock_network_manager_observer_,
              OnGetNetworks(testing::_, IsNull()));
  network_manager_->IterateOverServicePropertiesError(iter, nullptr);
}

}  // namespace minios
