// Copyright (c) 2010 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_action.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/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,
                              ActionExitCode code) {
    processing_done_called_ = true;
    g_main_loop_quit(loop_);
  }

  virtual void ActionCompleted(ActionProcessor* processor,
                               AbstractAction* action,
                               ActionExitCode code) {
    // make sure actions always succeed
    EXPECT_EQ(kActionCodeSuccess, code);

    // 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;
      BindToUnusedDevice(kTestDir + "/dev2", &dev);
      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);
  OmahaRequestAction update_check_action(NULL, 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::ReadFile(
      "/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
