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

#include <base/file_util.h>
#include <base/scoped_temp_dir.h>
#include <base/string_util.h>
#include <gtest/gtest.h>

#include "shill/event_dispatcher.h"
#include "shill/nice_mock_control.h"
#include "shill/mock_adaptors.h"
#include "shill/mock_device_info.h"
#include "shill/mock_glib.h"
#include "shill/mock_manager.h"
#include "shill/mock_metrics.h"
#include "shill/mock_nss.h"
#include "shill/mock_vpn.h"
#include "shill/mock_vpn_service.h"
#include "shill/vpn.h"

using std::find;
using std::map;
using std::string;
using std::vector;
using testing::_;
using testing::ElementsAreArray;
using testing::NiceMock;
using testing::Return;
using testing::ReturnRef;
using testing::SetArgumentPointee;
using testing::StrictMock;

namespace shill {

class L2TPIPSecDriverTest : public testing::Test,
                            public RPCTaskDelegate {
 public:
  L2TPIPSecDriverTest()
      : device_info_(&control_, &dispatcher_, &metrics_, &manager_),
        manager_(&control_, &dispatcher_, &metrics_, &glib_),
        driver_(new L2TPIPSecDriver(&control_, &dispatcher_, &metrics_,
                                    &manager_, &device_info_, &glib_)),
        service_(new MockVPNService(&control_, &dispatcher_, &metrics_,
                                    &manager_, driver_)),
        device_(new MockVPN(&control_, &dispatcher_, &metrics_, &manager_,
                            kInterfaceName, kInterfaceIndex)) {
    driver_->nss_ = &nss_;
  }

  virtual ~L2TPIPSecDriverTest() {}

  virtual void SetUp() {
    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
  }

  virtual void TearDown() {
    driver_->child_watch_tag_ = 0;
    driver_->pid_ = 0;
    driver_->device_ = NULL;
    driver_->service_ = NULL;
    ASSERT_TRUE(temp_dir_.Delete());
  }

 protected:
  static const char kInterfaceName[];
  static const int kInterfaceIndex;

  void SetArg(const string &arg, const string &value) {
    driver_->args_.SetString(arg, value);
  }

  KeyValueStore *GetArgs() {
    return driver_->args();
  }

  // Used to assert that a flag appears in the options.
  void ExpectInFlags(const vector<string> &options, const string &flag,
                     const string &value);

  FilePath SetupPSKFile();

  // Inherited from RPCTaskDelegate.
  virtual void GetLogin(string *user, string *password);
  virtual void Notify(const string &reason, const map<string, string> &dict);

  ScopedTempDir temp_dir_;
  NiceMockControl control_;
  NiceMock<MockDeviceInfo> device_info_;
  EventDispatcher dispatcher_;
  MockMetrics metrics_;
  MockGLib glib_;
  MockManager manager_;
  L2TPIPSecDriver *driver_;  // Owned by |service_|.
  scoped_refptr<MockVPNService> service_;
  scoped_refptr<MockVPN> device_;
  MockNSS nss_;
};

const char L2TPIPSecDriverTest::kInterfaceName[] = "ppp0";
const int L2TPIPSecDriverTest::kInterfaceIndex = 123;

void L2TPIPSecDriverTest::GetLogin(string */*user*/, string */*password*/) {}

void L2TPIPSecDriverTest::Notify(
    const string &/*reason*/, const map<string, string> &/*dict*/) {}

void L2TPIPSecDriverTest::ExpectInFlags(
    const vector<string> &options, const string &flag, const string &value) {
  vector<string>::const_iterator it =
      find(options.begin(), options.end(), flag);

  EXPECT_TRUE(it != options.end());
  if (it != options.end())
    return;  // Don't crash below.
  it++;
  EXPECT_TRUE(it != options.end());
  if (it != options.end())
    return;  // Don't crash below.
  EXPECT_EQ(value, *it);
}

FilePath L2TPIPSecDriverTest::SetupPSKFile() {
  FilePath psk_file;
  EXPECT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir_.path(), &psk_file));
  EXPECT_FALSE(psk_file.empty());
  EXPECT_TRUE(file_util::PathExists(psk_file));
  driver_->psk_file_ = psk_file;
  return psk_file;
}

