// Copyright (c) 2013 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 <signal.h>

#include <string>

#include <base/files/file_util.h>
#include <base/files/scoped_temp_dir.h>
#include <base/strings/string_number_conversions.h>
#include <brillo/process_mock.h>
#include <brillo/test_helpers.h>
#include <gtest/gtest.h>

#include "vpn-manager/daemon.h"

using ::base::FilePath;
using ::base::IntToString;
using ::brillo::Process;
using ::brillo::ProcessImpl;
using ::brillo::ProcessMock;
using ::std::string;
using ::testing::_;
using ::testing::InvokeWithoutArgs;
using ::testing::Mock;
using ::testing::Return;

namespace vpn_manager {

namespace {
const char kBinSleep[] = "/bin/sleep";
}  // namespace

class DaemonTest : public ::testing::Test {
 public:
  void SetUp() override {
    FilePath cwd;
    CHECK(temp_dir_.CreateUniqueTempDir());
    FilePath test_path = temp_dir_.path().Append("daemon_testdir");
    base::DeleteFile(test_path, true);
    base::CreateDirectory(test_path);
    pid_file_path_ = test_path.Append("process.pid");
    daemon_.reset(new Daemon(pid_file_path_.value()));
  }

  void TearDown() override {
    if (real_process_)
      KillRealProcess();
  }

  // Needs to be public so we can use the testing::Invoke() family of functions.
  bool KillRealProcess() { return real_process_->Kill(SIGTERM, 5); }

 protected:
  void WritePidFile(const string& pid) {
    if (base::WriteFile(pid_file_path_, pid.c_str(), pid.size()) < 0) {
      LOG(ERROR) << "Unable to create " << pid_file_path_.value();
    }
  }

  void MakeRealProcess() {
    real_process_.reset(new ProcessImpl);
    real_process_->AddArg(kBinSleep);
    real_process_->AddArg("12345");
    CHECK(real_process_->Start());
  }

  const string& GetPidFile() { return daemon_->pid_file_; }

  Process* GetProcess() { return daemon_->process_.get(); }

  void SetProcess(Process* process) { daemon_->SetProcess(process); }

