// 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/dhcp/dhcpv6_config.h"

#include <memory>
#include <string>
#include <vector>

#include <base/bind.h>
#include <base/files/file_util.h>
#include <base/files/scoped_temp_dir.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/stringprintf.h>
#include <chromeos/dbus/service_constants.h>

#include "shill/dhcp/mock_dhcp_provider.h"
#include "shill/dhcp/mock_dhcp_proxy.h"
#include "shill/event_dispatcher.h"
#include "shill/mock_control.h"
#include "shill/mock_log.h"
#include "shill/mock_metrics.h"
#include "shill/mock_process_manager.h"
#include "shill/property_store_test.h"
#include "shill/testing.h"

using base::Bind;
using base::FilePath;
using base::ScopedTempDir;
using base::Unretained;
using std::string;
using std::unique_ptr;
using std::vector;
using testing::_;
using testing::InvokeWithoutArgs;
using testing::Mock;
using testing::Return;
using testing::Test;

namespace shill {

namespace {
const char kDeviceName[] = "eth0";
const char kLeaseFileSuffix[] = "leasefilesuffix";
const bool kHasLeaseSuffix = true;
const char kIPAddress[] = "2001:db8:0:1::1";
const char kDelegatedPrefix[] = "2001:db8:0:100::";
}  // namespace

using DHCPv6ConfigRefPtr = scoped_refptr<DHCPv6Config>;

class DHCPv6ConfigTest : public PropertyStoreTest {
 public:
  DHCPv6ConfigTest()
      : proxy_(new MockDHCPProxy()),
        config_(new DHCPv6Config(&control_,
                                 dispatcher(),
                                 &provider_,
                                 kDeviceName,
                                 kLeaseFileSuffix)) {}

  void SetUp() override {
    config_->process_manager_ = &process_manager_;
  }

  bool StartInstance(DHCPv6ConfigRefPtr config) {
    return config->Start();
  }

  void StopInstance() {
    config_->Stop("In test");
  }

  DHCPv6ConfigRefPtr CreateMockMinijailConfig(const string& lease_suffix);
  DHCPv6ConfigRefPtr CreateRunningConfig(const string& lease_suffix);
  void StopRunningConfigAndExpect(DHCPv6ConfigRefPtr config,
                                  bool lease_file_exists);

 protected:
  static const int kPID;
  static const unsigned int kTag;

