// 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 <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_log.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 testing::_;
using testing::InvokeWithoutArgs;
using testing::Mock;
using testing::Return;

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_interface(),
                                 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_;
  std::unique_ptr<MockDHCPProxy> proxy_;
  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_interface(), dispatcher(),
                                             &provider_, kDeviceName,
                                             lease_suffix));
  config->process_manager_ = &process_manager_;

  return config;
}

DHCPv6ConfigRefPtr DHCPv6ConfigTest::CreateRunningConfig(
    const string& lease_suffix) {
  DHCPv6ConfigRefPtr config(new DHCPv6Config(control_interface(), 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.Set<string>(DHCPv6Config::kConfigurationKeyIPAddress + kOne,
                   kConfigIPAddress);
  conf.Set<uint32_t>(DHCPv6Config::kConfigurationKeyIPAddressLeaseTime + kOne,
                     kConfigIPAddressLeaseTime);
  conf.Set<uint32_t>(
      DHCPv6Config::kConfigurationKeyIPAddressPreferredLeaseTime + kOne,
      kConfigIPAddressPreferredLeaseTime);
  conf.Set<string>(DHCPv6Config::kConfigurationKeyDelegatedPrefix + kOne,
                   kConfigDelegatedPrefix);
  conf.Set<uint32_t>(
      DHCPv6Config::kConfigurationKeyDelegatedPrefixLength + kOne,
      kConfigDelegatedPrefixLength);
  conf.Set<uint32_t>(
      DHCPv6Config::kConfigurationKeyDelegatedPrefixLeaseTime + kOne,
      kConfigDelegatedPrefixLeaseTime);
  conf.Set<uint32_t>(
      DHCPv6Config::kConfigurationKeyDelegatedPrefixPreferredLeaseTime + kOne,
      kConfigDelegatedPrefixPreferredLeaseTime);
  conf.Set<Strings>(DHCPv6Config::kConfigurationKeyDNS, {kConfigNameServer});
  conf.Set<Strings>(DHCPv6Config::kConfigurationKeyDomainSearch,
                    {kConfigDomainSearch});
  conf.Set<string>("UnknownKey", "UnknownValue");

  ASSERT_TRUE(config_->ParseConfiguration(conf));
  const Stringmaps kAddresses = {{
      {kDhcpv6AddressProperty, kConfigIPAddress},
      {kDhcpv6LengthProperty, "128"},
      {kDhcpv6LeaseDurationSecondsProperty,
       base::NumberToString(kConfigIPAddressLeaseTime)},
      {kDhcpv6PreferredLeaseDurationSecondsProperty,
       base::NumberToString(kConfigIPAddressPreferredLeaseTime)},
  }};
  EXPECT_EQ(kAddresses, config_->properties_.dhcpv6_addresses);
  const Stringmaps kDelegatedPrefixes = {{
      {kDhcpv6AddressProperty, kConfigDelegatedPrefix},
      {kDhcpv6LengthProperty,
       base::NumberToString(kConfigDelegatedPrefixLength)},
      {kDhcpv6LeaseDurationSecondsProperty,
       base::NumberToString(kConfigDelegatedPrefixLeaseTime)},
      {kDhcpv6PreferredLeaseDurationSecondsProperty,
       base::NumberToString(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_METHOD(void, SuccessCallback, (const IPConfigRefPtr&, bool));
  MOCK_METHOD(void, FailureCallback, (const IPConfigRefPtr&));

  // 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.Set<string>(DHCPv6Config::kConfigurationKeyIPAddress, kIPAddress);
  conf.Set<string>(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.Set<string>(DHCPv6Config::kConfigurationKeyIPAddress + kOne,
                     kIPAddress);
    const uint32_t kLeaseTime = 1;
    conf.Set<uint32_t>(DHCPv6Config::kConfigurationKeyIPAddressLeaseTime + kOne,
                       kLeaseTime);
    conf.Set<uint32_t>(
        DHCPv6Config::kConfigurationKeyIPAddressPreferredLeaseTime + kOne,
        kLeaseTime);
    conf.Set<uint32_t>(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.Set<string>(DHCPv6Config::kConfigurationKeyIPAddress + kOne, kIPAddress);
  conf.Set<string>(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.Set<string>(DHCPv6Config::kConfigurationKeyIPAddress + kOne, kIPAddress);
  conf.Set<string>(DHCPv6Config::kConfigurationKeyDelegatedPrefix + kOne,
                   kDelegatedPrefix);
  const uint32_t kLeaseTime = 1;
  conf.Set<uint32_t>(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.Set<string>(DHCPv6Config::kConfigurationKeyIPAddress + kOne, kIPAddress);
  conf.Set<string>(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
