// Copyright 2018 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 "shill/static_ip_parameters.h"

#include <base/check.h>
#include <base/strings/string_number_conversions.h>
#include <chromeos/dbus/service_constants.h>
#include <gtest/gtest.h>

#include "shill/fake_store.h"
#include "shill/ipconfig.h"
#include "shill/mock_control.h"
#include "shill/mock_ipconfig.h"
#include "shill/property_store.h"

using std::string;
using std::vector;
using testing::_;
using testing::DoAll;
using testing::Return;
using testing::SetArgPointee;
using testing::StrictMock;
using testing::Test;

namespace shill {

namespace {

const char kAddress[] = "10.0.0.1";
const char kGateway[] = "10.0.0.254";
const int32_t kMtu = 512;

const char kNameServer0[] = "10.0.1.253";
const char kNameServer1[] = "10.0.1.252";
const char kNameServers[] = "10.0.1.253,10.0.1.252";

const char kSearchDomains[] = "example.com,chromium.org";
const char kSearchDomain0[] = "example.com";
const char kSearchDomain1[] = "chromium.org";

const char kPeerAddress[] = "10.0.0.2";
const int32_t kPrefixLen = 24;

const char kExcludedRoutes[] = "192.168.1.0/24,192.168.2.0/24";
const char kExcludedRoute0[] = "192.168.1.0/24";
const char kExcludedRoute1[] = "192.168.2.0/24";

const char kIncludedRoutes[] = "0.0.0.0/0";
const IPConfig::Route kIncludedRoute0("0.0.0.0", 0, "10.0.0.254");

}  // namespace

class StaticIPParametersTest : public Test {
 public:
  StaticIPParametersTest() = default;

