// 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 <errno.h>
#include <sys/types.h>
#include <unistd.h>

#include <memory>

#include <base/bind.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/files/scoped_temp_dir.h>
#include <base/location.h>
#include <base/logging.h>
#include <base/memory/ptr_util.h>
#include <base/memory/ref_counted.h>
#include <base/optional.h>
#include <base/strings/string_util.h>
#include <brillo/message_loops/base_message_loop.h>
#include <chromeos/dbus/service_constants.h>
#include <dbus/mock_object_proxy.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "login_manager/browser_job.h"
#include "login_manager/fake_browser_job.h"
#include "login_manager/fake_child_process.h"
#include "login_manager/fake_generator_job.h"
#include "login_manager/mock_device_policy_service.h"
#include "login_manager/mock_file_checker.h"
#include "login_manager/mock_liveness_checker.h"
#include "login_manager/mock_metrics.h"
#include "login_manager/mock_session_manager.h"
#include "login_manager/system_utils_impl.h"
#include "power_manager/proto_bindings/suspend.pb.h"

using ::testing::_;
using ::testing::AnyNumber;
using ::testing::AtLeast;
using ::testing::Return;
using ::testing::Sequence;

namespace login_manager {

// Used as a fixture for the tests in this file.
// Gives useful shared functionality.
class SessionManagerProcessTest : public ::testing::Test {
 public:
  SessionManagerProcessTest()
      : manager_(nullptr),
        liveness_checker_(new MockLivenessChecker),
        session_manager_impl_(new MockSessionManager),
        must_destroy_mocks_(true) {}
  SessionManagerProcessTest(const SessionManagerProcessTest&) = delete;
  SessionManagerProcessTest& operator=(const SessionManagerProcessTest&) =
      delete;

  ~SessionManagerProcessTest() override {
    if (must_destroy_mocks_) {
      delete liveness_checker_;
      delete session_manager_impl_;
    }
  }

  void SetUp() override {
    brillo_loop_.SetAsCurrent();
    ASSERT_TRUE(tmpdir_.CreateUniqueTempDir());

    aborted_browser_pid_path_ = tmpdir_.GetPath().Append("aborted_browser_pid");
  }

  void TearDown() override {
    must_destroy_mocks_ = !manager_.get();
    manager_ = nullptr;
  }

 protected:
  // kFakeEmail is NOT const so that it can be passed to methods that
  // implement dbus calls, which (of necessity) take bare gchar*.
  static char kFakeEmail[];
  static const pid_t kFakePid;
  static const int kExit;

  void MockUtils() { manager_->test_api().set_systemutils(&utils_); }

  void ExpectShutdown() {
    EXPECT_CALL(*session_manager_impl_, AnnounceSessionStoppingIfNeeded())
        .Times(1);
    EXPECT_CALL(*session_manager_impl_, AnnounceSessionStopped()).Times(1);
  }

  void ExpectLivenessChecking() {
    EXPECT_CALL(*liveness_checker_, Start()).Times(AtLeast(1));
    EXPECT_CALL(*liveness_checker_, Stop()).Times(AtLeast(1));
  }

  void ExpectOneJobReRun(FakeBrowserJob* job, int exit_status) {
    EXPECT_CALL(*job, KillEverything(SIGKILL, _)).Times(AnyNumber());
    EXPECT_CALL(*session_manager_impl_, ShouldEndSession(_))
        .WillRepeatedly(Return(false));
    // Return false once to allow the job to rerun. We then return true to stop
    // the loop; otherwise, the test will keep restarting the job forever.
    EXPECT_CALL(*job, ShouldStop())
        .WillOnce(Return(false))
        .WillOnce(Return(true));

    // Browser shutdown time is not tracked if browser does not request stop.
    EXPECT_CALL(metrics_, SendBrowserShutdownTime(_)).Times(0);

    job->set_fake_child_process(std::make_unique<FakeChildProcess>(
        kFakePid, exit_status, manager_->test_api()));
  }

  void InitManager(std::unique_ptr<BrowserJobInterface> job) {
    manager_ =
        new SessionManagerService(std::move(job), getuid(), base::nullopt,
                                  base::TimeDelta::FromSeconds(3), false,
                                  base::TimeDelta(), &metrics_, &utils_);
    manager_->test_api().set_liveness_checker(liveness_checker_);
    manager_->test_api().set_session_manager(session_manager_impl_);
    manager_->test_api().set_aborted_browser_pid_path(
        aborted_browser_pid_path_);
  }