TEST_F(L2TPIPSecDriverTest, GetProviderType) {
  EXPECT_EQ(flimflam::kProviderL2tpIpsec, driver_->GetProviderType());
}

TEST_F(L2TPIPSecDriverTest, Cleanup) {
  driver_->Cleanup(Service::kStateIdle);  // Ensure no crash.

  const unsigned int kTag = 123;
  driver_->child_watch_tag_ = kTag;
  EXPECT_CALL(glib_, SourceRemove(kTag));
  const int kPID = 123456;
  driver_->pid_ = kPID;
  EXPECT_CALL(glib_, SpawnClosePID(kPID));
  driver_->service_ = service_;
  EXPECT_CALL(*service_, SetState(Service::kStateFailure));
  driver_->rpc_task_.reset(new RPCTask(&control_, this));
  FilePath psk_file = SetupPSKFile();
  driver_->Cleanup(Service::kStateFailure);
  EXPECT_FALSE(file_util::PathExists(psk_file));
  EXPECT_TRUE(driver_->psk_file_.empty());
  EXPECT_EQ(0, driver_->child_watch_tag_);
  EXPECT_EQ(0, driver_->pid_);
  EXPECT_FALSE(driver_->rpc_task_.get());
  EXPECT_FALSE(driver_->service_);
}

TEST_F(L2TPIPSecDriverTest, DeletePSKFile) {
  FilePath psk_file = SetupPSKFile();
  driver_->DeletePSKFile();
  EXPECT_FALSE(file_util::PathExists(psk_file));
  EXPECT_TRUE(driver_->psk_file_.empty());
}

TEST_F(L2TPIPSecDriverTest, InitEnvironment) {
  vector<string> env;
  driver_->rpc_task_.reset(new RPCTask(&control_, this));
  driver_->InitEnvironment(&env);
  ASSERT_EQ(3, env.size());
  EXPECT_EQ(string("CONNMAN_BUSNAME=") + RPCTaskMockAdaptor::kRpcConnId,
            env[0]);
  EXPECT_EQ(string("CONNMAN_INTERFACE=") + RPCTaskMockAdaptor::kRpcInterfaceId,
            env[1]);
  EXPECT_EQ(string("CONNMAN_PATH=") + RPCTaskMockAdaptor::kRpcId, env[2]);
}

TEST_F(L2TPIPSecDriverTest, InitOptionsNoHost) {
  Error error;
  vector<string> options;
  EXPECT_FALSE(driver_->InitOptions(&options, &error));
  EXPECT_EQ(Error::kInvalidArguments, error.type());
  EXPECT_TRUE(options.empty());
}

TEST_F(L2TPIPSecDriverTest, InitOptions) {
  static const char kHost[] = "192.168.2.254";
  static const char kCaCertNSS[] = "{1234}";
  static const char kPSK[] = "foobar";

  SetArg(flimflam::kProviderHostProperty, kHost);
  SetArg(flimflam::kL2tpIpsecCaCertNssProperty, kCaCertNSS);
  SetArg(flimflam::kL2tpIpsecPskProperty, kPSK);

  FilePath empty_cert;
  EXPECT_CALL(nss_, GetDERCertfile(kCaCertNSS, _)).WillOnce(Return(empty_cert));

  const FilePath temp_dir(temp_dir_.path());
  EXPECT_CALL(manager_, run_path()).WillOnce(ReturnRef(temp_dir));

  Error error;
  vector<string> options;
  EXPECT_TRUE(driver_->InitOptions(&options, &error));
  EXPECT_TRUE(error.IsSuccess());

  ExpectInFlags(options, "--remote_host", kHost);
  ASSERT_FALSE(driver_->psk_file_.empty());
  ExpectInFlags(options, "--psk_file", driver_->psk_file_.value());
}

