// 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() 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 kDummyPid;
  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>(
        kDummyPid, exit_status, manager_->test_api()));
  }

  void InitManager(std::unique_ptr<BrowserJobInterface> job) {
    manager_ =
        new SessionManagerService(std::move(job), getuid(), base::nullopt, 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>(kDummyPid, 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_;

  DISALLOW_COPY_AND_ASSIGN(SessionManagerProcessTest);
};

// static
char SessionManagerProcessTest::kFakeEmail[] = "cmasone@whaaat.org";
const pid_t SessionManagerProcessTest::kDummyPid = 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, WaitAndAbort(_)).Times(1);
  job->RunInBackground();
  manager_->test_api().CleanupChildren(3);
}

// 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, WaitAndAbort(_)).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_->AbortBrowser(SIGKILL, "");
  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(kDummyPid, 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
