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

#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <memory>
#include <string>
#include <vector>

#include <base/files/file_util.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <gtest/gtest.h>

#include "update_engine/constants.h"
#include "update_engine/test_utils.h"
#include "update_engine/utils.h"

using chromeos_update_engine::test_utils::System;
using chromeos_update_engine::test_utils::WriteFileString;
using std::string;
using std::unique_ptr;
using std::vector;

namespace chromeos_update_engine {

namespace {
gboolean StartProcessorInRunLoop(gpointer data) {
  ActionProcessor *processor = reinterpret_cast<ActionProcessor*>(data);
  processor->StartProcessing();
  return FALSE;
}
}  // namespace

class PostinstallRunnerActionTest : public ::testing::Test {
 public:
  // DoTest with various combinations of do_losetup, err_code and
  // powerwash_required.
  void DoTest(bool do_losetup, int err_code, bool powerwash_required);

 private:
  static const char* kImageMountPointTemplate;
};

class PostinstActionProcessorDelegate : public ActionProcessorDelegate {
 public:
  PostinstActionProcessorDelegate()
      : loop_(nullptr),
        code_(ErrorCode::kError),
        code_set_(false) {}
  void ProcessingDone(const ActionProcessor* processor,
                      ErrorCode code) {
    ASSERT_TRUE(loop_);
    g_main_loop_quit(loop_);
  }
  void ActionCompleted(ActionProcessor* processor,
                       AbstractAction* action,
                       ErrorCode code) {
    if (action->Type() == PostinstallRunnerAction::StaticType()) {
      code_ = code;
      code_set_ = true;
    }
  }
  GMainLoop* loop_;
  ErrorCode code_;
  bool code_set_;
};

TEST_F(PostinstallRunnerActionTest, RunAsRootSimpleTest) {
  ASSERT_EQ(0, getuid());
  DoTest(true, 0, false);
}

TEST_F(PostinstallRunnerActionTest, RunAsRootPowerwashRequiredTest) {
  ASSERT_EQ(0, getuid());
  DoTest(true, 0, true);
}

TEST_F(PostinstallRunnerActionTest, RunAsRootCantMountTest) {
  ASSERT_EQ(0, getuid());
  DoTest(false, 0, true);
}

TEST_F(PostinstallRunnerActionTest, RunAsRootErrScriptTest) {
  ASSERT_EQ(0, getuid());
  DoTest(true, 1, false);
}

TEST_F(PostinstallRunnerActionTest, RunAsRootFirmwareBErrScriptTest) {
  ASSERT_EQ(0, getuid());
  DoTest(true, 3, false);
}

TEST_F(PostinstallRunnerActionTest, RunAsRootFirmwareROErrScriptTest) {
  ASSERT_EQ(0, getuid());
  DoTest(true, 4, false);
}

const char* PostinstallRunnerActionTest::kImageMountPointTemplate =
    "au_destination-XXXXXX";

void PostinstallRunnerActionTest::DoTest(
    bool do_losetup,
    int err_code,
    bool powerwash_required) {
  ASSERT_EQ(0, getuid()) << "Run me as root. Ideally don't run other tests "
                         << "as root, tho.";
  // True if the post-install action is expected to succeed.
  bool should_succeed = do_losetup && !err_code;

  string orig_cwd;
  {
    vector<char> buf(1000);
    ASSERT_EQ(buf.data(), getcwd(buf.data(), buf.size()));
    orig_cwd = string(buf.data(), strlen(buf.data()));
  }

  // Create a unique named working directory and chdir into it.
  string cwd;
  ASSERT_TRUE(utils::MakeTempDirectory(
          "postinstall_runner_action_unittest-XXXXXX",
          &cwd));
  ASSERT_EQ(0, test_utils::Chdir(cwd));

  // Create a 10MiB sparse file to be used as image; format it as ext2.
  ASSERT_EQ(0, System(
          "dd if=/dev/zero of=image.dat seek=10485759 bs=1 count=1"));
  ASSERT_EQ(0, System("mkfs.ext2 -F image.dat"));

  // Create a uniquely named image mount point, mount the image.
  ASSERT_EQ(0, System(string("mkdir -p ") + kStatefulPartition));
  string mountpoint;
  ASSERT_TRUE(utils::MakeTempDirectory(
          string(kStatefulPartition) + "/" + kImageMountPointTemplate,
          &mountpoint));
  ASSERT_EQ(0, System(string("mount -o loop image.dat ") + mountpoint));

  // Generate a fake postinst script inside the image.
  string script = (err_code ?
                   base::StringPrintf("#!/bin/bash\nexit %d", err_code) :
                   base::StringPrintf(
                       "#!/bin/bash\n"
                       "mount | grep au_postint_mount | grep ext2\n"
                       "if [ $? -eq 0 ]; then\n"
                       "  touch %s/postinst_called\n"
                       "fi\n",
                       cwd.c_str()));
  const string script_file_name = mountpoint + "/postinst";
  ASSERT_TRUE(WriteFileString(script_file_name, script));
  ASSERT_EQ(0, System(string("chmod a+x ") + script_file_name));

  // Unmount image; do not remove the uniquely named directory as it will be
  // reused during the test.
  ASSERT_TRUE(utils::UnmountFilesystem(mountpoint));

  // get a loop device we can use for the install device
  string dev = "/dev/null";

  unique_ptr<test_utils::ScopedLoopbackDeviceBinder> loop_releaser;
  if (do_losetup) {
    loop_releaser.reset(new test_utils::ScopedLoopbackDeviceBinder(
            cwd + "/image.dat", &dev));
  }

  // We use a test-specific powerwash marker file, to avoid race conditions.
  string powerwash_marker_file = mountpoint + "/factory_install_reset";
  LOG(INFO) << ">>> powerwash_marker_file=" << powerwash_marker_file;

  ActionProcessor processor;
  ObjectFeederAction<InstallPlan> feeder_action;
  InstallPlan install_plan;
  install_plan.install_path = dev;
  install_plan.download_url = "http://devserver:8080/update";
  install_plan.powerwash_required = powerwash_required;
  feeder_action.set_obj(install_plan);
  PostinstallRunnerAction runner_action(powerwash_marker_file.c_str());
  BondActions(&feeder_action, &runner_action);
  ObjectCollectorAction<InstallPlan> collector_action;
  BondActions(&runner_action, &collector_action);
  PostinstActionProcessorDelegate delegate;
  processor.EnqueueAction(&feeder_action);
  processor.EnqueueAction(&runner_action);
  processor.EnqueueAction(&collector_action);
  processor.set_delegate(&delegate);

  GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
  delegate.loop_ = loop;
  g_timeout_add(0, &StartProcessorInRunLoop, &processor);
  g_main_loop_run(loop);
  g_main_loop_unref(loop);
  ASSERT_FALSE(processor.IsRunning());

  EXPECT_TRUE(delegate.code_set_);
  EXPECT_EQ(should_succeed, delegate.code_ == ErrorCode::kSuccess);
  EXPECT_EQ(should_succeed, !collector_action.object().install_path.empty());
  if (should_succeed)
    EXPECT_TRUE(install_plan == collector_action.object());

  const base::FilePath kPowerwashMarkerPath(powerwash_marker_file);
  string actual_cmd;
  if (should_succeed && powerwash_required) {
    EXPECT_TRUE(base::ReadFileToString(kPowerwashMarkerPath, &actual_cmd));
    EXPECT_EQ(kPowerwashCommand, actual_cmd);
  } else {
    EXPECT_FALSE(
        base::ReadFileToString(kPowerwashMarkerPath, &actual_cmd));
  }

  if (err_code == 2)
    EXPECT_EQ(ErrorCode::kPostinstallBootedFromFirmwareB, delegate.code_);

  struct stat stbuf;
  int rc = lstat((string(cwd) + "/postinst_called").c_str(), &stbuf);
  if (should_succeed)
    ASSERT_EQ(0, rc);
  else
    ASSERT_LT(rc, 0);

  if (do_losetup) {
    loop_releaser.reset(nullptr);
  }

  // Remove unique stateful directory.
  ASSERT_EQ(0, System(string("rm -fr ") + mountpoint));

  // Remove the temporary work directory.
  ASSERT_EQ(0, test_utils::Chdir(orig_cwd));
  ASSERT_EQ(0, System(string("rm -fr ") + cwd));
}

// Death tests don't seem to be working on Hardy
TEST_F(PostinstallRunnerActionTest, DISABLED_RunAsRootDeathTest) {
  ASSERT_EQ(0, getuid());
  PostinstallRunnerAction runner_action;
  ASSERT_DEATH({ runner_action.TerminateProcessing(); },
               "postinstall_runner_action.h:.*] Check failed");
}

}  // namespace chromeos_update_engine