TEST_F(L2TPIPSecDriverTest, InitPSKOptions) {
  Error error;
  vector<string> options;
  static const char kPSK[] = "foobar";
  const FilePath bad_dir("/non/existent/directory");
  const FilePath temp_dir(temp_dir_.path());
  EXPECT_CALL(manager_, run_path())
      .WillOnce(ReturnRef(bad_dir))
      .WillOnce(ReturnRef(temp_dir));

  EXPECT_TRUE(driver_->InitPSKOptions(&options, &error));
  EXPECT_TRUE(options.empty());
  EXPECT_TRUE(error.IsSuccess());

  SetArg(flimflam::kL2tpIpsecPskProperty, kPSK);

  EXPECT_FALSE(driver_->InitPSKOptions(&options, &error));
  EXPECT_TRUE(options.empty());
  EXPECT_EQ(Error::kInternalError, error.type());
  error.Reset();

  EXPECT_TRUE(driver_->InitPSKOptions(&options, &error));
  ASSERT_FALSE(driver_->psk_file_.empty());
  ExpectInFlags(options, "--psk_file", driver_->psk_file_.value());
  EXPECT_TRUE(error.IsSuccess());
  string contents;
  EXPECT_TRUE(
      file_util::ReadFileToString(driver_->psk_file_, &contents));
  EXPECT_EQ(kPSK, contents);
  struct stat buf;
  ASSERT_EQ(0, stat(driver_->psk_file_.value().c_str(), &buf));
  EXPECT_EQ(S_IFREG | S_IRUSR | S_IWUSR, buf.st_mode);
}

TEST_F(L2TPIPSecDriverTest, InitNSSOptions) {
  static const char kHost[] = "192.168.2.254";
  static const char kCaCertNSS[] = "{1234}";
  static const char kNSSCertfile[] = "/tmp/nss-cert";
  FilePath empty_cert;
  FilePath nss_cert(kNSSCertfile);
  SetArg(flimflam::kProviderHostProperty, kHost);
  SetArg(flimflam::kL2tpIpsecCaCertNssProperty, kCaCertNSS);
  EXPECT_CALL(nss_,
              GetDERCertfile(kCaCertNSS,
                             ElementsAreArray(kHost, arraysize(kHost) - 1)))
      .WillOnce(Return(empty_cert))
      .WillOnce(Return(nss_cert));

  vector<string> options;
  driver_->InitNSSOptions(&options);
  EXPECT_TRUE(options.empty());
  driver_->InitNSSOptions(&options);
  ExpectInFlags(options, "--server_ca_file", kNSSCertfile);
}

TEST_F(L2TPIPSecDriverTest, AppendValueOption) {
  static const char kOption[] = "--l2tpipsec-option";
  static const char kProperty[] = "L2TPIPSec.SomeProperty";
  static const char kValue[] = "some-property-value";
  static const char kOption2[] = "--l2tpipsec-option2";
  static const char kProperty2[] = "L2TPIPSec.SomeProperty2";
  static const char kValue2[] = "some-property-value2";

  vector<string> options;
  EXPECT_FALSE(
      driver_->AppendValueOption(
          "L2TPIPSec.UnknownProperty", kOption, &options));
  EXPECT_TRUE(options.empty());

  SetArg(kProperty, "");
  EXPECT_FALSE(driver_->AppendValueOption(kProperty, kOption, &options));
  EXPECT_TRUE(options.empty());

  SetArg(kProperty, kValue);
  SetArg(kProperty2, kValue2);
  EXPECT_TRUE(driver_->AppendValueOption(kProperty, kOption, &options));
  EXPECT_TRUE(driver_->AppendValueOption(kProperty2, kOption2, &options));
  EXPECT_EQ(4, options.size());
  EXPECT_EQ(kOption, options[0]);
  EXPECT_EQ(kValue, options[1]);
  EXPECT_EQ(kOption2, options[2]);
  EXPECT_EQ(kValue2, options[3]);
}