  void ExpectEmptyIPConfig() {
    EXPECT_TRUE(ipconfig_props_.address.empty());
    EXPECT_TRUE(ipconfig_props_.gateway.empty());
    EXPECT_EQ(IPConfig::kUndefinedMTU, ipconfig_props_.mtu);
    EXPECT_TRUE(ipconfig_props_.dns_servers.empty());
    EXPECT_TRUE(ipconfig_props_.domain_search.empty());
    EXPECT_TRUE(ipconfig_props_.peer_address.empty());
    EXPECT_FALSE(ipconfig_props_.subnet_prefix);
    EXPECT_TRUE(ipconfig_props_.exclusion_list.empty());
    EXPECT_TRUE(ipconfig_props_.routes.empty());
    EXPECT_TRUE(ipconfig_props_.default_route);
  }
  // Modify an IP address string in some predictable way.  There's no need
  // for the output string to be valid from a networking perspective.
  string VersionedAddress(const string& address, int version) {
    string returned_address = address;
    CHECK(returned_address.length());
    returned_address[returned_address.length() - 1] += version;
    return returned_address;
  }
  void ExpectPopulatedIPConfigWithVersion(int version) {
    EXPECT_EQ(VersionedAddress(kAddress, version), ipconfig_props_.address);
    EXPECT_EQ(VersionedAddress(kGateway, version), ipconfig_props_.gateway);
    EXPECT_EQ(kMtu + version, ipconfig_props_.mtu);

    EXPECT_EQ(2, ipconfig_props_.dns_servers.size());
    EXPECT_EQ(VersionedAddress(kNameServer0, version),
              ipconfig_props_.dns_servers[0]);
    EXPECT_EQ(VersionedAddress(kNameServer1, version),
              ipconfig_props_.dns_servers[1]);

    // VersionedAddress() increments the final character of each domain
    // name.
    EXPECT_EQ(2, ipconfig_props_.domain_search.size());
    EXPECT_EQ(VersionedAddress(kSearchDomain0, version),
              ipconfig_props_.domain_search[0]);
    EXPECT_EQ(VersionedAddress(kSearchDomain1, version),
              ipconfig_props_.domain_search[1]);

    EXPECT_EQ(VersionedAddress(kPeerAddress, version),
              ipconfig_props_.peer_address);
    EXPECT_EQ(kPrefixLen + version, ipconfig_props_.subnet_prefix);

    EXPECT_EQ(2, ipconfig_props_.exclusion_list.size());
    EXPECT_EQ(VersionedAddress(kExcludedRoute0, version),
              ipconfig_props_.exclusion_list[0]);
    EXPECT_EQ(VersionedAddress(kExcludedRoute1, version),
              ipconfig_props_.exclusion_list[1]);

    // VersionedAddress() increments the final digit of the prefix on
    // the IncludedRoutes property, and the final digit of the IP address
    // on the Gateway property.
    EXPECT_EQ(1, ipconfig_props_.routes.size());
    EXPECT_EQ(kIncludedRoute0.host, ipconfig_props_.routes[0].host);
    EXPECT_EQ(kIncludedRoute0.prefix + version,
              ipconfig_props_.routes[0].prefix);
    EXPECT_EQ(VersionedAddress(kIncludedRoute0.gateway, version),
              ipconfig_props_.routes[0].gateway);
    EXPECT_FALSE(ipconfig_props_.default_route);
  }
  void ExpectPopulatedIPConfig() { ExpectPopulatedIPConfigWithVersion(0); }
  void ExpectPropertiesWithVersion(PropertyStore* store,
                                   const string& property_prefix,
                                   int version) {
    KeyValueStore args;
    Error unused_error;
    EXPECT_TRUE(store->GetKeyValueStoreProperty(property_prefix + "Config",
                                                &args, &unused_error));
    EXPECT_EQ(VersionedAddress(kAddress, version),
              args.Get<string>(kAddressProperty));
    EXPECT_EQ(VersionedAddress(kGateway, version),
              args.Get<string>(kGatewayProperty));
    EXPECT_EQ(kMtu + version, args.Get<int32_t>(kMtuProperty));
    vector<string> kTestNameServers({VersionedAddress(kNameServer0, version),
                                     VersionedAddress(kNameServer1, version)});
    EXPECT_EQ(kTestNameServers, args.Get<Strings>(kNameServersProperty));
    vector<string> kTestSearchDomains(
        {VersionedAddress(kSearchDomain0, version),
         VersionedAddress(kSearchDomain1, version)});
    EXPECT_EQ(kTestSearchDomains, args.Get<Strings>(kSearchDomainsProperty));
    EXPECT_EQ(VersionedAddress(kPeerAddress, version),
              args.Get<string>(kPeerAddressProperty));
    EXPECT_EQ(kPrefixLen + version, args.Get<int32_t>(kPrefixlenProperty));
    vector<string> kTestExcludedRoutes(
        {VersionedAddress(kExcludedRoute0, version),
         VersionedAddress(kExcludedRoute1, version)});
    EXPECT_EQ(kTestExcludedRoutes, args.Get<Strings>(kExcludedRoutesProperty));
    vector<string> kTestIncludedRoutes(
        {VersionedAddress(kIncludedRoutes, version)});
    EXPECT_EQ(kTestIncludedRoutes, args.Get<Strings>(kIncludedRoutesProperty));
  }
  void ExpectProperties(PropertyStore* store, const string& property_prefix) {
    ExpectPropertiesWithVersion(store, property_prefix, 0);
  }
  void PopulateIPConfig() {
    ipconfig_props_.address = kAddress;
    ipconfig_props_.gateway = kGateway;
    ipconfig_props_.mtu = kMtu;
    ipconfig_props_.dns_servers = {kNameServer0, kNameServer1};
    ipconfig_props_.domain_search = {kSearchDomain0, kSearchDomain1};
    ipconfig_props_.peer_address = kPeerAddress;
    ipconfig_props_.subnet_prefix = kPrefixLen;
    ipconfig_props_.exclusion_list = {kExcludedRoute0, kExcludedRoute1};
    ipconfig_props_.routes = {kIncludedRoute0};
    ipconfig_props_.default_route = false;
  }
  void SetStaticProperties(PropertyStore* store) {
    SetStaticPropertiesWithVersion(store, 0);
  }
  void SetStaticPropertiesWithVersion(PropertyStore* store, int version) {
    KeyValueStore args;
    args.Set<string>(kAddressProperty, VersionedAddress(kAddress, version));
    args.Set<string>(kGatewayProperty, VersionedAddress(kGateway, version));
    args.Set<int32_t>(kMtuProperty, kMtu + version);
    args.Set<Strings>(kNameServersProperty,
                      {VersionedAddress(kNameServer0, version),
                       VersionedAddress(kNameServer1, version)});
    args.Set<Strings>(kSearchDomainsProperty,
                      {VersionedAddress(kSearchDomain0, version),
                       VersionedAddress(kSearchDomain1, version)});
    args.Set<string>(kPeerAddressProperty,
                     VersionedAddress(kPeerAddress, version));
    args.Set<int32_t>(kPrefixlenProperty, kPrefixLen + version);
    args.Set<Strings>(kExcludedRoutesProperty,
                      {VersionedAddress(kExcludedRoute0, version),
                       VersionedAddress(kExcludedRoute1, version)});
    args.Set<Strings>(kIncludedRoutesProperty,
                      {VersionedAddress(kIncludedRoutes, version)});

    Error error;
    store->SetKeyValueStoreProperty(kStaticIPConfigProperty, args, &error);
  }
  void SetStaticPropertiesWithoutRoute(PropertyStore* store) {
    KeyValueStore args;
    args.Set<string>(kAddressProperty, kAddress);
    args.Set<string>(kGatewayProperty, kGateway);
    args.Set<int32_t>(kMtuProperty, kMtu);
    Error error;
    store->SetKeyValueStoreProperty(kStaticIPConfigProperty, args, &error);
  }
  KeyValueStore* static_args() { return &static_params_.args_; }
  KeyValueStore* saved_args() { return &static_params_.saved_args_; }

