Add recovery test tool 61/235161/13
authorIlho Kim <ilho159.kim@samsung.com>
Tue, 2 Jun 2020 02:09:44 +0000 (11:09 +0900)
committerilho kim <ilho159.kim@samsung.com>
Tue, 11 Aug 2020 01:51:58 +0000 (01:51 +0000)
Change-Id: I1693e591d771d8118ee142476774be1dfc33a861
Signed-off-by: Ilho Kim <ilho159.kim@samsung.com>
16 files changed:
CMakeLists.txt
packaging/unified-installer-tests.manifest
test/smoke_test/CMakeLists.txt
test/smoke_test/smoke_test_helper.cc
test/smoke_test/smoke_utils.cc
test/smoke_test/smoke_utils.h
test/smoke_test/test_samples/smoke/RecoveryHybridPkg.delta [new file with mode: 0644]
test/smoke_test/test_samples/smoke/RecoveryHybridPkg.wgt [new file with mode: 0644]
test/smoke_test/test_samples/smoke/RecoveryHybridPkg2.wgt [new file with mode: 0644]
test/smoke_test/test_samples/smoke/RecoveryTpkPkg.delta [new file with mode: 0644]
test/smoke_test/test_samples/smoke/RecoveryTpkPkg.tpk [new file with mode: 0644]
test/smoke_test/test_samples/smoke/RecoveryTpkPkg2.tpk [new file with mode: 0644]
test/smoke_test/test_samples/smoke/RecoveryWgtPkg.delta [new file with mode: 0644]
test/smoke_test/test_samples/smoke/RecoveryWgtPkg.wgt [new file with mode: 0644]
test/smoke_test/test_samples/smoke/RecoveryWgtPkg2.wgt [new file with mode: 0644]
test/smoke_test/unified_recovery_test.cc [new file with mode: 0644]

index 036ee73804071785f6566510d4ef4030bbe4f080..829cf9f3de6c928111f3a099acc79c8ccfafa262 100644 (file)
@@ -30,6 +30,7 @@ SET(TARGET_LIBNAME_UNIFIED "unified-installer")
 SET(TARGET_SMOKE_TEST "smoke-test")
 SET(TARGET_SMOKE_TEST_HELPER "smoke-test-helper")
 SET(TARGET_DEPENDENCY_CHECKER_TEST "dependency-checker-test")
+SET(TARGET_RECOVERY_TEST "unified-recovery-test")
 
 ENABLE_TESTING()
 SET(TARGET_UNIFIED_INSTALLER_UNIT_TEST "unified-installer-unit-test")
index 523984121b9e2ba0b3c12e49b4d26b77229d4713..a4e70b8e0950808781be19dd6b13e4785239dd95 100644 (file)
@@ -5,5 +5,6 @@
         <assign>
                 <filesystem path="/usr/bin/unified-installer-ut/smoke-test" exec_label="System" />
                 <filesystem path="/usr/bin/unified-installer-ut/smoke-test-helper" exec_label="System" />
+                <filesystem path="/usr/bin/unified-installer-ut/unified-recovery-test" exec_label="System" />
         </assign>
 </manifest>