  void SimpleRunManager() {
    ExpectShutdown();
    manager_->RunBrowser();
    brillo_loop_.Run();
  }

  void ForceRunLoop() { brillo_loop_.Run(); }

  FakeBrowserJob* CreateMockJobAndInitManager(bool schedule_exit) {
    FakeBrowserJob* job = new FakeBrowserJob("FakeBrowserJob", schedule_exit);
    InitManager(base::WrapUnique(job));

    job->set_fake_child_process(
        std::make_unique<FakeChildProcess>(kFakePid, 0, manager_->test_api()));

    return job;
  }

  int PackStatus(int status) { return __W_EXITCODE(status, 0); }
  int PackSignal(int signal) { return __W_EXITCODE(0, signal); }

  scoped_refptr<SessionManagerService> manager_;
  MockMetrics metrics_;
  SystemUtilsImpl utils_;
  base::FilePath aborted_browser_pid_path_;

  // These are bare pointers, not unique_ptrs, because we need to give them
  // to a SessionManagerService instance, but also be able to set expectations
  // on them after we hand them off.
  MockLivenessChecker* liveness_checker_;
  MockSessionManager* session_manager_impl_;

 private:
  bool must_destroy_mocks_;
  base::ScopedTempDir tmpdir_;
  brillo::BaseMessageLoop brillo_loop_;
};

// static
char SessionManagerProcessTest::kFakeEmail[] = "cmasone@whaaat.org";
const pid_t SessionManagerProcessTest::kFakePid = 4;
const int SessionManagerProcessTest::kExit = 1;

class HandleSuspendReadinessMethodMatcher
    : public ::testing::MatcherInterface<dbus::MethodCall*> {
 public:
  HandleSuspendReadinessMethodMatcher(int delay_id, int suspend_id)
      : delay_id_(delay_id), suspend_id_(suspend_id) {}

  bool MatchAndExplain(
      dbus::MethodCall* method_call,
      ::testing::MatchResultListener* listener) const override {
    // Make sure we've got the right kind of method call.
    if (method_call->GetInterface() != power_manager::kPowerManagerInterface) {
      *listener << "interface was " << method_call->GetInterface();
      return false;
    }

    if (method_call->GetMember() !=
        power_manager::kHandleSuspendReadinessMethod) {
      *listener << "method name was " << method_call->GetMember();
      return false;
    }

    // Check proto for correctness.
    power_manager::SuspendReadinessInfo info;
    dbus::MessageReader reader(method_call);
    reader.PopArrayOfBytesAsProto(&info);
    if (info.delay_id() != delay_id_) {
      *listener << "delay ID was " << info.delay_id();
      return false;
    }
    if (info.suspend_id() != suspend_id_) {
      *listener << "suspend ID was " << info.suspend_id();
      return false;
    }

    return true;
  }

  void DescribeTo(::std::ostream* os) const override {
    *os << "HandleSuspendReadiness method call with delay ID " << delay_id_
        << " and suspend ID " << suspend_id_;
  }

  void DescribeNegationTo(::std::ostream* os) const override {
    *os << "non-HandleSuspendReadiness method call, or method call "
        << "not with delay ID " << delay_id_ << " and suspend ID "
        << suspend_id_;
  }

 private:
  const int delay_id_;
  const int suspend_id_;
};

inline testing::Matcher<dbus::MethodCall*> HandleSuspendReadinessMethod(
    int delay_id, int suspend_id) {
  return MakeMatcher(
      new HandleSuspendReadinessMethodMatcher(delay_id, suspend_id));
}

class StopAllVmsMethodMatcher
    : public ::testing::MatcherInterface<dbus::MethodCall*> {
 public:
  StopAllVmsMethodMatcher() = default;

  bool MatchAndExplain(
      dbus::MethodCall* method_call,
      ::testing::MatchResultListener* listener) const override {
    // Make sure we've got the right kind of method call.
    if (method_call->GetInterface() !=
        vm_tools::concierge::kVmConciergeInterface) {
      *listener << "interface was " << method_call->GetInterface();
      return false;
    }

    if (method_call->GetMember() != vm_tools::concierge::kStopAllVmsMethod) {
      *listener << "method name was " << method_call->GetMember();
      return false;
    }

    return true;
  }

  void DescribeTo(::std::ostream* os) const override {
    *os << "StopAllVms method call";
  }

  void DescribeNegationTo(::std::ostream* os) const override {
    *os << "non-StopAllVms method call";
  }
};

inline testing::Matcher<dbus::MethodCall*> StopAllVmsMethod() {
  return MakeMatcher(new StopAllVmsMethodMatcher());
}

// Browser processes get correctly terminated.
TEST_F(SessionManagerProcessTest, CleanupBrowser) {
  FakeBrowserJob* job = CreateMockJobAndInitManager(false);
  EXPECT_CALL(*job, Kill(SIGTERM, _)).Times(1);
  EXPECT_CALL(*job, AbortAndKillAll(_)).Times(1);
  job->RunInBackground();
  manager_->test_api().CleanupChildrenBeforeExit();
}

// Gracefully shut down while the browser is running.
TEST_F(SessionManagerProcessTest, BrowserRunningShutdown) {
  FakeBrowserJob* job = CreateMockJobAndInitManager(false);

  ExpectLivenessChecking();
  ExpectShutdown();

  // Expect the job to be killed.
  EXPECT_CALL(*job, Kill(SIGTERM, _)).Times(1);
  EXPECT_CALL(*job, AbortAndKillAll(_)).Times(1);

  brillo::MessageLoop::current()->PostTask(
      FROM_HERE,
      base::Bind(&SessionManagerService::RunBrowser, manager_.get()));

  brillo::MessageLoop::current()->PostTask(
      FROM_HERE,
      base::Bind(&SessionManagerService::ScheduleShutdown, manager_.get()));

  ForceRunLoop();
}

// If the browser exits and asks to stop, the session manager
// should not restart it.
TEST_F(SessionManagerProcessTest, ChildExitFlagFileStop) {
  FakeBrowserJob* job = CreateMockJobAndInitManager(true);
  manager_->test_api().set_exit_on_child_done(true);  // or it'll run forever.
  ExpectLivenessChecking();

  EXPECT_CALL(*job, KillEverything(SIGKILL, _)).Times(AnyNumber());
  EXPECT_CALL(*job, ShouldStop()).WillOnce(Return(false));
  EXPECT_CALL(metrics_,
              SendSessionExitType(LoginMetrics::SessionExitType::NORMAL_EXIT))
      .Times(1);
  // Browser shutdown time is track when browser request to stop.
  EXPECT_CALL(metrics_, SendBrowserShutdownTime(_)).Times(1);
  job->set_should_run(false);

  EXPECT_CALL(*session_manager_impl_, ShouldEndSession(_))
      .WillOnce(Return(false));

  SimpleRunManager();
}

// A child that exits with a signal should get re-run.
TEST_F(SessionManagerProcessTest, BadExitChildOnSignal) {
  FakeBrowserJob* job = CreateMockJobAndInitManager(true);
  ExpectLivenessChecking();
  ExpectOneJobReRun(job, PackSignal(SIGILL));
  SimpleRunManager();
}

// A child that exits badly should get re-run.
TEST_F(SessionManagerProcessTest, BadExitChild) {
  FakeBrowserJob* job = CreateMockJobAndInitManager(true);
  ExpectLivenessChecking();
  ExpectOneJobReRun(job, PackSignal(kExit));
  SimpleRunManager();
}

// A child that exits cleanly should get re-run.
TEST_F(SessionManagerProcessTest, CleanExitChild) {
  FakeBrowserJob* job = CreateMockJobAndInitManager(true);
  ExpectLivenessChecking();
  ExpectOneJobReRun(job, PackSignal(0));
  SimpleRunManager();
}

// If the browser exits while the screen is locked, the session manager
// should exit.
TEST_F(SessionManagerProcessTest, LockedExit) {
  FakeBrowserJob* job = CreateMockJobAndInitManager(true);
  ExpectLivenessChecking();

  EXPECT_CALL(*job, KillEverything(SIGKILL, _)).Times(AnyNumber());
  EXPECT_CALL(*job, ShouldStop()).Times(0);

  EXPECT_CALL(*session_manager_impl_, ShouldEndSession(_))
      .WillOnce(Return(true));
  EXPECT_CALL(metrics_,
              SendSessionExitType(LoginMetrics::SessionExitType::NORMAL_EXIT))
      .Times(1);
  // Browser shutdown time is not tracked if browser does not request stop.
  EXPECT_CALL(metrics_, SendBrowserShutdownTime(_)).Times(0);

  SimpleRunManager();
}

// Liveness checking should be started and stopped along with the browser.
TEST_F(SessionManagerProcessTest, LivenessCheckingStartStop) {
  FakeBrowserJob* job = CreateMockJobAndInitManager(true);
  {
    Sequence start_stop;
    EXPECT_CALL(*liveness_checker_, Start()).Times(2);
    EXPECT_CALL(*liveness_checker_, Stop()).Times(AtLeast(1));
  }
  EXPECT_CALL(metrics_, SendBrowserShutdownTime(_)).Times(0);
  ExpectOneJobReRun(job, PackSignal(0));
  SimpleRunManager();
}

// If the child indicates it should be stopped, the session manager must honor.
TEST_F(SessionManagerProcessTest, MustStopChild) {
  FakeBrowserJob* job = CreateMockJobAndInitManager(true);
  ExpectLivenessChecking();
  EXPECT_CALL(*job, KillEverything(SIGKILL, _)).Times(AnyNumber());
  // ShouldStop returning true indicates a login crash loop.
  EXPECT_CALL(*job, ShouldStop()).WillOnce(Return(true));
  EXPECT_CALL(*session_manager_impl_, ShouldEndSession(_))
      .WillRepeatedly(Return(false));
  EXPECT_CALL(metrics_, SendSessionExitType(
                            LoginMetrics::SessionExitType::LOGIN_CRASH_LOOP))
      .Times(1);
  // Browser shutdown time is not tracked if browser does not request stop.
  EXPECT_CALL(metrics_, SendBrowserShutdownTime(_)).Times(0);

  SimpleRunManager();
}

TEST_F(SessionManagerProcessTest, TestWipeOnBadState) {
  CreateMockJobAndInitManager(true);

  EXPECT_CALL(*session_manager_impl_, Initialize()).WillOnce(Return(false));

  // Expect Powerwash to be triggered.
  EXPECT_CALL(*session_manager_impl_, InitiateDeviceWipe(_)).Times(1);
  EXPECT_CALL(*session_manager_impl_, Finalize()).Times(1);

  ASSERT_FALSE(manager_->test_api().InitializeImpl());
  ASSERT_EQ(SessionManagerService::MUST_WIPE_DEVICE, manager_->exit_code());
}

// When aborting the browser, the session manager should write the killed pid.
TEST_F(SessionManagerProcessTest, TestAbortedBrowserPidWritten) {
  FakeBrowserJob* job = CreateMockJobAndInitManager(false);
  EXPECT_CALL(*job, KillEverything(SIGKILL, _)).Times(AnyNumber());
  ASSERT_TRUE(job->RunInBackground());

  manager_->AbortBrowserForHang();
  ASSERT_TRUE(base::PathExists(aborted_browser_pid_path_));
  std::string read_pid_str;
  ASSERT_TRUE(base::ReadFileToString(aborted_browser_pid_path_, &read_pid_str));
  int read_pid = atoi(read_pid_str.c_str());
  EXPECT_EQ(kFakePid, read_pid);
}

// When the vm_concierge service is running, stop all vms when the session ends.
TEST_F(SessionManagerProcessTest, StopAllVms) {
  FakeBrowserJob* job = CreateMockJobAndInitManager(true);
  scoped_refptr<dbus::MockObjectProxy> vm_concierge_proxy(
      new dbus::MockObjectProxy(nullptr, "", dbus::ObjectPath("/fake/vm")));
  manager_->test_api().set_vm_concierge_proxy(vm_concierge_proxy.get());
  manager_->test_api().set_vm_concierge_available(true);

  EXPECT_CALL(*vm_concierge_proxy.get(), DoCallMethod(StopAllVmsMethod(), _, _))
      .Times(AtLeast(1));

  ExpectLivenessChecking();
  ExpectOneJobReRun(job, PackSignal(0));

  SimpleRunManager();
}

}  // namespace login_manager
