// Copyright (c) 2012 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/strings/string_number_conversions.h>
#include <chromeos/dbus/service_constants.h>
#include <gtest/gtest.h>

#include "shill/ipconfig.h"
#include "shill/mock_store.h"
#include "shill/property_store.h"

using base::IntToString;
using std::string;
using std::vector;
using testing::_;
using testing::DoAll;
using testing::Return;
using testing::SetArgumentPointee;
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 kPeerAddress[] = "10.0.0.2";
const int32_t kPrefixLen = 24;

}  // namespace

class StaticIpParametersTest : public Test {
 public:
  StaticIpParametersTest() {}

  void ExpectEmptyIPConfig() {
    EXPECT_TRUE(ipconfig_props_.address.empty());
    EXPECT_TRUE(ipconfig_props_.gateway.empty());
    EXPECT_FALSE(ipconfig_props_.mtu);
    EXPECT_TRUE(ipconfig_props_.dns_servers.empty());
    EXPECT_TRUE(ipconfig_props_.peer_address.empty());
    EXPECT_FALSE(ipconfig_props_.subnet_prefix);
  }
  // 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]);
    EXPECT_EQ(VersionedAddress(kPeerAddress, version),
              ipconfig_props_.peer_address);
    EXPECT_EQ(kPrefixLen + version, ipconfig_props_.subnet_prefix);
  }
  void ExpectPopulatedIPConfig() { ExpectPopulatedIPConfigWithVersion(0); }
  void ExpectPropertiesWithVersion(PropertyStore *store,
                                        const string &property_prefix,
                                        int version) {
    string string_value;
    Error unused_error;
    EXPECT_TRUE(store->GetStringProperty(property_prefix + ".Address",
                                         &string_value,
                                         &unused_error));
    EXPECT_EQ(VersionedAddress(kAddress, version), string_value);
    EXPECT_TRUE(store->GetStringProperty(property_prefix + ".Gateway",
                                         &string_value,
                                         &unused_error));
    EXPECT_EQ(VersionedAddress(kGateway, version), string_value);
    int32_t int_value;
    EXPECT_TRUE(store->GetInt32Property(property_prefix + ".Mtu", &int_value,
                                        &unused_error));
    EXPECT_EQ(kMtu + version, int_value);
    EXPECT_TRUE(store->GetStringProperty(property_prefix + ".NameServers",
                                         &string_value,
                                         &unused_error));
    EXPECT_EQ(VersionedAddress(kNameServer0, version) + "," +
              VersionedAddress(kNameServer1, version),
              string_value);
    EXPECT_TRUE(store->GetStringProperty(property_prefix + ".PeerAddress",
                                         &string_value,
                                         &unused_error));
    EXPECT_EQ(VersionedAddress(kPeerAddress, version), string_value);
    EXPECT_TRUE(store->GetInt32Property(property_prefix + ".Prefixlen",
                                        &int_value,
                                        &unused_error));
    EXPECT_EQ(kPrefixLen + version, int_value);
  }
  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.push_back(kNameServer0);
    ipconfig_props_.dns_servers.push_back(kNameServer1);
    ipconfig_props_.peer_address = kPeerAddress;
    ipconfig_props_.subnet_prefix = kPrefixLen;
  }
  void SetStaticPropertiesWithVersion(PropertyStore *store, int version) {
    Error error;
    store->SetStringProperty(
        "StaticIP.Address", VersionedAddress(kAddress, version), &error);
    store->SetStringProperty(
        "StaticIP.Gateway", VersionedAddress(kGateway, version), &error);
    store->SetInt32Property(
        "StaticIP.Mtu", kMtu + version, &error);
    store->SetStringProperty(
        "StaticIP.NameServers",
        VersionedAddress(kNameServer0, version) + "," +
        VersionedAddress(kNameServer1, version),
        &error);
    store->SetStringProperty(
        "StaticIP.PeerAddress",
        VersionedAddress(kPeerAddress, version),
        &error);
    store->SetInt32Property("StaticIP.Prefixlen", kPrefixLen + version, &error);
  }
  void SetStaticProperties(PropertyStore *store) {
    SetStaticPropertiesWithVersion(store, 0);
  }
  void SetStaticDictPropertiesWithVersion(PropertyStore *store, int version) {
    KeyValueStore args;
    args.SetString(kAddressProperty, VersionedAddress(kAddress, version));
    args.SetString(kGatewayProperty, VersionedAddress(kGateway, version));
    args.SetInt(kMtuProperty, kMtu + version);
    vector<string> name_servers;
    name_servers.push_back(VersionedAddress(kNameServer0, version));
    name_servers.push_back(VersionedAddress(kNameServer1, version));
    args.SetStrings(kNameServersProperty, name_servers);
    args.SetString(kPeerAddressProperty,
                   VersionedAddress(kPeerAddress, version));
    args.SetInt(kPrefixlenProperty, kPrefixLen + version);
    Error error;
    store->SetKeyValueStoreProperty(kStaticIPConfigProperty, args, &error);
  }

 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, ControlInterface) {
  PropertyStore store;
  static_params_.PlumbPropertyStore(&store);
  SetStaticProperties(&store);
  static_params_.ApplyTo(&ipconfig_props_);
  ExpectPopulatedIPConfig();

  EXPECT_TRUE(static_params_.ContainsAddress());
  Error unused_error;
  store.ClearProperty("StaticIP.Address", &unused_error);
  EXPECT_FALSE(static_params_.ContainsAddress());
  store.ClearProperty("StaticIP.Mtu", &unused_error);
  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);

  {
    Error error;
    EXPECT_FALSE(store.GetStringProperty("StaticIP.Address", nullptr, &error));
    EXPECT_EQ(Error::kNotFound, error.type());
  }
  string string_value;
  EXPECT_TRUE(store.GetStringProperty("StaticIP.Gateway", &string_value,
                                      &unused_error));
  EXPECT_EQ(kGateway, string_value);
  {
    Error error;
    EXPECT_FALSE(store.GetInt32Property("StaticIP.Mtu", nullptr, &error));
    EXPECT_EQ(Error::kNotFound, error.type());
  }
  EXPECT_TRUE(store.GetStringProperty("StaticIP.NameServers", &string_value,
                                      &unused_error));
  EXPECT_EQ(kNameServers, string_value);
  EXPECT_TRUE(store.GetStringProperty("StaticIP.PeerAddress", &string_value,
                                      &unused_error));
  EXPECT_EQ(kPeerAddress, string_value);
  int32_t int_value;
  EXPECT_TRUE(store.GetInt32Property("StaticIP.Prefixlen", &int_value,
                                     &unused_error));
  EXPECT_EQ(kPrefixLen, int_value);
}