  FilePath pid_file_path_;
  std::unique_ptr<Daemon> daemon_;
  std::unique_ptr<Process> real_process_;
  base::ScopedTempDir temp_dir_;
};

TEST_F(DaemonTest, Construction) {
  EXPECT_EQ(nullptr, GetProcess());
  EXPECT_EQ(pid_file_path_.value(), GetPidFile());
  EXPECT_FALSE(daemon_->IsRunning());
}

TEST_F(DaemonTest, FindProcess) {
  EXPECT_FALSE(daemon_->FindProcess());
  EXPECT_FALSE(daemon_->IsRunning());

  // Start a real process and note its pid, then kill it so we know we have
  // a non-running pid.
  MakeRealProcess();
  pid_t pid = real_process_->pid();
  KillRealProcess();

  WritePidFile(IntToString(pid));
  EXPECT_FALSE(daemon_->FindProcess());
  EXPECT_EQ(nullptr, GetProcess());

  MakeRealProcess();
  pid = real_process_->pid();

  WritePidFile(IntToString(pid));
  EXPECT_TRUE(daemon_->FindProcess());
  EXPECT_TRUE(GetProcess());
  EXPECT_EQ(pid, GetProcess()->pid());
}

TEST_F(DaemonTest, IsRunningAndGetPid) {
  EXPECT_FALSE(daemon_->IsRunning());
  EXPECT_EQ(0, daemon_->GetPid());

  MakeRealProcess();
  pid_t pid = real_process_->pid();
  ASSERT_NE(0, pid);
  SetProcess(real_process_.release());
  EXPECT_TRUE(daemon_->IsRunning());
  EXPECT_EQ(pid, daemon_->GetPid());

  // Kill the process outside of the view of the process owned by the daemon.
  std::unique_ptr<Process> killed_process(new ProcessImpl);
  killed_process->Reset(pid);
  killed_process->Kill(SIGTERM, 5);
  EXPECT_FALSE(daemon_->IsRunning());
  EXPECT_EQ(pid, daemon_->GetPid());

  SetProcess(nullptr);
  EXPECT_EQ(0, daemon_->GetPid());
}

TEST_F(DaemonTest, SetProcessFromNull) {
  EXPECT_EQ(nullptr, GetProcess());
  SetProcess(nullptr);  // Should be a no-op.
  ProcessMock* process0 = new ProcessMock;
  SetProcess(process0);  // Passes ownership.
  EXPECT_EQ(process0, GetProcess());
  // Called during destructor.
  EXPECT_CALL(*process0, pid()).WillOnce(Return(0));
}

TEST_F(DaemonTest, SetProcessToNullFromNotRunning) {
  ProcessMock* process = new ProcessMock;
  EXPECT_CALL(*process, Release()).Times(0);
  EXPECT_CALL(*process, pid()).WillOnce(Return(0));
  SetProcess(process);  // Passes ownership.
  SetProcess(nullptr);
  EXPECT_EQ(nullptr, GetProcess());
}

TEST_F(DaemonTest, SetProcessToNullFromRunning) {
  MakeRealProcess();
  ProcessMock* process = new ProcessMock;
  EXPECT_CALL(*process, Release()).Times(0);
  EXPECT_CALL(*process, pid()).WillRepeatedly(Return(real_process_->pid()));
  EXPECT_CALL(*process, Kill(SIGKILL, _)).Times(1);
  SetProcess(process);  // Passes ownership.
  SetProcess(nullptr);
  EXPECT_EQ(nullptr, GetProcess());
}

TEST_F(DaemonTest, SetProcessToDifferentPid) {
  MakeRealProcess();
  ProcessMock* process0 = new ProcessMock;
  EXPECT_CALL(*process0, Release()).Times(0);
  EXPECT_CALL(*process0, pid()).WillRepeatedly(Return(real_process_->pid()));
  EXPECT_CALL(*process0, Kill(SIGKILL, _)).Times(1);
  ProcessMock* process1 = new ProcessMock;
  EXPECT_CALL(*process1, Release()).Times(0);
  EXPECT_CALL(*process1, pid()).WillOnce(Return(2));
  SetProcess(process0);  // Passes ownership.
  SetProcess(process1);  // Passes ownership.
  EXPECT_EQ(process1, GetProcess());
  // Verify expectations now so we don't trigger on calls during the destructor.
  Mock::VerifyAndClearExpectations(process1);
  EXPECT_CALL(*process1, pid()).WillOnce(Return(0));
}

TEST_F(DaemonTest, SetProcessToSamePid) {
  ProcessMock* process0 = new ProcessMock;
  EXPECT_CALL(*process0, Release()).Times(1);
  EXPECT_CALL(*process0, pid()).WillOnce(Return(1));
  ProcessMock* process1 = new ProcessMock;
  EXPECT_CALL(*process1, Release()).Times(0);
  EXPECT_CALL(*process1, pid()).WillOnce(Return(1));
  SetProcess(process0);  // Passes ownership.
  SetProcess(process1);  // Passes ownership.
  EXPECT_EQ(process1, GetProcess());
  // Reset expectations now so we don't trigger on calls during the destructor.
  Mock::VerifyAndClearExpectations(process1);
  EXPECT_CALL(*process1, pid()).WillOnce(Return(0));
}

TEST_F(DaemonTest, TerminateNoProcess) {
  WritePidFile("");
  ASSERT_TRUE(base::PathExists(pid_file_path_));
  EXPECT_TRUE(daemon_->Terminate());
  EXPECT_FALSE(base::PathExists(pid_file_path_));
}

TEST_F(DaemonTest, TerminateDeadProcess) {
  ProcessMock* process = new ProcessMock;
  EXPECT_CALL(*process, pid()).Times(2).WillRepeatedly(Return(0));
  EXPECT_CALL(*process, Kill(SIGTERM, _)).Times(0);
  SetProcess(process);  // Passes ownership.
  WritePidFile("");
  ASSERT_TRUE(base::PathExists(pid_file_path_));
  EXPECT_TRUE(daemon_->Terminate());
  EXPECT_FALSE(base::PathExists(pid_file_path_));
}

TEST_F(DaemonTest, TerminateLiveProcess) {
  MakeRealProcess();
  ProcessMock* process = new ProcessMock;
  EXPECT_CALL(*process, pid()).WillRepeatedly(Return(real_process_->pid()));
  EXPECT_CALL(*process, Kill(SIGTERM, _))
      .WillOnce(InvokeWithoutArgs(this, &DaemonTest::KillRealProcess));
  EXPECT_CALL(*process, Kill(SIGKILL, _)).Times(0);
  SetProcess(process);  // Passes ownership.
  WritePidFile("");
  ASSERT_TRUE(base::PathExists(pid_file_path_));
  // Returns false since the daemon was unable to terminate the process.
  EXPECT_TRUE(daemon_->Terminate());
  EXPECT_FALSE(base::PathExists(pid_file_path_));
}

TEST_F(DaemonTest, Destructor) {
  // This doesn't directly unit-test the Daemon class, but it does illuminate
  // a side effect of the destruction of the underlying Process it holds.
  MakeRealProcess();
  ProcessMock* process = new ProcessMock;
  EXPECT_CALL(*process, pid()).WillRepeatedly(Return(real_process_->pid()));
  EXPECT_CALL(*process, Kill(SIGKILL, _)).Times(1);
  SetProcess(process);  // Passes ownership.

  EXPECT_TRUE(daemon_->IsRunning());
  SetProcess(nullptr);
  daemon_.reset();
}

}  // namespace vpn_manager

int main(int argc, char** argv) {
  SetUpTests(&argc, argv, true);
  return RUN_ALL_TESTS();
}
