// Copyright (c) 2009 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 <string>
#include <vector>
#include <glib.h>
#include <pthread.h>
#include <gtest/gtest.h>
#include "update_engine/download_action.h"
#include "update_engine/install_action.h"
#include "update_engine/libcurl_http_fetcher.h"
#include "update_engine/mock_http_fetcher.h"
#include "update_engine/omaha_request_prep_action.h"
#include "update_engine/omaha_response_handler_action.h"
#include "update_engine/postinstall_runner_action.h"
#include "update_engine/set_bootable_flag_action.h"
#include "update_engine/test_utils.h"
#include "update_engine/update_check_action.h"
#include "update_engine/utils.h"

// The tests here integrate many Action objects together. This test that
// the objects work well together, whereas most other tests focus on a single
// action at a time.

namespace chromeos_update_engine {

using std::string;
using std::vector;

class IntegrationTest : public ::testing::Test { };

namespace {
const char* kTestDir = "/tmp/update_engine-integration-test";

class IntegrationTestProcessorDelegate : public ActionProcessorDelegate {
 public:
  IntegrationTestProcessorDelegate()
      : loop_(NULL), processing_done_called_(false) {}
  virtual ~IntegrationTestProcessorDelegate() {
    EXPECT_TRUE(processing_done_called_);
  }
  virtual void ProcessingDone(const ActionProcessor* processor, bool success) {
    processing_done_called_ = true;
    g_main_loop_quit(loop_);
  }

  virtual void ActionCompleted(ActionProcessor* processor,
                               AbstractAction* action,
                               bool success) {
    // make sure actions always succeed
    EXPECT_TRUE(success);

    // Swap in the device path for PostinstallRunnerAction with a loop device
    if (action->Type() == InstallAction::StaticType()) {
      InstallAction* install_action = static_cast<InstallAction*>(action);
      old_dev_ = install_action->GetOutputObject();
      string dev = GetUnusedLoopDevice();
      string cmd = string("losetup ") + dev + " " + kTestDir + "/dev2";
      EXPECT_EQ(0, system(cmd.c_str()));
      install_action->SetOutputObject(dev);
    } else if (action->Type() == PostinstallRunnerAction::StaticType()) {
      PostinstallRunnerAction* postinstall_runner_action =
          static_cast<PostinstallRunnerAction*>(action);
      string dev = postinstall_runner_action->GetOutputObject();
      EXPECT_EQ(0, system((string("losetup -d ") + dev).c_str()));
      postinstall_runner_action->SetOutputObject(old_dev_);
      old_dev_ = "";
    }
  }

  void set_loop(GMainLoop* loop) {
    loop_ = loop;
  }

 private:
  GMainLoop *loop_;
  bool processing_done_called_;

