// 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/constants.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 +
                       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