  FilePath lease_file_;
  FilePath pid_file_;
  ScopedTempDir temp_dir_;
  unique_ptr<MockDHCPProxy> proxy_;
  MockControl control_;
  MockProcessManager process_manager_;
  MockDHCPProvider provider_;
  DHCPv6ConfigRefPtr config_;
};

const int DHCPv6ConfigTest::kPID = 123456;
const unsigned int DHCPv6ConfigTest::kTag = 77;

DHCPv6ConfigRefPtr DHCPv6ConfigTest::CreateMockMinijailConfig(
    const string& lease_suffix) {
  DHCPv6ConfigRefPtr config(new DHCPv6Config(&control_,
                                             dispatcher(),
                                             &provider_,
                                             kDeviceName,
                                             lease_suffix));
  config->process_manager_ = &process_manager_;

  return config;
}

DHCPv6ConfigRefPtr DHCPv6ConfigTest::CreateRunningConfig(
    const string& lease_suffix) {
  DHCPv6ConfigRefPtr config(new DHCPv6Config(&control_,
                                             dispatcher(),
                                             &provider_,
                                             kDeviceName,
                                             lease_suffix));
  config->process_manager_ = &process_manager_;
  EXPECT_CALL(process_manager_,
              StartProcessInMinijail(_, _, _, _, _, _, _, _, _))
      .WillOnce(Return(kPID));
  EXPECT_CALL(provider_, BindPID(kPID, IsRefPtrTo(config)));
  EXPECT_TRUE(config->Start());
  EXPECT_EQ(kPID, config->pid_);

  EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
  config->root_ = temp_dir_.GetPath();
  FilePath varrun = temp_dir_.GetPath().Append("var/run/dhcpcd");
  EXPECT_TRUE(base::CreateDirectory(varrun));
  pid_file_ = varrun.Append(base::StringPrintf("dhcpcd-%s-6.pid", kDeviceName));
  FilePath varlib = temp_dir_.GetPath().Append("var/lib/dhcpcd");
  EXPECT_TRUE(base::CreateDirectory(varlib));
  lease_file_ =
      varlib.Append(base::StringPrintf("dhcpcd-%s.lease6", kDeviceName));
  EXPECT_EQ(0, base::WriteFile(pid_file_, "", 0));
  EXPECT_EQ(0, base::WriteFile(lease_file_, "", 0));
  EXPECT_TRUE(base::PathExists(pid_file_));
  EXPECT_TRUE(base::PathExists(lease_file_));

  return config;
}

void DHCPv6ConfigTest::StopRunningConfigAndExpect(DHCPv6ConfigRefPtr config,
                                                  bool lease_file_exists) {
  ScopedMockLog log;
  // We use a non-zero exit status so that we get the log message.
  EXPECT_CALL(log, Log(_, _, ::testing::EndsWith("status 10")));
  EXPECT_CALL(provider_, UnbindPID(kPID));
  config->OnProcessExited(10);

  EXPECT_FALSE(base::PathExists(pid_file_));
  EXPECT_EQ(lease_file_exists, base::PathExists(lease_file_));
}

TEST_F(DHCPv6ConfigTest, ParseConfiguration) {
  const char kConfigIPAddress[] = "2001:db8:0:1::129";
  const char kConfigDelegatedPrefix[] = "2001:db8:1:100::";
  const char kConfigNameServer[] = "fec8:0::1";
  const char kConfigDomainSearch[] = "example.domain";
  const uint32_t kConfigDelegatedPrefixLength = 56;
  const uint32_t kConfigIPAddressLeaseTime = 5;
  const uint32_t kConfigIPAddressPreferredLeaseTime = 4;
  const uint32_t kConfigDelegatedPrefixLeaseTime = 10;
  const uint32_t kConfigDelegatedPrefixPreferredLeaseTime = 3;

  // For building configuration strings.
  const std::string kOne = "1";

  KeyValueStore conf;
  conf.SetString(DHCPv6Config::kConfigurationKeyIPAddress + kOne,
                 kConfigIPAddress);
  conf.SetUint(DHCPv6Config::kConfigurationKeyIPAddressLeaseTime + kOne,
               kConfigIPAddressLeaseTime);
  conf.SetUint(
      DHCPv6Config::kConfigurationKeyIPAddressPreferredLeaseTime + kOne,
      kConfigIPAddressPreferredLeaseTime);
  conf.SetString(DHCPv6Config::kConfigurationKeyDelegatedPrefix + kOne,
                 kConfigDelegatedPrefix);
  conf.SetUint(DHCPv6Config::kConfigurationKeyDelegatedPrefixLength + kOne,
               kConfigDelegatedPrefixLength);
  conf.SetUint(DHCPv6Config::kConfigurationKeyDelegatedPrefixLeaseTime + kOne,
               kConfigDelegatedPrefixLeaseTime);
  conf.SetUint(
      DHCPv6Config::kConfigurationKeyDelegatedPrefixPreferredLeaseTime + kOne,
      kConfigDelegatedPrefixPreferredLeaseTime);
  {
    vector<string> dns;
    dns.push_back(kConfigNameServer);
    conf.SetStrings(DHCPv6Config::kConfigurationKeyDNS, dns);
  }
  {
    vector<string> domain_search;
    domain_search.push_back(kConfigDomainSearch);
    conf.SetStrings(DHCPv6Config::kConfigurationKeyDomainSearch, domain_search);
  }
  conf.SetString("UnknownKey", "UnknownValue");

  ASSERT_TRUE(config_->ParseConfiguration(conf));
  const Stringmaps kAddresses = {{{kDhcpv6AddressProperty, kConfigIPAddress},
      {kDhcpv6LengthProperty, "128"},
      {kDhcpv6LeaseDurationSecondsProperty,
          base::UintToString(kConfigIPAddressLeaseTime)},
      {kDhcpv6PreferredLeaseDurationSecondsProperty,
          base::UintToString(kConfigIPAddressPreferredLeaseTime)},
  }};
  EXPECT_EQ(kAddresses, config_->properties_.dhcpv6_addresses);
  const Stringmaps kDelegatedPrefixes =
      {{{kDhcpv6AddressProperty, kConfigDelegatedPrefix},
      {kDhcpv6LengthProperty, base::UintToString(kConfigDelegatedPrefixLength)},
      {kDhcpv6LeaseDurationSecondsProperty,
          base::UintToString(kConfigDelegatedPrefixLeaseTime)},
      {kDhcpv6PreferredLeaseDurationSecondsProperty,
          base::UintToString(kConfigDelegatedPrefixPreferredLeaseTime)},
  }};
  EXPECT_EQ(kDelegatedPrefixes, config_->properties_.dhcpv6_delegated_prefixes);
  ASSERT_EQ(1, config_->properties_.dns_servers.size());
  EXPECT_EQ(kConfigNameServer, config_->properties_.dns_servers[0]);
  ASSERT_EQ(1, config_->properties_.domain_search.size());
  EXPECT_EQ(kConfigDomainSearch, config_->properties_.domain_search[0]);
  // Use IP address lease time since it is shorter.
  EXPECT_EQ(kConfigIPAddressLeaseTime,
            config_->properties_.lease_duration_seconds);
}

MATCHER_P(IsDHCPCDv6Args, has_lease_suffix, "") {
  if (arg[0] != "-B" ||
      arg[1] != "-q" ||
      arg[2] != "-6" ||
      arg[3] != "-a") {
    return false;
  }

  int end_offset = 4;

  string device_arg = has_lease_suffix ?
      string(kDeviceName) + "=" + string(kLeaseFileSuffix) : kDeviceName;
  return arg[end_offset] == device_arg;
}

TEST_F(DHCPv6ConfigTest, StartDhcpcd) {
  EXPECT_CALL(process_manager_,
              StartProcessInMinijail(_, _, IsDHCPCDv6Args(kHasLeaseSuffix), _,
                                     _, _, _, _, _))
      .WillOnce(Return(-1));
  EXPECT_FALSE(StartInstance(config_));
}


namespace {

class DHCPv6ConfigCallbackTest : public DHCPv6ConfigTest {
 public:
  void SetUp() override {
    DHCPv6ConfigTest::SetUp();
    config_->RegisterUpdateCallback(
        Bind(&DHCPv6ConfigCallbackTest::SuccessCallback, Unretained(this)));
    config_->RegisterFailureCallback(
        Bind(&DHCPv6ConfigCallbackTest::FailureCallback, Unretained(this)));
    ip_config_ = config_;
  }