TEST_F(L2TPIPSecDriverTest, AppendFlag) {
  static const char kTrueOption[] = "--l2tpipsec-option";
  static const char kFalseOption[] = "--nol2tpipsec-option";
  static const char kProperty[] = "L2TPIPSec.SomeProperty";
  static const char kTrueOption2[] = "--l2tpipsec-option2";
  static const char kFalseOption2[] = "--nol2tpipsec-option2";
  static const char kProperty2[] = "L2TPIPSec.SomeProperty2";

  vector<string> options;
  EXPECT_FALSE(driver_->AppendFlag("L2TPIPSec.UnknownProperty",
                                   kTrueOption, kFalseOption, &options));
  EXPECT_TRUE(options.empty());

  SetArg(kProperty, "");
  EXPECT_FALSE(
      driver_->AppendFlag(kProperty, kTrueOption, kFalseOption, &options));
  EXPECT_TRUE(options.empty());

  SetArg(kProperty, "true");
  SetArg(kProperty2, "false");
  EXPECT_TRUE(
      driver_->AppendFlag(kProperty, kTrueOption, kFalseOption, &options));
  EXPECT_TRUE(
      driver_->AppendFlag(kProperty2, kTrueOption2, kFalseOption2, &options));
  EXPECT_EQ(2, options.size());
  EXPECT_EQ(kTrueOption, options[0]);
  EXPECT_EQ(kFalseOption2, options[1]);
}

TEST_F(L2TPIPSecDriverTest, GetLogin) {
  static const char kUser[] = "joesmith";
  static const char kPassword[] = "random-password";
  string user, password;
  SetArg(flimflam::kL2tpIpsecUserProperty, kUser);
  driver_->GetLogin(&user, &password);
  EXPECT_TRUE(user.empty());
  EXPECT_TRUE(password.empty());
  SetArg(flimflam::kL2tpIpsecUserProperty, "");
  SetArg(flimflam::kL2tpIpsecPasswordProperty, kPassword);
  driver_->GetLogin(&user, &password);
  EXPECT_TRUE(user.empty());
  EXPECT_TRUE(password.empty());
  SetArg(flimflam::kL2tpIpsecUserProperty, kUser);
  driver_->GetLogin(&user, &password);
  EXPECT_EQ(kUser, user);
  EXPECT_EQ(kPassword, password);
}

TEST_F(L2TPIPSecDriverTest, OnL2TPIPSecVPNDied) {
  const int kPID = 99999;
  driver_->child_watch_tag_ = 333;
  driver_->pid_ = kPID;
  EXPECT_CALL(glib_, SpawnClosePID(kPID));
  L2TPIPSecDriver::OnL2TPIPSecVPNDied(kPID, 2, driver_);
  EXPECT_EQ(0, driver_->child_watch_tag_);
  EXPECT_EQ(0, driver_->pid_);
}

namespace {
MATCHER(CheckEnv, "") {
  if (!arg || !arg[0] || !arg[1] || !arg[2] || arg[3]) {
    return false;
  }
  return StartsWithASCII(arg[0], "CONNMAN_", true);
}
}  // namespace

TEST_F(L2TPIPSecDriverTest, SpawnL2TPIPSecVPN) {
  Error error;
  EXPECT_FALSE(driver_->SpawnL2TPIPSecVPN(&error));
  EXPECT_TRUE(error.IsFailure());

  static const char kHost[] = "192.168.2.254";
  SetArg(flimflam::kProviderHostProperty, kHost);
  driver_->rpc_task_.reset(new RPCTask(&control_, this));

  const int kPID = 234678;
  EXPECT_CALL(glib_,
              SpawnAsyncWithPipesCWD(_, CheckEnv(), _, _, _, _, _, _, _, _))
      .WillOnce(Return(false))
      .WillOnce(DoAll(SetArgumentPointee<5>(kPID), Return(true)));
  const int kTag = 6;
  EXPECT_CALL(glib_, ChildWatchAdd(kPID, &driver_->OnL2TPIPSecVPNDied, driver_))
      .WillOnce(Return(kTag));
  error.Reset();
  EXPECT_FALSE(driver_->SpawnL2TPIPSecVPN(&error));
  EXPECT_EQ(Error::kInternalError, error.type());
  error.Reset();
  EXPECT_TRUE(driver_->SpawnL2TPIPSecVPN(&error));
  EXPECT_TRUE(error.IsSuccess());
  EXPECT_EQ(kPID, driver_->pid_);
  EXPECT_EQ(kTag, driver_->child_watch_tag_);
}