index 891e4bcd75e9cca8ce387844d0b2508505086247..3fe25232510a45bba98333702becaa54de949d9e 100644 (file)
@@ -12,6 +12,14 @@ ADD_EXECUTABLE(${TARGET_SMOKE_TEST}
 
 ADD_EXECUTABLE(${TARGET_SMOKE_TEST_HELPER}
   smoke_test_helper.cc
+  smoke_utils.h
+  smoke_utils.cc
+)
+
+ADD_EXECUTABLE(${TARGET_RECOVERY_TEST}
+  unified_recovery_test.cc
+  smoke_utils.h
+  smoke_utils.cc
 )
 
 ADD_EXECUTABLE(${TARGET_DEPENDENCY_CHECKER_TEST}
@@ -23,6 +31,7 @@ ADD_EXECUTABLE(${TARGET_DEPENDENCY_CHECKER_TEST}
 TARGET_INCLUDE_DIRECTORIES(${TARGET_SMOKE_TEST} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../)
 TARGET_INCLUDE_DIRECTORIES(${TARGET_SMOKE_TEST_HELPER} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../)
 TARGET_INCLUDE_DIRECTORIES(${TARGET_DEPENDENCY_CHECKER_TEST} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../)
+TARGET_INCLUDE_DIRECTORIES(${TARGET_RECOVERY_TEST} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../)
 
 INSTALL(DIRECTORY test_samples/ DESTINATION ${SHAREDIR}/${DESTINATION_DIR}/test_samples)
 
@@ -32,6 +41,16 @@ APPLY_PKG_CONFIG(${TARGET_SMOKE_TEST} PUBLIC
   GUM_DEPS
 )
 
+APPLY_PKG_CONFIG(${TARGET_RECOVERY_TEST} PUBLIC
+  Boost
+  GMOCK_DEPS
+  GUM_DEPS
+)
+
+APPLY_PKG_CONFIG(${TARGET_SMOKE_TEST_HELPER} PUBLIC
+  Boost
+)
+
 APPLY_PKG_CONFIG(${TARGET_DEPENDENCY_CHECKER_TEST} PUBLIC
   Boost
   GMOCK_DEPS
@@ -43,7 +62,9 @@ APPLY_PKG_CONFIG(${TARGET_DEPENDENCY_CHECKER_TEST} PUBLIC
 TARGET_LINK_LIBRARIES(${TARGET_SMOKE_TEST} PRIVATE ${TARGET_LIBNAME_UNIFIED} ${GTEST_MAIN_LIBRARIES} ${TARGET_SMOKE_UTILS} ${TARGET_TPK_SMOKE_UTILS} ${TARGET_WGT_SMOKE_UTILS})
 TARGET_LINK_LIBRARIES(${TARGET_SMOKE_TEST_HELPER} PRIVATE ${TARGET_LIBNAME_UNIFIED} ${TARGET_TPK_SMOKE_UTILS} ${TARGET_WGT_SMOKE_UTILS})
 TARGET_LINK_LIBRARIES(${TARGET_DEPENDENCY_CHECKER_TEST} PRIVATE ${TARGET_LIBNAME_UNIFIED} ${GTEST_MAIN_LIBRARIES} ${TARGET_SMOKE_UTILS})
+TARGET_LINK_LIBRARIES(${TARGET_RECOVERY_TEST} PRIVATE ${TARGET_LIBNAME_UNIFIED} ${GTEST_MAIN_LIBRARIES} ${TARGET_SMOKE_UTILS} ${TARGET_TPK_SMOKE_UTILS} ${TARGET_WGT_SMOKE_UTILS})
 
 INSTALL(TARGETS ${TARGET_SMOKE_TEST} DESTINATION ${BINDIR}/${DESTINATION_DIR})
 INSTALL(TARGETS ${TARGET_SMOKE_TEST_HELPER} DESTINATION ${BINDIR}/${DESTINATION_DIR})
 INSTALL(TARGETS ${TARGET_DEPENDENCY_CHECKER_TEST} DESTINATION ${BINDIR}/${DESTINATION_DIR})
+INSTALL(TARGETS ${TARGET_RECOVERY_TEST} DESTINATION ${BINDIR}/${DESTINATION_DIR})
index 4dfc1861d5ec41528cc2a64df0c5e8cb98aebc02..f9ea7e77771359eb16361ee588e1d370c233e1bc 100644 (file)
@@ -15,6 +15,8 @@
 #include <memory>
 #include <string>
 
+#include "smoke_test/smoke_utils.h"
+
 namespace ci = common_installer;
 
 namespace {
@@ -58,15 +60,60 @@ class CrashInstallerFactory : public ci::InstallerFactory {
   }
 };
 
+class RemovePluginInstallerFactory : public ci::InstallerFactory {
+ public:
+  std::unique_ptr<ci::AppInstaller> CreateInstaller(ci::PkgMgrPtr pkgmgr,
+      int idx) override {
+    std::string type =
+        smoke_test::GetPkgType(pkgmgr->GetRequestInfo(idx), pkgmgr->GetUid());
+    std::unique_ptr<ci::AppInstaller> installer;
+    if (type == "tpk") {
+      tpk::TpkAppQueryInterface* tpk_aqi = new tpk::TpkAppQueryInterface();
+      pkgmgr->AddAppQueryInterface(idx, tpk_aqi);
+      installer.reset(
+          new smoke_test::TpkInstallerWithoutPasrserPlugins(pkgmgr));
+    } else {
+      wgt::WgtAppQueryInterface* wgt_aqi = new wgt::WgtAppQueryInterface();
+      pkgmgr->AddAppQueryInterface(idx, wgt_aqi);
+      if (wgt_aqi->IsHybridApplication(pkgmgr->GetRequestInfo(idx),
+          pkgmgr->GetUid())) {
+        installer.reset(
+            new smoke_test::HybridInstallerWithoutPasrserPlugins(pkgmgr));
+      } else {
+        installer.reset(
+            new smoke_test::WgtInstallerWithoutPasrserPlugins(pkgmgr));
+      }
+    }
+    installer->SetIndex(idx);
+    return installer;
+  }
+};
+
 int main(int argc, char** argv) {
+  int backend_argc = argc;
+  bool remove_plugins = false;
+
+  if (!strcmp(argv[backend_argc-1], "-remove_plugin_steps")) {
+    backend_argc--;
+    remove_plugins = true;
+    LOG(DEBUG) << "Remove parser plugins steps";
+  }
+
   ci::PkgmgrInstaller pkgmgr_installer;
   try {
-    auto pkgmgr = ci::PkgMgrInterface::Create(argc, argv, &pkgmgr_installer);
-
-    ci::InstallerRunner runner(
-        std::make_unique<CrashInstallerFactory>(), pkgmgr);
-    ci::AppInstaller::Result result = runner.Run();
+    ci::AppInstaller::Result result;
+    auto pkgmgr = ci::PkgMgrInterface::Create(
+        backend_argc, argv, &pkgmgr_installer);
 
+    if (remove_plugins) {
+      ci::InstallerRunner runner(
+          std::make_unique<RemovePluginInstallerFactory>(), pkgmgr);
+      result = runner.Run();
+    } else {
+      ci::InstallerRunner runner(
+          std::make_unique<CrashInstallerFactory>(), pkgmgr);
+      result = runner.Run();
+    }
     return (result == ci::AppInstaller::Result::OK) ? 0 : 1;
   } catch(...) {
     LOG(ERROR) << "Exception occured";
index 49221f8a3838219716c50bc93359d5aeb1e3665c..37349dc5e186a843cfe9d11ec200c9d7a5d95d33 100644 (file)
 
 #include <map>
 #include <string>
+#include <vector>
 
 namespace bf = boost::filesystem;
 namespace ci = common_installer;
 
 namespace {
 
+const char kRecoveryFilePattern[] = "^(.*)-recovery-(.){6}$";
+
 std::map<const char*, const char*> kTypeMap = {
   {"res/wgt/config.xml", "wgt"},
   {"config.xml", "wgt"},
@@ -57,14 +60,11 @@ std::string GetPkgTypeFromRecoveryFile(const std::string& path) {
   return {};
 }
 
-std::string GetPkgType(const std::string& pkginfo, uid_t uid) {
-  std::string type = GetPkgTypeFromPkgid(pkginfo, uid);
-  if (type.empty())
-    type = GetPkgTypeFromPath(pkginfo);
-  // recovery file
-  if (type.empty())
-    type = GetPkgTypeFromRecoveryFile(pkginfo);
-  return type;
+std::string TruncateNewLine(const char* data) {
+  int length = strlen(data);
+  if (data[length - 1] == '\n')
+      --length;
+  return std::string(data, length);
 }
 
 }  // namespace
@@ -145,7 +145,54 @@ UnifiedBackendInterface::CreateInstaller(ci::PkgMgrPtr pkgmgr) const {
 UnifiedBackendInterface::AppInstallerPtr
 UnifiedBackendInterface::CreateFailExpectedInstaller(
     ci::PkgMgrPtr pkgmgr, int fail_at) const {
-  return factory_->CreateFailExpectedInstaller(0, pkgmgr, fail_at);;
+  return factory_->CreateFailExpectedInstaller(0, pkgmgr, fail_at);
+}
+
+UnifiedRecoveryInfo::UnifiedRecoveryInfo(bf::path path) : path_(path) {
+}
+
+bool UnifiedRecoveryInfo::Init() {
+  FILE* handle = fopen(path_.c_str(), "r");
+  if (!handle) {
+    LOG(ERROR) << "Failed to open recovery file :" << path_.string();
+    return false;
+  }
+
+  std::array<char, 200> data;
+  data[0] = '\0';
+  while (fgets(data.data(), data.size(), handle)) {
+    std::string line_data = TruncateNewLine(data.data());
+    if (line_data == "cleanup") {
+      clean_up_ = true;
+      break;
+    }
+
+    if (!boost::filesystem::exists(line_data))
+      continue;
+
+    recovery_files_.emplace_back(line_data);
+  }
+  fclose(handle);
+
+  return true;
+}
+
+bool UnifiedRecoveryInfo::GetCleanUp() const {
+  return clean_up_;
+}
+
+const std::vector<bf::path> UnifiedRecoveryInfo::GetRecoveryFiles() const {
+  return recovery_files_;
+}
+
+std::string GetPkgType(const std::string& pkginfo, uid_t uid) {
+  std::string type = GetPkgTypeFromPkgid(pkginfo, uid);
+  if (type.empty())
+    type = GetPkgTypeFromPath(pkginfo);
+  // recovery file
+  if (type.empty())
+    type = GetPkgTypeFromRecoveryFile(pkginfo);
+  return type;
 }
 
 }  // namespace smoke_test
index 3e2efd5f01b96318d33858a1240b642426de0661..b8795dc1d3f4b74eb307442d066a696da5b3f7c1 100644 (file)
 #include <unit_tests/common/smoke_utils.h>
 #include <unit_tests/tpk_smoke_utils.h>
 
+#include <string>
+#include <vector>
+
+#include <boost/filesystem/path.hpp>
+
+namespace bf = boost::filesystem;
+
 namespace smoke_test {
 
 class UnifiedSmokeInstallerFactory : public SmokeInstallerFactory {
@@ -31,6 +38,30 @@ class UnifiedBackendInterface : public BackendInterface {
       common_installer::PkgMgrPtr pkgmgr, int fail_at) const override;
 };
 
+class UnifiedSmokeTestHelperRunner : public SmokeTestHelperRunner {
+ private:
+  common_installer::Subprocess CreateSubprocess() const {
+    return common_installer::Subprocess(
+        "/usr/bin/unified-installer-ut/smoke-test-helper");
+  }
+};
+
+class UnifiedRecoveryInfo {
+ public:
+  explicit UnifiedRecoveryInfo(bf::path path);
+
+  bool Init();
+  bool GetCleanUp() const;
+  const std::vector<bf::path> GetRecoveryFiles() const;
+
+ private:
+  std::vector<bf::path> recovery_files_;
+  bf::path path_;
+  bool clean_up_ = false;
+};
+
+std::string GetPkgType(const std::string& pkginfo, uid_t uid);
+
 }  // namespace smoke_test
 
 #endif  // TEST_SMOKE_TEST_SMOKE_UTILS_H_
diff --git a/test/smoke_test/test_samples/smoke/RecoveryHybridPkg.delta b/test/smoke_test/test_samples/smoke/RecoveryHybridPkg.delta
new file mode 100644 (file)
index 0000000..00c79ed
Binary files /dev/null and b/test/smoke_test/test_samples/smoke/RecoveryHybridPkg.delta differ
diff --git a/test/smoke_test/test_samples/smoke/RecoveryHybridPkg.wgt b/test/smoke_test/test_samples/smoke/RecoveryHybridPkg.wgt
new file mode 100644 (file)
index 0000000..402fed3
Binary files /dev/null and b/test/smoke_test/test_samples/smoke/RecoveryHybridPkg.wgt differ
diff --git a/test/smoke_test/test_samples/smoke/RecoveryHybridPkg2.wgt b/test/smoke_test/test_samples/smoke/RecoveryHybridPkg2.wgt
new file mode 100644 (file)
index 0000000..9c319b6
Binary files /dev/null and b/test/smoke_test/test_samples/smoke/RecoveryHybridPkg2.wgt differ
diff --git a/test/smoke_test/test_samples/smoke/RecoveryTpkPkg.delta b/test/smoke_test/test_samples/smoke/RecoveryTpkPkg.delta
new file mode 100644 (file)
index 0000000..0f4709e
Binary files /dev/null and b/test/smoke_test/test_samples/smoke/RecoveryTpkPkg.delta differ
diff --git a/test/smoke_test/test_samples/smoke/RecoveryTpkPkg.tpk b/test/smoke_test/test_samples/smoke/RecoveryTpkPkg.tpk
new file mode 100644 (file)
index 0000000..82c2fc3
Binary files /dev/null and b/test/smoke_test/test_samples/smoke/RecoveryTpkPkg.tpk differ
diff --git a/test/smoke_test/test_samples/smoke/RecoveryTpkPkg2.tpk b/test/smoke_test/test_samples/smoke/RecoveryTpkPkg2.tpk
new file mode 100644 (file)
index 0000000..cae1de2
Binary files /dev/null and b/test/smoke_test/test_samples/smoke/RecoveryTpkPkg2.tpk differ
diff --git a/test/smoke_test/test_samples/smoke/RecoveryWgtPkg.delta b/test/smoke_test/test_samples/smoke/RecoveryWgtPkg.delta
new file mode 100644 (file)
index 0000000..84adacd
Binary files /dev/null and b/test/smoke_test/test_samples/smoke/RecoveryWgtPkg.delta differ
diff --git a/test/smoke_test/test_samples/smoke/RecoveryWgtPkg.wgt b/test/smoke_test/test_samples/smoke/RecoveryWgtPkg.wgt
new file mode 100644 (file)
index 0000000..e7bbdbf
Binary files /dev/null and b/test/smoke_test/test_samples/smoke/RecoveryWgtPkg.wgt differ
diff --git a/test/smoke_test/test_samples/smoke/RecoveryWgtPkg2.wgt b/test/smoke_test/test_samples/smoke/RecoveryWgtPkg2.wgt
new file mode 100644 (file)
index 0000000..ed62588
Binary files /dev/null and b/test/smoke_test/test_samples/smoke/RecoveryWgtPkg2.wgt differ
diff --git a/test/smoke_test/unified_recovery_test.cc b/test/smoke_test/unified_recovery_test.cc
new file mode 100644 (file)
index 0000000..ce466c3
--- /dev/null
@@ -0,0 +1,690 @@
+// Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache-2.0 license that can be
+// found in the LICENSE file.
+
+#include <boost/exception/diagnostic_information.hpp>
+#include <boost/program_options.hpp>
+
+#include <common/utils/subprocess.h>
+#include <unit_tests/common/smoke_utils.h>
+
+#include <gtest/gtest.h>
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "smoke_test/smoke_utils.h"
+
+namespace bf = boost::filesystem;
+namespace bpo = boost::program_options;
+namespace ci = common_installer;
+
+enum class ReqType : int {
+  UNKNOWN_REQ,
+  INSTALL_REQ,
+  UPDATE_REQ,
+  DELTA_REQ,
+  MOUNT_INSTALL_REQ,
+  MOUNT_UPDATE_REQ,
+};
+
+enum class BackupType : int {
+  MOVE,
+  COPY_AND_REMOVE,
+};
+
+std::map<ReqType, std::string> install_req_filter = {
+  { ReqType::INSTALL_REQ, "SmokeTest.RecoveryMode_Multi_Installation" },
+  { ReqType::UPDATE_REQ, "SmokeTest.RecoveryMode_Multi_Update" },
+  { ReqType::DELTA_REQ, "SmokeTest.RecoveryMode_ForDelta" },
+  { ReqType::MOUNT_INSTALL_REQ, "SmokeTest.RecoveryMode_ForMountInstall" },
+  { ReqType::MOUNT_UPDATE_REQ, "SmokeTest.RecoveryMode_ForMountUpdate" }
+};
+
+int delay = 1000000;
+int interval = 500000;
+int test_count = 0;
+
+namespace smoke_test {
+
+class SmokeEnvironment : public testing::Environment {
+ public:
+  explicit SmokeEnvironment(ci::RequestMode mode, bool no_backup,
+      BackupType backup_type) :
+          request_mode_(mode), no_backup_(no_backup),
+              backup_type_(backup_type) {
+  }
+
+  void SetUp() override {
+    if (request_mode_ == ci::RequestMode::USER)
+      ASSERT_TRUE(AddTestUser(&test_user));
+    if (no_backup_)
+      return;
+    backups_ = SetupBackupDirectories(test_user.uid);
+    if (backup_type_ == BackupType::MOVE) {
+      for (auto& path : backups_)
+        ASSERT_TRUE(BackupPath(path));
+    } else if (backup_type_ == BackupType::COPY_AND_REMOVE) {
+      for (auto& path : backups_)
+        ASSERT_TRUE(BackupPathCopyAndRemove(path));
+    }
+  }
+
+  void TearDown() override {
+    test_count++;
+    if (request_mode_ == ci::RequestMode::USER)
+      ASSERT_TRUE(DeleteTestUser());
+    if (no_backup_)
+      return;
+    if (backup_type_ == BackupType::MOVE) {
+      for (auto& path : backups_)
+        ASSERT_TRUE(RestorePath(path));
+    } else if (backup_type_ == BackupType::COPY_AND_REMOVE) {
+      for (auto& path : backups_)
+        ASSERT_TRUE(RestorePathCopyAndRemove(path));
+    }
+  }
+
+  User test_user;
+
+ private:
+  ci::RequestMode request_mode_;
+  std::vector<bf::path> backups_;
+  bool no_backup_;
+  BackupType backup_type_;
+};
+
+}  // namespace smoke_test
+
+namespace {
+
+smoke_test::SmokeEnvironment *env = nullptr;
+
+void signalHandler(int signum) {
+  env->TearDown();
+  exit(signum);
+}
+
+}  // namespace
+
+namespace smoke_test {
+
+const bf::path kUnifiedSmokePackagesDirectory =
+    "/usr/share/unified-installer-ut/test_samples/smoke/";
+
+class SmokeTest : public testing::Test {
+ public:
+  SmokeTest() : params{PackageType::TPK, false} {
+    params.test_user.uid = env->test_user.uid;
+    params.test_user.gid = env->test_user.gid;
+  }
+
+ protected:
+  UnifiedSmokeTestHelperRunner backend;
+  TestParameters params;
+};
+
+TEST_F(SmokeTest, RecoveryMode_Multi_Installation) {
+  RemoveAllRecoveryFiles("/unified-recovery", params.test_user.uid);
+  RemoveAllRecoveryFiles("/tpk-recovery", params.test_user.uid);
+  RemoveAllRecoveryFiles("/wgt-recovery", params.test_user.uid);
+
+  std::vector<bf::path> paths = {
+      kUnifiedSmokePackagesDirectory / "RecoveryTpkPkg.tpk",
+      kUnifiedSmokePackagesDirectory / "RecoveryWgtPkg.wgt",
+      kUnifiedSmokePackagesDirectory / "RecoveryHybridPkg.wgt" };
+  std::vector<std::string> pkgids =
+      { "smokerec01", "smokerec02", "smokerec03" };
+  std::vector<Apps> app_infos = {
+      { {"smokerec01.RecoveryTpk", "native"} },
+      { {"smokerec02.RecoveryWgt", "smokerec02.RecoveryWgt"} },
+      {
+        {"smokerec03.RecoveryHybridUI", "smokerec03.RecoveryHybridUI"},
+        {"smokerec03.recoveryhybridservice", "recoveryhybridservice"},
+      }
+  };
+
+  int wait_time = delay + interval * test_count;
+  SmokeTestHelperRunner::Result ret = backend.InstallPkgsWithSubprocessAndKill(
+      paths, params.test_user.uid, wait_time);
+  if (ret == SmokeTestHelperRunner::Result::SUCCESS) {
+    std::cout << "install finished before process killed" << std::endl;
+    return;
+  }
+  ASSERT_EQ(ret, SmokeTestHelperRunner::Result::KILLED);
+
+  bf::path recovery_file = FindRecoveryFile("/unified-recovery",
+      params.test_user.uid);
+  if (recovery_file.empty()) {
+    std::cout << "recovery file dosen't exist, "
+                 "this test is skipped" << std::endl;
+    return;
+  }
+
+  UnifiedRecoveryInfo recovery_info(recovery_file);
+  ASSERT_TRUE(recovery_info.Init());
+  bf::remove(recovery_file);
+  const std::vector<bf::path>& recovery_list = recovery_info.GetRecoveryFiles();
+  if (recovery_list.empty()) {
+    std::cout << "installer recovery file is not created yet" << std::endl;
+    return;
+  }
+  ASSERT_EQ(
+      backend.RecoveryPkgsWithSubprocess(recovery_list, params.test_user.uid),
+      SmokeTestHelperRunner::Result::SUCCESS);
+  if (recovery_info.GetCleanUp()) {
+    params.pkg_type = PackageType::TPK;
+    ASSERT_TRUE(ValidatePackage(pkgids.at(0), app_infos.at(0), params));
+    params.pkg_type = PackageType::WGT;
+    ASSERT_TRUE(ValidatePackage(pkgids.at(1), app_infos.at(1), params));
+    params.pkg_type = PackageType::HYBRID;
+    ASSERT_TRUE(ValidatePackage(pkgids.at(2), app_infos.at(2), params));
+    ASSERT_EQ(
+        backend.UninstallWithSubprocess(pkgids.at(0), params.test_user.uid),
+        SmokeTestHelperRunner::Result::SUCCESS);
+    ASSERT_EQ(
+        backend.UninstallWithSubprocess(pkgids.at(1), params.test_user.uid),
+        SmokeTestHelperRunner::Result::SUCCESS);
+    ASSERT_EQ(
+        backend.UninstallWithSubprocess(pkgids.at(2), params.test_user.uid),
+        SmokeTestHelperRunner::Result::SUCCESS);
+  } else {
+    params.pkg_type = PackageType::TPK;
+    ASSERT_TRUE(CheckPackageNonExistance(pkgids.at(0), params));
+    params.pkg_type = PackageType::WGT;
+    ASSERT_TRUE(CheckPackageNonExistance(pkgids.at(1), params));
+    params.pkg_type = PackageType::HYBRID;
+    ASSERT_TRUE(CheckPackageNonExistance(pkgids.at(2), params));
+  }
+}
+
+TEST_F(SmokeTest, RecoveryMode_Multi_Update) {
+  RemoveAllRecoveryFiles("/unified-recovery", params.test_user.uid);
+  RemoveAllRecoveryFiles("/tpk-recovery", params.test_user.uid);
+  RemoveAllRecoveryFiles("/wgt-recovery", params.test_user.uid);
+
+  std::vector<bf::path> paths_old = {
+      kUnifiedSmokePackagesDirectory / "RecoveryTpkPkg.tpk",
+      kUnifiedSmokePackagesDirectory / "RecoveryWgtPkg.wgt",
+      kUnifiedSmokePackagesDirectory / "RecoveryHybridPkg.wgt" };
+  std::vector<bf::path> paths_new = {
+      kUnifiedSmokePackagesDirectory / "RecoveryTpkPkg2.tpk",
+      kUnifiedSmokePackagesDirectory / "RecoveryWgtPkg2.wgt",
+      kUnifiedSmokePackagesDirectory / "RecoveryHybridPkg2.wgt" };
+  std::vector<std::string> pkgids =
+      { "smokerec01", "smokerec02", "smokerec03" };
+  std::vector<Apps> app_infos = {
+      { {"smokerec01.RecoveryTpk", "native"} },
+      { {"smokerec02.RecoveryWgt", "smokerec02.RecoveryWgt"} },
+      {
+        {"smokerec03.RecoveryHybridUI", "smokerec03.RecoveryHybridUI"},
+        {"smokerec03.recoveryhybridservice", "recoveryhybridservice"},
+      }
+  };
+  int wait_time = delay + interval * test_count;
+
+  ASSERT_EQ(backend.InstallPkgsWithSubprocess(paths_old, params.test_user.uid),
+      SmokeTestHelperRunner::Result::SUCCESS);
+
+  SmokeTestHelperRunner::Result ret = backend.InstallPkgsWithSubprocessAndKill(
+      paths_new, params.test_user.uid, wait_time);
+  if (ret == SmokeTestHelperRunner::Result::SUCCESS) {
+    std::cout << "update finished before process killed" << std::endl;
+    return;
+  }
+  ASSERT_EQ(ret, SmokeTestHelperRunner::Result::KILLED);
+
+  bf::path recovery_file = FindRecoveryFile("/unified-recovery",
+      params.test_user.uid);
+  if (recovery_file.empty()) {
+    std::cout << "recovery file dosen't exist, "
+                 "this test is skipped" << std::endl;
+    return;
+  }
+
+  UnifiedRecoveryInfo recovery_info(recovery_file);
+  ASSERT_TRUE(recovery_info.Init());
+  bf::remove(recovery_file);
+  const std::vector<bf::path>& recovery_list = recovery_info.GetRecoveryFiles();
+  if (recovery_list.empty()) {
+    std::cout << "installer recovery file is not created yet" << std::endl;
+    return;
+  }
+
+  ASSERT_EQ(
+      backend.RecoveryPkgsWithSubprocess(recovery_list, params.test_user.uid),
+      SmokeTestHelperRunner::Result::SUCCESS);
+  if (recovery_info.GetCleanUp()) {
+    params.pkg_type = PackageType::TPK;
+    ASSERT_TRUE(ValidatePackage(pkgids.at(0), app_infos.at(0), params));
+    ASSERT_TRUE(ValidateFileContentInPackage(
+        pkgids.at(0), "res/VERSION", "2", params));
+    params.pkg_type = PackageType::WGT;
+    ASSERT_TRUE(ValidatePackage(pkgids.at(1), app_infos.at(1), params));
+    ASSERT_TRUE(ValidateFileContentInPackage(
+        pkgids.at(1), "res/wgt/VERSION", "2", params));
+    params.pkg_type = PackageType::HYBRID;
+    ASSERT_TRUE(ValidatePackage(pkgids.at(2), app_infos.at(2), params));
+    ASSERT_TRUE(ValidateFileContentInPackage(
+        pkgids.at(2), "res/wgt/VERSION", "2", params));
+  } else {
+    params.pkg_type = PackageType::TPK;
+    ASSERT_TRUE(ValidatePackage(pkgids.at(0), app_infos.at(0), params));
+    ASSERT_TRUE(ValidateFileContentInPackage(
+        pkgids.at(0), "res/VERSION", "1", params));
+    params.pkg_type = PackageType::WGT;
+    ASSERT_TRUE(ValidatePackage(pkgids.at(1), app_infos.at(1), params));
+    ASSERT_TRUE(ValidateFileContentInPackage(
+        pkgids.at(1), "res/wgt/VERSION", "1", params));
+    params.pkg_type = PackageType::HYBRID;
+    ASSERT_TRUE(ValidatePackage(pkgids.at(2), app_infos.at(2), params));
+    ASSERT_TRUE(ValidateFileContentInPackage(
+        pkgids.at(2), "res/wgt/VERSION", "1", params));
+  }
+  ASSERT_EQ(
+      backend.UninstallWithSubprocess(pkgids.at(0), params.test_user.uid),
+      SmokeTestHelperRunner::Result::SUCCESS);
+  ASSERT_EQ(
+      backend.UninstallWithSubprocess(pkgids.at(1), params.test_user.uid),
+      SmokeTestHelperRunner::Result::SUCCESS);
+  ASSERT_EQ(
+      backend.UninstallWithSubprocess(pkgids.at(2), params.test_user.uid),
+      SmokeTestHelperRunner::Result::SUCCESS);
+}
+
+TEST_F(SmokeTest, RecoveryMode_ForDelta) {
+  RemoveAllRecoveryFiles("/unified-recovery", params.test_user.uid);
+  RemoveAllRecoveryFiles("/tpk-recovery", params.test_user.uid);
+  RemoveAllRecoveryFiles("/wgt-recovery", params.test_user.uid);
+
+  std::vector<bf::path> paths_old = {
+      kUnifiedSmokePackagesDirectory / "RecoveryTpkPkg.tpk",
+      kUnifiedSmokePackagesDirectory / "RecoveryWgtPkg.wgt",
+      kUnifiedSmokePackagesDirectory / "RecoveryHybridPkg.wgt" };
+  std::vector<bf::path> paths_new = {
+      kUnifiedSmokePackagesDirectory / "RecoveryTpkPkg.delta",
+      kUnifiedSmokePackagesDirectory / "RecoveryWgtPkg.delta",
+      kUnifiedSmokePackagesDirectory / "RecoveryHybridPkg.delta" };
+  std::vector<std::string> pkgids =
+      { "smokerec01", "smokerec02", "smokerec03" };
+  std::vector<Apps> app_infos = {
+      { {"smokerec01.RecoveryTpk", "native"} },
+      { {"smokerec02.RecoveryWgt", "smokerec02.RecoveryWgt"} },
+      {
+        {"smokerec03.RecoveryHybridUI", "smokerec03.RecoveryHybridUI"},
+        {"smokerec03.recoveryhybridservice", "recoveryhybridservice"},
+      }
+  };
+  int wait_time = delay + interval * test_count;
+
+  ASSERT_EQ(backend.InstallPkgsWithSubprocess(paths_old, params.test_user.uid),
+      SmokeTestHelperRunner::Result::SUCCESS);
+
+  SmokeTestHelperRunner::Result ret = backend.InstallPkgsWithSubprocessAndKill(
+      paths_new, params.test_user.uid, wait_time);
+  if (ret == SmokeTestHelperRunner::Result::SUCCESS) {
+    std::cout << "delta finished before process killed" << std::endl;
+    return;
+  }
+  ASSERT_EQ(ret, SmokeTestHelperRunner::Result::KILLED);
+
+  bf::path recovery_file = FindRecoveryFile("/unified-recovery",
+      params.test_user.uid);
+  if (recovery_file.empty()) {
+    std::cout << "recovery file dosen't exist, "
+                 "this test is skipped" << std::endl;
+    return;
+  }
+
+  UnifiedRecoveryInfo recovery_info(recovery_file);
+  ASSERT_TRUE(recovery_info.Init());
+  bf::remove(recovery_file);
+  const std::vector<bf::path>& recovery_list = recovery_info.GetRecoveryFiles();
+  if (recovery_list.empty()) {
+    std::cout << "installer recovery file is not created yet" << std::endl;
+    return;
+  }
+
+  ASSERT_EQ(
+      backend.RecoveryPkgsWithSubprocess(recovery_list, params.test_user.uid),
+      SmokeTestHelperRunner::Result::SUCCESS);
+  if (recovery_info.GetCleanUp()) {
+    params.pkg_type = PackageType::TPK;
+    ASSERT_TRUE(ValidatePackage(pkgids.at(0), app_infos.at(0), params));
+    ASSERT_TRUE(ValidateFileContentInPackage(
+        pkgids.at(0), "res/VERSION", "2", params));
+    params.pkg_type = PackageType::WGT;
+    ASSERT_TRUE(ValidatePackage(pkgids.at(1), app_infos.at(1), params));
+    ASSERT_TRUE(ValidateFileContentInPackage(
+        pkgids.at(1), "res/wgt/VERSION", "2", params));
+    params.pkg_type = PackageType::HYBRID;
+    ASSERT_TRUE(ValidatePackage(pkgids.at(2), app_infos.at(2), params));
+    ASSERT_TRUE(ValidateFileContentInPackage(
+        pkgids.at(2), "res/wgt/VERSION", "2", params));
+  } else {
+    params.pkg_type = PackageType::TPK;
+    ASSERT_TRUE(ValidatePackage(pkgids.at(0), app_infos.at(0), params));
+    ASSERT_TRUE(ValidateFileContentInPackage(
+        pkgids.at(0), "res/VERSION", "1", params));
+    params.pkg_type = PackageType::WGT;
+    ASSERT_TRUE(ValidatePackage(pkgids.at(1), app_infos.at(1), params));
+    ASSERT_TRUE(ValidateFileContentInPackage(
+        pkgids.at(1), "res/wgt/VERSION", "1", params));
+    params.pkg_type = PackageType::HYBRID;
+    ASSERT_TRUE(ValidatePackage(pkgids.at(2), app_infos.at(2), params));
+    ASSERT_TRUE(ValidateFileContentInPackage(
+        pkgids.at(2), "res/wgt/VERSION", "1", params));
+  }
+  ASSERT_EQ(
+      backend.UninstallWithSubprocess(pkgids.at(0), params.test_user.uid),
+      SmokeTestHelperRunner::Result::SUCCESS);
+  ASSERT_EQ(
+      backend.UninstallWithSubprocess(pkgids.at(1), params.test_user.uid),
+      SmokeTestHelperRunner::Result::SUCCESS);
+  ASSERT_EQ(
+      backend.UninstallWithSubprocess(pkgids.at(2), params.test_user.uid),
+      SmokeTestHelperRunner::Result::SUCCESS);
+}
+
+TEST_F(SmokeTest, RecoveryMode_ForMountInstall) {
+  RemoveAllRecoveryFiles("/unified-recovery", params.test_user.uid);
+  RemoveAllRecoveryFiles("/tpk-recovery", params.test_user.uid);
+  RemoveAllRecoveryFiles("/wgt-recovery", params.test_user.uid);
+
+  std::vector<bf::path> paths = {
+      kUnifiedSmokePackagesDirectory / "RecoveryTpkPkg.tpk",
+      kUnifiedSmokePackagesDirectory / "RecoveryWgtPkg.wgt",
+      kUnifiedSmokePackagesDirectory / "RecoveryHybridPkg.wgt" };
+  std::vector<std::string> pkgids =
+      { "smokerec01", "smokerec02", "smokerec03" };
+  std::vector<Apps> app_infos = {
+      { {"smokerec01.RecoveryTpk", "native"} },
+      { {"smokerec02.RecoveryWgt", "smokerec02.RecoveryWgt"} },
+      {
+        {"smokerec03.RecoveryHybridUI", "smokerec03.RecoveryHybridUI"},
+        {"smokerec03.recoveryhybridservice", "recoveryhybridservice"},
+      }
+  };
+
+  int wait_time = delay + interval * test_count;
+  SmokeTestHelperRunner::Result ret =
+      backend.MountInstallPkgsWithSubprocessAndKill(
+          paths, params.test_user.uid, wait_time);
+  if (ret == SmokeTestHelperRunner::Result::SUCCESS) {
+    std::cout << "install finished before process killed" << std::endl;
+    return;
+  }
+  ASSERT_EQ(ret, SmokeTestHelperRunner::Result::KILLED);
+
+  bf::path recovery_file = FindRecoveryFile("/unified-recovery",
+      params.test_user.uid);
+  if (recovery_file.empty()) {
+    std::cout << "recovery file dosen't exist, "
+                 "this test is skipped" << std::endl;
+    return;
+  }
+
+  UnifiedRecoveryInfo recovery_info(recovery_file);
+  ASSERT_TRUE(recovery_info.Init());
+  bf::remove(recovery_file);
+  const std::vector<bf::path>& recovery_list = recovery_info.GetRecoveryFiles();
+  if (recovery_list.empty()) {
+    std::cout << "installer recovery file is not created yet" << std::endl;
+    return;
+  }
+  ASSERT_EQ(
+      backend.RecoveryPkgsWithSubprocess(recovery_list, params.test_user.uid),
+      SmokeTestHelperRunner::Result::SUCCESS);
+  if (recovery_info.GetCleanUp()) {
+    params.pkg_type = PackageType::TPK;
+    ASSERT_TRUE(ValidatePackage(pkgids.at(0), app_infos.at(0), params));
+    params.pkg_type = PackageType::WGT;
+    ASSERT_TRUE(ValidatePackage(pkgids.at(1), app_infos.at(1), params));
+    params.pkg_type = PackageType::HYBRID;
+    ASSERT_TRUE(ValidatePackage(pkgids.at(2), app_infos.at(2), params));
+    ASSERT_EQ(
+        backend.UninstallWithSubprocess(pkgids.at(0), params.test_user.uid),
+        SmokeTestHelperRunner::Result::SUCCESS);
+    ASSERT_EQ(
+        backend.UninstallWithSubprocess(pkgids.at(1), params.test_user.uid),
+        SmokeTestHelperRunner::Result::SUCCESS);
+    ASSERT_EQ(
+        backend.UninstallWithSubprocess(pkgids.at(2), params.test_user.uid),
+        SmokeTestHelperRunner::Result::SUCCESS);
+  } else {
+    params.pkg_type = PackageType::TPK;
+    ASSERT_TRUE(CheckPackageNonExistance(pkgids.at(0), params));
+    params.pkg_type = PackageType::WGT;
+    ASSERT_TRUE(CheckPackageNonExistance(pkgids.at(1), params));
+    params.pkg_type = PackageType::HYBRID;
+    ASSERT_TRUE(CheckPackageNonExistance(pkgids.at(2), params));
+  }
+}
+
+TEST_F(SmokeTest, RecoveryMode_ForMountUpdate) {
+  RemoveAllRecoveryFiles("/unified-recovery", params.test_user.uid);
+  RemoveAllRecoveryFiles("/tpk-recovery", params.test_user.uid);
+  RemoveAllRecoveryFiles("/wgt-recovery", params.test_user.uid);
+
+  std::vector<bf::path> paths_old = {
+      kUnifiedSmokePackagesDirectory / "RecoveryTpkPkg.tpk",
+      kUnifiedSmokePackagesDirectory / "RecoveryWgtPkg.wgt",
+      kUnifiedSmokePackagesDirectory / "RecoveryHybridPkg.wgt" };
+  std::vector<bf::path> paths_new = {
+      kUnifiedSmokePackagesDirectory / "RecoveryTpkPkg2.tpk",
+      kUnifiedSmokePackagesDirectory / "RecoveryWgtPkg2.wgt",
+      kUnifiedSmokePackagesDirectory / "RecoveryHybridPkg2.wgt" };
+  std::vector<std::string> pkgids =
+      { "smokerec01", "smokerec02", "smokerec03" };
+  std::vector<Apps> app_infos = {
+      { {"smokerec01.RecoveryTpk", "native"} },
+      { {"smokerec02.RecoveryWgt", "smokerec02.RecoveryWgt"} },
+      {
+        {"smokerec03.RecoveryHybridUI", "smokerec03.RecoveryHybridUI"},
+        {"smokerec03.recoveryhybridservice", "recoveryhybridservice"},
+      }
+  };
+  int wait_time = delay + interval * test_count;
+
+  ASSERT_EQ(backend.
+      MountInstallPkgsWithSubprocess(paths_old, params.test_user.uid),
+          SmokeTestHelperRunner::Result::SUCCESS);
+
+  SmokeTestHelperRunner::Result ret =
+      backend.MountInstallPkgsWithSubprocessAndKill(
+          paths_new, params.test_user.uid, wait_time);
+  if (ret == SmokeTestHelperRunner::Result::SUCCESS) {
+    std::cout << "update finished before process killed" << std::endl;
+    return;
+  }
+  ASSERT_EQ(ret, SmokeTestHelperRunner::Result::KILLED);
+
+  bf::path recovery_file = FindRecoveryFile("/unified-recovery",
+      params.test_user.uid);
+  if (recovery_file.empty()) {
+    std::cout << "recovery file dosen't exist, "
+                 "this test is skipped" << std::endl;
+    return;
+  }
+
+  UnifiedRecoveryInfo recovery_info(recovery_file);
+  ASSERT_TRUE(recovery_info.Init());
+  bf::remove(recovery_file);
+  const std::vector<bf::path>& recovery_list = recovery_info.GetRecoveryFiles();
+  if (recovery_list.empty()) {
+    std::cout << "installer recovery file is not created yet" << std::endl;
+    return;
+  }
+
+  // Filesystem may be mounted after crash
+  for (const std::string& pkgid : pkgids) {
+    ScopedTzipInterface poweroff_unmount_interface(pkgid, params.test_user.uid);
+    poweroff_unmount_interface.Release();
+  }
+
+  ASSERT_EQ(
+      backend.RecoveryPkgsWithSubprocess(recovery_list, params.test_user.uid),
+      SmokeTestHelperRunner::Result::SUCCESS);
+
+  ScopedTzipInterface interface_1(pkgids.at(0), params.test_user.uid);
+  ScopedTzipInterface interface_2(pkgids.at(1), params.test_user.uid);
+  ScopedTzipInterface interface_3(pkgids.at(2), params.test_user.uid);
+
+  if (recovery_info.GetCleanUp()) {
+    params.pkg_type = PackageType::TPK;
+    ASSERT_TRUE(ValidatePackage(pkgids.at(0), app_infos.at(0), params));
+    ASSERT_TRUE(ValidateFileContentInPackage(
+        pkgids.at(0), "res/VERSION", "2", params));
+    params.pkg_type = PackageType::WGT;
+    ASSERT_TRUE(ValidatePackage(pkgids.at(1), app_infos.at(1), params));
+    ASSERT_TRUE(ValidateFileContentInPackage(
+        pkgids.at(1), "res/wgt/VERSION", "2", params));
+    params.pkg_type = PackageType::HYBRID;
+    ASSERT_TRUE(ValidatePackage(pkgids.at(2), app_infos.at(2), params));
+    ASSERT_TRUE(ValidateFileContentInPackage(
+        pkgids.at(2), "res/wgt/VERSION", "2", params));
+  } else {
+    params.pkg_type = PackageType::TPK;
+    ASSERT_TRUE(ValidatePackage(pkgids.at(0), app_infos.at(0), params));
+    ASSERT_TRUE(ValidateFileContentInPackage(
+        pkgids.at(0), "res/VERSION", "1", params));
+    params.pkg_type = PackageType::WGT;
+    ASSERT_TRUE(ValidatePackage(pkgids.at(1), app_infos.at(1), params));
+    ASSERT_TRUE(ValidateFileContentInPackage(
+        pkgids.at(1), "res/wgt/VERSION", "1", params));
+    params.pkg_type = PackageType::HYBRID;
+    ASSERT_TRUE(ValidatePackage(pkgids.at(2), app_infos.at(2), params));
+    ASSERT_TRUE(ValidateFileContentInPackage(
+        pkgids.at(2), "res/wgt/VERSION", "1", params));
+  }
+
+  ASSERT_EQ(
+      backend.UninstallWithSubprocess(pkgids.at(0), params.test_user.uid),
+      SmokeTestHelperRunner::Result::SUCCESS);
+  ASSERT_EQ(
+      backend.UninstallWithSubprocess(pkgids.at(1), params.test_user.uid),
+      SmokeTestHelperRunner::Result::SUCCESS);
+  ASSERT_EQ(
+      backend.UninstallWithSubprocess(pkgids.at(2), params.test_user.uid),
+      SmokeTestHelperRunner::Result::SUCCESS);
+}
+
+}  // namespace smoke_test
+
+const int kBufSize = 1024;
+
+int main(int argc,  char** argv) {
+  bool no_backup = false;
+  int repeat_count = 10;
+  ReqType req_type = ReqType::UNKNOWN_REQ;
+  bool repeat = false;
+  BackupType backup_type = BackupType::MOVE;
+  ci::RequestMode request_mode = smoke_test::ParseRequestMode(argc, argv);
+  if (getuid() != 0 || request_mode != ci::RequestMode::GLOBAL)
+    std::cout << "Run recovery test with user request mode" << std::endl;
+
+  bpo::options_description options("Allowed options");
+  bpo::variables_map opt_map;
+  try {
+    options.add_options()
+        ("help", "display this help message")
+        ("install",
+            "recovery test for forced termination "
+            "during package installing")
+        ("update",
+            "recovery test for forced termination "
+            "during package updating")
+        ("delta",
+            "recovery test for forced termination "
+            "during package delta installing")
+        ("mount-install",
+            "recovery test for forced termination "
+            "during package mount-installing")
+        ("mount-update",
+            "recovery test for forced termination "
+            "during package mount-updating")
+        ("delay", bpo::value<int>(), "fixed delay for forced termination\n"
+            "unit : microsecond (ex. 1000000us = 1s)")
+        ("interval", bpo::value<int>(),
+            "use with repeat option.\n"
+            "as it repeat the interval is added to delay\n"
+            "unit : microsecond (ex. 1000000us = 1s)")
+        ("repeat", bpo::value<int>(), "option for performing tests repeatedly\n"
+            "enter -1 to test infinitely")
+        ("no-backup", "Do test without backup")
+        ("backup-type", bpo::value<std::string>(), "<move|copy> set test's "
+            "backup type \'move\', \'copy and remove\'");
+    bpo::store(bpo::command_line_parser(argc, argv).
+        options(options).allow_unregistered().run(), opt_map);
+    if (opt_map.count("help")) {
+      std::cerr << options << std::endl;
+      return -1;
+    }
+
+    if (opt_map.count("install"))
+      req_type = ReqType::INSTALL_REQ;
+    else if (opt_map.count("update"))
+      req_type = ReqType::UPDATE_REQ;
+    else if (opt_map.count("delta"))
+      req_type = ReqType::DELTA_REQ;
+    else if (opt_map.count("mount-install"))
+      req_type = ReqType::MOUNT_INSTALL_REQ;
+    else if (opt_map.count("mount-update"))
+      req_type = ReqType::MOUNT_UPDATE_REQ;
+
+    if (opt_map.count("delay"))
+      delay = opt_map["delay"].as<int>();
+
+    if (opt_map.count("interval"))
+      interval = opt_map["interval"].as<int>();
+
+    if (opt_map.count("repeat")) {
+      repeat = true;
+      repeat_count = opt_map["repeat"].as<int>();
+    }
+
+    if (opt_map.count("no-backup"))
+      no_backup = true;
+    if (opt_map.count("backup-type")) {
+      if (opt_map["backup-type"].as<std::string>() == "move") {
+        backup_type = BackupType::MOVE;
+      } else if (opt_map["backup-type"].as<std::string>() == "copy") {
+        backup_type = BackupType::COPY_AND_REMOVE;
+      } else {
+        std::cerr << options << std::endl;
+        return -1;
+      }
+    }
+    bpo::notify(opt_map);
+  } catch (...) {
+    std::cerr << "Exception occurred: "
+              << boost::current_exception_diagnostic_information()
+              << std::endl;
+    return -1;
+  }
+
+  if (req_type == ReqType::UNKNOWN_REQ) {
+    std::cerr << options << std::endl;
+    return 0;
+  }
+
+  try {
+    testing::GTEST_FLAG(filter) = install_req_filter[req_type];
+    if (repeat) {
+      testing::GTEST_FLAG(repeat) = repeat_count;
+      testing::GTEST_FLAG(break_on_failure) = true;
+    }
+    testing::InitGoogleTest(&argc, argv);
+    ::env = static_cast<smoke_test::SmokeEnvironment*>(
+        testing::AddGlobalTestEnvironment(
+            new smoke_test::SmokeEnvironment(request_mode,
+                no_backup, backup_type)));
+    signal(SIGINT, ::signalHandler);
+    signal(SIGSEGV, ::signalHandler);
+    return RUN_ALL_TESTS();
+  } catch (...) {
+    std::cout << "Exception occurred during testing" << std::endl;
+    return 1;
+  }
+}