  // We have to change the dev for the PostinstallRunnerAction action.
  // Before that runs, we store the device here, and after it runs, we
  // restore it.
  // This is because we use a file, rather than a device, to install into,
  // but the PostinstallRunnerAction requires a real device. We set up a
  // loop device pointing to the file when necessary.
  string old_dev_;
};

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

}  // namespace {}

TEST(IntegrationTest, DISABLED_RunAsRootFullInstallTest) {
  ASSERT_EQ(0, getuid());
  GMainLoop *loop = g_main_loop_new(g_main_context_default(), FALSE);

  ActionProcessor processor;
  IntegrationTestProcessorDelegate delegate;
  delegate.set_loop(loop);
  processor.set_delegate(&delegate);

  // Actions:
  OmahaRequestPrepAction request_prep_action(false);
  UpdateCheckAction update_check_action(new LibcurlHttpFetcher);
  OmahaResponseHandlerAction response_handler_action;
  DownloadAction download_action(new LibcurlHttpFetcher);
  InstallAction install_action;
  PostinstallRunnerAction postinstall_runner_action;
  SetBootableFlagAction set_bootable_flag_action;

  // Enqueue the actions
  processor.EnqueueAction(&request_prep_action);
  processor.EnqueueAction(&update_check_action);
  processor.EnqueueAction(&response_handler_action);
  processor.EnqueueAction(&download_action);
  processor.EnqueueAction(&install_action);
  processor.EnqueueAction(&postinstall_runner_action);
  processor.EnqueueAction(&set_bootable_flag_action);

  // Bond them together
  BondActions(&request_prep_action, &update_check_action);
  BondActions(&update_check_action, &response_handler_action);
  BondActions(&response_handler_action, &download_action);
  BondActions(&download_action, &install_action);
  BondActions(&install_action, &postinstall_runner_action);
  BondActions(&postinstall_runner_action, &set_bootable_flag_action);

  // Set up filesystem to trick some of the actions
  ASSERT_EQ(0, System(string("rm -rf ") + kTestDir));
  ASSERT_EQ(0, system("rm -f /tmp/update_engine_test_postinst_out.txt"));
  ASSERT_EQ(0, System(string("mkdir -p ") + kTestDir + "/etc"));
  ASSERT_EQ(0, system((string("mkdir -p ") + kTestDir +
                       utils::kStatefulPartition +
                       "/etc").c_str()));
  ASSERT_TRUE(WriteFileString(string(kTestDir) + "/etc/lsb-release",
                              "GOOGLE_RELEASE=0.2.0.0\n"
                              "GOOGLE_TRACK=unittest-track"));
  ASSERT_EQ(0, System(string("touch ") + kTestDir + "/dev1"));
  ASSERT_EQ(0, System(string("touch ") + kTestDir + "/dev2"));
  ASSERT_TRUE(WriteFileVector(string(kTestDir) + "/dev", GenerateSampleMbr()));

  request_prep_action.set_root(kTestDir);
  response_handler_action.set_boot_device(string(kTestDir) + "/dev1");

  // Run the actions
  g_timeout_add(0, &TestStarter, &processor);
  g_main_loop_run(loop);
  g_main_loop_unref(loop);

  // Verify the results
  struct stat stbuf;
  ASSERT_EQ(0, lstat((string(kTestDir) + "/dev1").c_str(), &stbuf));
  EXPECT_EQ(0, stbuf.st_size);
  EXPECT_TRUE(S_ISREG(stbuf.st_mode));
  ASSERT_EQ(0, lstat((string(kTestDir) + "/dev2").c_str(), &stbuf));
  EXPECT_EQ(996147200, stbuf.st_size);
  EXPECT_TRUE(S_ISREG(stbuf.st_mode));
  ASSERT_EQ(0, lstat((string(kTestDir) + "/dev").c_str(), &stbuf));
  ASSERT_EQ(512, stbuf.st_size);
  EXPECT_TRUE(S_ISREG(stbuf.st_mode));
  vector<char> new_mbr;
  EXPECT_TRUE(utils::ReadFile((string(kTestDir) + "/dev").c_str(), &new_mbr));

  // Check bootable flag in MBR
  for (int i = 0; i < 4; i++) {
    char expected_flag = '\0';
    if (i == 1)
      expected_flag = 0x80;
    EXPECT_EQ(expected_flag, new_mbr[446 + 16 * i]);
  }
  // Check MBR signature
  EXPECT_EQ(static_cast<char>(0x55), new_mbr[510]);
  EXPECT_EQ(static_cast<char>(0xaa), new_mbr[511]);

  ASSERT_EQ(0, lstat("/tmp/update_engine_test_postinst_out.txt", &stbuf));
  EXPECT_TRUE(S_ISREG(stbuf.st_mode));
  string file_data;
  EXPECT_TRUE(utils::ReadFileToString(
      "/tmp/update_engine_test_postinst_out.txt",
      &file_data));
  EXPECT_EQ("POSTINST_DONE\n", file_data);

  // cleanup
  ASSERT_EQ(0, System(string("rm -rf ") + kTestDir));
  ASSERT_EQ(0, system("rm -f /tmp/update_engine_test_postinst_out.txt"));
}

}  // namespace chromeos_update_engine