TEST_F(L2TPIPSecDriverTest, Connect) {
  EXPECT_CALL(*service_, SetState(Service::kStateConfiguring));
  static const char kHost[] = "192.168.2.254";
  SetArg(flimflam::kProviderHostProperty, kHost);
  EXPECT_CALL(glib_, SpawnAsyncWithPipesCWD(_, _, _, _, _, _, _, _, _, _))
      .WillOnce(Return(true));
  EXPECT_CALL(glib_, ChildWatchAdd(_, _, _)).WillOnce(Return(1));
  Error error;
  driver_->Connect(service_, &error);
  EXPECT_TRUE(error.IsSuccess());
}

TEST_F(L2TPIPSecDriverTest, InitPropertyStore) {
  // Sanity test property store initialization.
  PropertyStore store;
  driver_->InitPropertyStore(&store);
  const string kUser = "joe";
  Error error;
  EXPECT_TRUE(
      store.SetStringProperty(flimflam::kL2tpIpsecUserProperty, kUser, &error));
  EXPECT_TRUE(error.IsSuccess());
  EXPECT_EQ(kUser, GetArgs()->GetString(flimflam::kL2tpIpsecUserProperty));
}

TEST_F(L2TPIPSecDriverTest, ParseIPConfiguration) {
  map<string, string> config;
  config["INTERNAL_IP4_ADDRESS"] = "4.5.6.7";
  config["EXTERNAL_IP4_ADDRESS"] = "33.44.55.66";
  config["GATEWAY_ADDRESS"] = "192.168.1.1";
  config["DNS1"] = "1.1.1.1";
  config["DNS2"] = "2.2.2.2";
  config["INTERNAL_IFNAME"] = "ppp0";
  config["LNS_ADDRESS"] = "99.88.77.66";
  config["foo"] = "bar";
  IPConfig::Properties props;
  string interface_name;
  L2TPIPSecDriver::ParseIPConfiguration(config, &props, &interface_name);
  EXPECT_EQ(IPAddress::kFamilyIPv4, props.address_family);
  EXPECT_EQ("4.5.6.7", props.address);
  EXPECT_EQ("33.44.55.66", props.peer_address);
  EXPECT_EQ("192.168.1.1", props.gateway);
  EXPECT_EQ("99.88.77.66", props.trusted_ip);
  ASSERT_EQ(2, props.dns_servers.size());
  EXPECT_EQ("1.1.1.1", props.dns_servers[0]);
  EXPECT_EQ("2.2.2.2", props.dns_servers[1]);
  EXPECT_EQ("ppp0", interface_name);
}

namespace {
MATCHER_P(IsIPAddress, address, "") {
  IPAddress ip_address(IPAddress::kFamilyIPv4);
  EXPECT_TRUE(ip_address.SetAddressFromString(address));
  return ip_address.Equals(arg);
}
}  // namespace

TEST_F(L2TPIPSecDriverTest, Notify) {
  map<string, string> config;
  config["INTERNAL_IFNAME"] = kInterfaceName;
  EXPECT_CALL(device_info_, GetIndex(kInterfaceName))
      .WillOnce(Return(kInterfaceIndex));
  EXPECT_CALL(*device_, SetEnabled(true));
  EXPECT_CALL(*device_, UpdateIPConfig(_));
  driver_->device_ = device_;
  FilePath psk_file = SetupPSKFile();
  driver_->Notify("connect", config);
  EXPECT_FALSE(file_util::PathExists(psk_file));
  EXPECT_TRUE(driver_->psk_file_.empty());
}

}  // namespace shill