  MOCK_METHOD2(SuccessCallback,
               void(const IPConfigRefPtr& ipconfig, bool new_lease_acquired));
  MOCK_METHOD1(FailureCallback, void(const IPConfigRefPtr& ipconfig));

  // The mock methods above take IPConfigRefPtr because this is the type
  // that the registered callbacks take.  This conversion of the DHCP
  // config ref pointer eases our work in setting up expectations.
  const IPConfigRefPtr& ConfigRef() { return ip_config_; }

 private:
  IPConfigRefPtr ip_config_;
};

}  // namespace

TEST_F(DHCPv6ConfigCallbackTest, ProcessEventSignalFail) {
  KeyValueStore conf;
  conf.SetString(DHCPv6Config::kConfigurationKeyIPAddress, kIPAddress);
  conf.SetString(DHCPv6Config::kConfigurationKeyDelegatedPrefix,
                 kDelegatedPrefix);
  EXPECT_CALL(*this, SuccessCallback(_, _)).Times(0);
  EXPECT_CALL(*this, FailureCallback(ConfigRef()));
  config_->ProcessEventSignal(DHCPv6Config::kReasonFail, conf);
  Mock::VerifyAndClearExpectations(this);
  EXPECT_TRUE(config_->properties().address.empty());
}

TEST_F(DHCPv6ConfigCallbackTest, ProcessEventSignalSuccess) {
  const std::string kOne = "1";
  for (const auto& reason : { DHCPv6Config::kReasonBound,
                              DHCPv6Config::kReasonRebind,
                              DHCPv6Config::kReasonReboot,
                              DHCPv6Config::kReasonRenew }) {
    KeyValueStore conf;
    conf.SetString(DHCPv6Config::kConfigurationKeyIPAddress + kOne,
                   kIPAddress);
    const uint32_t kLeaseTime = 1;
    conf.SetUint(DHCPv6Config::kConfigurationKeyIPAddressLeaseTime + kOne,
                 kLeaseTime);
    conf.SetUint(
        DHCPv6Config::kConfigurationKeyIPAddressPreferredLeaseTime + kOne,
        kLeaseTime);
    conf.SetUint(DHCPv6Config::kConfigurationKeyIPAddressIaid, 0);

    EXPECT_CALL(*this, SuccessCallback(ConfigRef(), true));
    EXPECT_CALL(*this, FailureCallback(_)).Times(0);
    config_->ProcessEventSignal(reason, conf);
    string failure_message = string(reason) + " failed";
    EXPECT_TRUE(Mock::VerifyAndClearExpectations(this)) << failure_message;
    ASSERT_EQ(1, config_->properties().dhcpv6_addresses.size());
    auto it =
        config_->properties().dhcpv6_addresses[0].find(kDhcpv6AddressProperty);
    ASSERT_TRUE(it != config_->properties().dhcpv6_addresses[0].end())
        << failure_message;
    EXPECT_EQ("2001:db8:0:1::1", it->second)<< failure_message;
  }
}

TEST_F(DHCPv6ConfigCallbackTest, StoppedDuringFailureCallback) {
  const std::string kOne = "1";
  KeyValueStore conf;
  conf.SetString(DHCPv6Config::kConfigurationKeyIPAddress + kOne, kIPAddress);
  conf.SetString(DHCPv6Config::kConfigurationKeyDelegatedPrefix + kOne,
                 kDelegatedPrefix);
  // Stop the DHCP config while it is calling the failure callback.  We
  // need to ensure that no callbacks are left running inadvertently as
  // a result.
  EXPECT_CALL(*this, FailureCallback(ConfigRef()))
      .WillOnce(InvokeWithoutArgs(this, &DHCPv6ConfigTest::StopInstance));
  config_->ProcessEventSignal(DHCPv6Config::kReasonFail, conf);
  EXPECT_TRUE(Mock::VerifyAndClearExpectations(this));
}

TEST_F(DHCPv6ConfigCallbackTest, StoppedDuringSuccessCallback) {
  const std::string kOne = "1";
  KeyValueStore conf;
  conf.SetString(DHCPv6Config::kConfigurationKeyIPAddress + kOne, kIPAddress);
  conf.SetString(DHCPv6Config::kConfigurationKeyDelegatedPrefix + kOne,
                 kDelegatedPrefix);
  const uint32_t kLeaseTime = 1;
  conf.SetUint(DHCPv6Config::kConfigurationKeyIPAddressLeaseTime, kLeaseTime);
  // Stop the DHCP config while it is calling the success callback.  This
  // can happen if the device has a static IP configuration and releases
  // the lease after accepting other network parameters from the DHCP
  // IPConfig properties.  We need to ensure that no callbacks are left
  // running inadvertently as a result.
  EXPECT_CALL(*this, SuccessCallback(ConfigRef(), true))
      .WillOnce(InvokeWithoutArgs(this, &DHCPv6ConfigTest::StopInstance));
  config_->ProcessEventSignal(DHCPv6Config::kReasonBound, conf);
  EXPECT_TRUE(Mock::VerifyAndClearExpectations(this));
}

TEST_F(DHCPv6ConfigCallbackTest, ProcessEventSignalUnknown) {
  const std::string kOne = "1";
  KeyValueStore conf;
  conf.SetString(DHCPv6Config::kConfigurationKeyIPAddress + kOne, kIPAddress);
  conf.SetString(DHCPv6Config::kConfigurationKeyDelegatedPrefix + kOne,
                 kDelegatedPrefix);
  static const char kReasonUnknown[] = "UNKNOWN_REASON";
  EXPECT_CALL(*this, SuccessCallback(_, _)).Times(0);
  EXPECT_CALL(*this, FailureCallback(_)).Times(0);
  config_->ProcessEventSignal(kReasonUnknown, conf);
  Mock::VerifyAndClearExpectations(this);
  EXPECT_TRUE(config_->properties().dhcpv6_addresses.empty());
}

TEST_F(DHCPv6ConfigTest, StartSuccessEphemeral) {
  DHCPv6ConfigRefPtr config =
      CreateRunningConfig(kDeviceName);
  StopRunningConfigAndExpect(config, false);
}

TEST_F(DHCPv6ConfigTest, StartSuccessPersistent) {
  DHCPv6ConfigRefPtr config =
      CreateRunningConfig(kLeaseFileSuffix);
  StopRunningConfigAndExpect(config, true);
}

}  // namespace shill