TEST_F(StaticIpParametersTest, Profile) {
  StrictMock<MockStore> store;
  const string kID = "storage_id";
  EXPECT_CALL(store, GetString(kID, "StaticIP.Address", _))
      .WillOnce(DoAll(SetArgumentPointee<2>(string(kAddress)), Return(true)));
  EXPECT_CALL(store, GetString(kID, "StaticIP.Gateway", _))
      .WillOnce(DoAll(SetArgumentPointee<2>(string(kGateway)), Return(true)));
  EXPECT_CALL(store, GetInt(kID, "StaticIP.Mtu", _))
      .WillOnce(DoAll(SetArgumentPointee<2>(kMtu), Return(true)));
  EXPECT_CALL(store, GetString(kID, "StaticIP.NameServers", _))
      .WillOnce(DoAll(SetArgumentPointee<2>(string(kNameServers)),
                      Return(true)));
  EXPECT_CALL(store, GetString(kID, "StaticIP.PeerAddress", _))
      .WillOnce(DoAll(SetArgumentPointee<2>(string(kPeerAddress)),
                      Return(true)));
  EXPECT_CALL(store, GetInt(kID, "StaticIP.Prefixlen", _))
      .WillOnce(DoAll(SetArgumentPointee<2>(kPrefixLen), Return(true)));
  static_params_.Load(&store, kID);
  static_params_.ApplyTo(&ipconfig_props_);
  ExpectPopulatedIPConfig();

  EXPECT_CALL(store, SetString(kID, "StaticIP.Address", kAddress))
      .WillOnce(Return(true));
  EXPECT_CALL(store, SetString(kID, "StaticIP.Gateway", kGateway))
      .WillOnce(Return(true));
  EXPECT_CALL(store, SetInt(kID, "StaticIP.Mtu", kMtu))
      .WillOnce(Return(true));
  EXPECT_CALL(store, SetString(kID, "StaticIP.NameServers", kNameServers))
      .WillOnce(Return(true));
  EXPECT_CALL(store, SetString(kID, "StaticIP.PeerAddress", kPeerAddress))
      .WillOnce(Return(true));
  EXPECT_CALL(store, SetInt(kID, "StaticIP.Prefixlen", kPrefixLen))
      .WillOnce(Return(true));
  static_params_.Save(&store, kID);
}

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_params_.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(static_params_.saved_args_.IsEmpty());

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

TEST_F(StaticIpParametersTest, SavedParametersDict) {
  // 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);
  SetStaticDictPropertiesWithVersion(&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_params_.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_|.
  SetStaticDictPropertiesWithVersion(&static_params_props, 2);
  static_params_.RestoreTo(&ipconfig_props_);
  ExpectPopulatedIPConfigWithVersion(1);

  // All "SavedIP" parameters should be cleared.
  EXPECT_TRUE(static_params_.saved_args_.IsEmpty());

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

}  // namespace shill