 protected:
  StaticIPParameters static_params_;
  IPConfig::Properties ipconfig_props_;
};

TEST_F(StaticIPParametersTest, InitState) {
  ExpectEmptyIPConfig();

  // Applying an empty set of parameters on an empty set of properties should
  // be a no-op.
  static_params_.ApplyTo(&ipconfig_props_);
  ExpectEmptyIPConfig();
}

TEST_F(StaticIPParametersTest, ApplyEmptyParameters) {
  PopulateIPConfig();
  static_params_.ApplyTo(&ipconfig_props_);
  ExpectPopulatedIPConfig();
}

TEST_F(StaticIPParametersTest, DefaultRoute) {
  IPConfig::Properties props;
  PropertyStore store;
  static_params_.PlumbPropertyStore(&store);
  SetStaticPropertiesWithoutRoute(&store);
  static_params_.ApplyTo(&props);
  EXPECT_TRUE(props.default_route);
  SetStaticProperties(&store);
  static_params_.ApplyTo(&props);
  EXPECT_FALSE(props.default_route);
}

TEST_F(StaticIPParametersTest, ControlInterface) {
  PropertyStore store;
  int version = 0;
  static_params_.PlumbPropertyStore(&store);
  SetStaticProperties(&store);
  static_params_.ApplyTo(&ipconfig_props_);
  ExpectPopulatedIPConfig();

  EXPECT_TRUE(static_params_.ContainsAddress());
  EXPECT_TRUE(store.Contains("StaticIPConfig"));
  static_args()->Remove("Address");
  EXPECT_FALSE(static_params_.ContainsAddress());
  static_args()->Remove("Mtu");
  IPConfig::Properties props;
  const string kTestAddress("test_address");
  props.address = kTestAddress;
  const int32_t kTestMtu = 256;
  props.mtu = kTestMtu;
  static_params_.ApplyTo(&props);
  EXPECT_EQ(kTestAddress, props.address);
  EXPECT_EQ(kTestMtu, props.mtu);

  EXPECT_FALSE(static_args()->Contains<string>("Address"));
  EXPECT_EQ(kGateway, static_args()->Get<string>("Gateway"));
  EXPECT_FALSE(static_args()->Contains<int32_t>("Mtu"));
  vector<string> kTestNameServers({VersionedAddress(kNameServer0, version),
                                   VersionedAddress(kNameServer1, version)});
  EXPECT_EQ(kTestNameServers, static_args()->Get<Strings>("NameServers"));
  vector<string> kTestSearchDomains(
      {VersionedAddress(kSearchDomain0, version),
       VersionedAddress(kSearchDomain1, version)});
  EXPECT_EQ(kTestSearchDomains, static_args()->Get<Strings>("SearchDomains"));
  EXPECT_EQ(VersionedAddress(kPeerAddress, version),
            static_args()->Get<string>("PeerAddress"));
  EXPECT_EQ(kPrefixLen + version, static_args()->Get<int32_t>("Prefixlen"));
  vector<string> kTestExcludedRoutes(
      {VersionedAddress(kExcludedRoute0, version),
       VersionedAddress(kExcludedRoute1, version)});
  EXPECT_EQ(kTestExcludedRoutes, static_args()->Get<Strings>("ExcludedRoutes"));
  vector<string> kTestIncludedRoutes(
      {VersionedAddress(kIncludedRoutes, version)});
  EXPECT_EQ(kTestIncludedRoutes, static_args()->Get<Strings>("IncludedRoutes"));
}

TEST_F(StaticIPParametersTest, Profile) {
  FakeStore store;
  const string kID = "storage_id";
  store.SetString(kID, "StaticIP.Address", kAddress);
  store.SetString(kID, "StaticIP.Gateway", kGateway);
  store.SetInt(kID, "StaticIP.Mtu", kMtu);
  store.SetString(kID, "StaticIP.NameServers", kNameServers);
  store.SetString(kID, "StaticIP.SearchDomains", kSearchDomains);
  store.SetString(kID, "StaticIP.PeerAddress", kPeerAddress);
  store.SetInt(kID, "StaticIP.Prefixlen", kPrefixLen);
  store.SetString(kID, "StaticIP.ExcludedRoutes", kExcludedRoutes);
  store.SetString(kID, "StaticIP.IncludedRoutes", kIncludedRoutes);

  static_params_.Load(&store, kID);
  static_params_.ApplyTo(&ipconfig_props_);
  ExpectPopulatedIPConfig();

  static_params_.Save(&store, kID);

  std::string address;
  EXPECT_TRUE(store.GetString(kID, "StaticIP.Address", &address));
  EXPECT_EQ(address, kAddress);
  std::string gateway;
  EXPECT_TRUE(store.GetString(kID, "StaticIP.Gateway", &gateway));
  EXPECT_EQ(gateway, kGateway);
  int mtu;
  EXPECT_TRUE(store.GetInt(kID, "StaticIP.Mtu", &mtu));
  EXPECT_EQ(mtu, kMtu);
  std::string nameservers;
  EXPECT_TRUE(store.GetString(kID, "StaticIP.NameServers", &nameservers));
  EXPECT_EQ(nameservers, kNameServers);
  std::string searchdomains;
  EXPECT_TRUE(store.GetString(kID, "StaticIP.SearchDomains", &searchdomains));
  EXPECT_EQ(searchdomains, kSearchDomains);
  std::string peeraddress;
  EXPECT_TRUE(store.GetString(kID, "StaticIP.PeerAddress", &peeraddress));
  EXPECT_EQ(peeraddress, kPeerAddress);
  int prefixlen;
  EXPECT_TRUE(store.GetInt(kID, "StaticIP.Prefixlen", &prefixlen));
  EXPECT_EQ(prefixlen, kPrefixLen);
  std::string excludedroutes;
  EXPECT_TRUE(store.GetString(kID, "StaticIP.ExcludedRoutes", &excludedroutes));
  EXPECT_EQ(excludedroutes, kExcludedRoutes);
  std::string includedroutes;
  EXPECT_TRUE(store.GetString(kID, "StaticIP.IncludedRoutes", &includedroutes));
  EXPECT_EQ(includedroutes, kIncludedRoutes);
}

TEST_F(StaticIPParametersTest, SavedParameters) {
  // Calling RestoreTo() when no parameters are set should not crash or
  // add any entries.
  static_params_.RestoreTo(&ipconfig_props_);
  ExpectEmptyIPConfig();

  PopulateIPConfig();
  PropertyStore static_params_props;
  static_params_.PlumbPropertyStore(&static_params_props);
  SetStaticPropertiesWithVersion(&static_params_props, 1);
  static_params_.ApplyTo(&ipconfig_props_);

  // The version 0 properties in |ipconfig_props_| are now in SavedIP.*
  // properties, while the version 1 StaticIP parameters are now in
  // |ipconfig_props_|.
  ExpectPropertiesWithVersion(&static_params_props, "SavedIP", 0);
  ExpectPopulatedIPConfigWithVersion(1);

  // Clear all "StaticIP" parameters.
  static_args()->Clear();

  // Another ApplyTo() call rotates the version 1 properties in
  // |ipconfig_props_| over to SavedIP.*.  Since there are no StaticIP
  // parameters, |ipconfig_props_| should remain populated with version 1
  // parameters.
  static_params_.ApplyTo(&ipconfig_props_);
  ExpectPropertiesWithVersion(&static_params_props, "SavedIP", 1);
  ExpectPopulatedIPConfigWithVersion(1);

  // Reset |ipconfig_props_| to version 0.
  PopulateIPConfig();

  // A RestoreTo() call moves the version 1 "SavedIP" parameters into
  // |ipconfig_props_|.
  SetStaticPropertiesWithVersion(&static_params_props, 2);
  static_params_.RestoreTo(&ipconfig_props_);
  ExpectPopulatedIPConfigWithVersion(1);

  // All "SavedIP" parameters should be cleared.
  EXPECT_TRUE(saved_args()->IsEmpty());

  // Static IP parameters should be unchanged.
  ExpectPropertiesWithVersion(&static_params_props, "StaticIP", 2);
}

TEST_F(StaticIPParametersTest, IPConfigRefreshed) {
  MockControl control;
  scoped_refptr<MockIPConfig> ipconfig = new MockIPConfig(&control, "int0");
  static_params_.SetIPConfig(ipconfig->weak_ptr_factory_.GetWeakPtr());
  EXPECT_CALL(*ipconfig, Refresh());
  PropertyStore store;
  static_params_.PlumbPropertyStore(&store);
  SetStaticProperties(&store);
}

}  // namespace shill
