Export Smoke Utils 23/119323/6
authorPiotr Ganicz <p.ganicz@samsung.com>
Fri, 17 Feb 2017 13:11:30 +0000 (14:11 +0100)
committerjongmyeong ko <jongmyeong.ko@samsung.com>
Mon, 15 May 2017 10:17:50 +0000 (10:17 +0000)
This change exports utility functions to smoke_utils.h

Change-Id: I5035f0775af2749dbd07fe3d2970446f877d522d

src/unit_tests/CMakeLists.txt
src/unit_tests/smoke_test.cc
src/unit_tests/smoke_utils.cc [new file with mode: 0644]
src/unit_tests/smoke_utils.h [new file with mode: 0644]

index dcb4d43ad56a6974aede744696152d6750f823a9..f0bc7965cc873dfe58b0edd5f8b74bae5e58e7c2 100644 (file)
@@ -3,6 +3,8 @@ SET(DESTINATION_DIR tpk-backend-ut)
 # Executables
 ADD_EXECUTABLE(${TARGET_SMOKE_TEST}
   smoke_test.cc
+  smoke_utils.h
+  smoke_utils.cc
 )
 
 ADD_EXECUTABLE(${TARGET_SMOKE_TEST_HELPER}
index 71d9e5d67b199020846622855c3ad9f11916fc81..09bb3002d06f2a3439680906e71f97ce600d36a1 100644 (file)
 // Use of this source code is governed by an apache-2.0 license that can be
 // found in the LICENSE file.
 
-#include <boost/filesystem/operations.hpp>
-#include <boost/filesystem/path.hpp>
-#include <boost/range/iterator_range.hpp>
-#include <boost/system/error_code.hpp>
-
-#include <common/paths.h>
-#include <common/pkgmgr_interface.h>
-#include <common/pkgmgr_query.h>
-#include <common/request.h>
-#include <common/step/configuration/step_fail.h>
-#include <common/tzip_interface.h>
-#include <common/utils/file_util.h>
 #include <common/utils/subprocess.h>
-#include <common/utils/user_util.h>
 
 #include <gtest/gtest.h>
 #include <gtest/gtest-death-test.h>
-#include <pkgmgr-info.h>
-#include <signal.h>
-#include <unistd.h>
-#include <tzplatform_config.h>
-#include <vconf.h>
-#include <vconf-internal-keys.h>
-
-#include <array>
-#include <cstdio>
-#include <cstdlib>
-
-#include "tpk/tpk_app_query_interface.h"
-#include "tpk/tpk_installer.h"
-
-#define SIZEOFARRAY(ARR)                                                       \
-  sizeof(ARR) / sizeof(ARR[0])                                                 \
-
-namespace bf = boost::filesystem;
-namespace bs = boost::system;
-namespace ci = common_installer;
-
-namespace {
-
-const uid_t kGlobalUserUid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
-const uid_t kGlobalUserGid = tzplatform_getgid(TZ_SYS_GLOBALAPP_USER);
-const uid_t kDefaultUserUid = tzplatform_getuid(TZ_SYS_DEFAULT_USER);
-// TODO(s89.jang): Test local case also
-const uid_t kTestUserId = kGlobalUserUid;
-const gid_t kTestGroupId = kGlobalUserGid;
-const char kSystemShareGroupName[] = "system_share";
-const std::string& kTestUserIdStr = std::to_string(kTestUserId);
-const std::string& kDefaultUserIdStr = std::to_string(kDefaultUserUid);
-const char kLegacyExtImageDir[] = "legacy_extimage_dir";
-const char kMigrateTestDBName[] = "app2sd_migrate.db";
-
-const bf::path kSmokePackagesDirectory =
-    "/usr/share/tpk-backend-ut/test_samples/smoke/";
-
-// common entries
-const std::vector<std::string> kDBEntries = {
-  {".pkgmgr_parser.db"},
-  {".pkgmgr_parser.db-journal"},
-  {".pkgmgr_cert.db"},
-  {".pkgmgr_cert.db-journal"},
-  {".app2sd.db"},
-  {".app2sd.db-journal"},
-};
-// globaluser entries
-const char kGlobalManifestDir[] = "/opt/share/packages";
-const char kSkelDir[] = "/etc/skel/apps_rw";
-const char kPreloadApps[] = "/usr/apps";
-const char kPreloadManifestDir[] = "/usr/share/packages";
-const char kPreloadIcons[] = "/usr/share/icons";
-
-enum class RequestResult {
-  NORMAL,
-  FAIL
-};
-
-class ScopedTzipInterface {
- public:
-  explicit ScopedTzipInterface(const std::string& pkgid)
-      : pkg_path_(bf::path(ci::GetRootAppPath(false,
-            kTestUserId)) / pkgid),
-        interface_(ci::GetMountLocation(pkg_path_)),
-        mounted_(true) {
-    interface_.MountZip(ci::GetZipPackageLocation(pkg_path_, pkgid));
-  }
-
-  void Release() {
-    if (mounted_) {
-      interface_.UnmountZip();
-      mounted_ = false;
-    }
-  }
-
-  ~ScopedTzipInterface() {
-    Release();
-  }
-
- private:
-  bf::path pkg_path_;
-  ci::TzipInterface interface_;
-  bool mounted_;
-};
-
-bool TouchFile(const bf::path& path) {
-  FILE* f = fopen(path.c_str(), "w+");
-  if (!f)
-    return false;
-  fclose(f);
-  return true;
-}
-
-class TestPkgmgrInstaller : public ci::PkgmgrInstallerInterface {
- public:
-  bool CreatePkgMgrInstaller(pkgmgr_installer** installer,
-                             ci::InstallationMode* mode) {
-    *installer = pkgmgr_installer_offline_new();
-    if (!*installer)
-      return false;
-    *mode = ci::InstallationMode::ONLINE;
-    return true;
-  }
-
-  bool ShouldCreateSignal() const {
-    return false;
-  }
-};
-
-void RemoveAllRecoveryFiles() {
-  bf::path root_path = ci::GetRootAppPath(false,
-      kTestUserId);
-  if (!bf::exists(root_path))
-    return;
-  for (auto& dir_entry : boost::make_iterator_range(
-         bf::directory_iterator(root_path), bf::directory_iterator())) {
-    if (bf::is_regular_file(dir_entry)) {
-      if (dir_entry.path().string().find("/tpk-recovery") !=
-          std::string::npos) {
-        bs::error_code error;
-        bf::remove(dir_entry.path(), error);
-      }
-    }
-  }
-}
-
-bf::path FindRecoveryFile() {
-  bf::path root_path = ci::GetRootAppPath(false,
-      kTestUserId);
-  for (auto& dir_entry : boost::make_iterator_range(
-         bf::directory_iterator(root_path), bf::directory_iterator())) {
-    if (bf::is_regular_file(dir_entry)) {
-      if (dir_entry.path().string().find("/tpk-recovery") != std::string::npos)
-        return dir_entry.path();
-    }
-  }
-  return {};
-}
-
-bool ValidateFileContentInPackage(const std::string& pkgid,
-                                  const std::string& relative,
-                                  const std::string& expected,
-                                  bool is_readonly = false) {
-  bf::path root_path = ci::GetRootAppPath(is_readonly,
-      kTestUserId);
-  bf::path file_path = root_path / pkgid / relative;
-  if (!bf::exists(file_path)) {
-    LOG(ERROR) << file_path << " doesn't exist";
-    return false;
-  }
-  FILE* handle = fopen(file_path.c_str(), "r");
-  if (!handle) {
-    LOG(ERROR) << file_path << " cannot  be open";
-    return false;
-  }
-  std::string content;
-  std::array<char, 200> buffer;
-  while (fgets(buffer.data(), buffer.size(), handle)) {
-    content += buffer.data();
-  }
-  fclose(handle);
-  return content == expected;
-}
-
-void ValidatePackageRWFS(const std::string& pkgid, uid_t uid) {
-  bf::path root_path = ci::GetRootAppPath(false, uid);
-  bf::path package_path = root_path / pkgid;
-  bf::path data_path = package_path / "data";
-  bf::path cache_path = package_path / "cache";
-  bf::path shared_data_path = package_path / "shared" / "data";
-
-  ASSERT_TRUE(bf::exists(data_path));
-  ASSERT_TRUE(bf::exists(cache_path));
-
-  struct stat stats;
-  stat(data_path.c_str(), &stats);
-  // gid of RW dirs should be system_share
-  boost::optional<gid_t> system_share =
-      ci::GetGidByGroupName(kSystemShareGroupName);
-  ASSERT_EQ(uid, stats.st_uid) << "Invalid gid: " << data_path;
-  ASSERT_EQ(*system_share, stats.st_gid) << "Invalid gid: " << data_path;
-  if (bf::exists(shared_data_path)) {
-    stat(shared_data_path.c_str(), &stats);
-    ASSERT_EQ(uid, stats.st_uid) << "Invalid gid: " << shared_data_path;
-    ASSERT_EQ(*system_share, stats.st_gid) << "Invalid gid: "
-                                           << shared_data_path;
-  }
-
-  stat(cache_path.c_str(), &stats);
-  ASSERT_EQ(uid, stats.st_uid) << "Invalid gid: " << cache_path;
-  ASSERT_EQ(*system_share, stats.st_gid) << "Invalid gid: " << cache_path;
-}
-
-void ValidatePackageFS(const std::string& pkgid, const std::string& appid,
-    uid_t uid, gid_t gid, bool is_readonly = false) {
-  bf::path root_path = ci::GetRootAppPath(is_readonly, uid);
-  bf::path package_path = root_path / pkgid;
-  bf::path shared_path = package_path / "shared";
-  ASSERT_TRUE(bf::exists(root_path));
-  ASSERT_TRUE(bf::exists(package_path));
-  ASSERT_TRUE(bf::exists(shared_path));
-
-  bf::path manifest_path =
-      bf::path(getUserManifestPath(uid, is_readonly)) / (pkgid + ".xml");
-  ASSERT_TRUE(bf::exists(manifest_path));
-
-  // backups should not exist
-  bf::path package_backup = ci::GetBackupPathForPackagePath(package_path);
-  bf::path manifest_backup = ci::GetBackupPathForManifestFile(manifest_path);
-  ASSERT_FALSE(bf::exists(package_backup));
-  ASSERT_FALSE(bf::exists(manifest_backup));
-
-  for (bf::recursive_directory_iterator iter(package_path);
-      iter != bf::recursive_directory_iterator(); ++iter) {
-    if (bf::is_symlink(symlink_status(iter->path())))
-      continue;
-    if (iter->path().filename() == "data" ||
-        iter->path().filename() == ".mmc")
-      continue;
-    struct stat stats;
-    stat(iter->path().c_str(), &stats);
-    ASSERT_EQ(uid, stats.st_uid) << "Invalid uid: " << iter->path();
-    ASSERT_EQ(gid, stats.st_gid) << "Invalid gid: " << iter->path();
-  }
-}
-
-void PackageCheckCleanup(const std::string& pkgid, const std::string&,
-                         bool is_readonly = false) {
-  bf::path root_path = ci::GetRootAppPath(is_readonly,
-      kTestUserId);
-  bf::path package_path = root_path / pkgid;
-  ASSERT_FALSE(bf::exists(package_path));
-
-  bf::path manifest_path =
-      bf::path(getUserManifestPath(
-          kTestUserId, is_readonly)) / (pkgid + ".xml");
-  ASSERT_FALSE(bf::exists(manifest_path));
-
-  // backups should not exist
-  bf::path package_backup = ci::GetBackupPathForPackagePath(package_path);
-  bf::path manifest_backup = ci::GetBackupPathForManifestFile(manifest_path);
-  ASSERT_FALSE(bf::exists(package_backup));
-  ASSERT_FALSE(bf::exists(manifest_backup));
-}
-
-void ValidatePackage(const std::string& pkgid, const std::string& appid,
-    bool is_readonly = false) {
-  ASSERT_TRUE(ci::QueryIsPackageInstalled(
-      pkgid, ci::GetRequestMode(kTestUserId),
-      kTestUserId));
-  ValidatePackageFS(pkgid, appid, kTestUserId, kTestGroupId, is_readonly);
-  if (kTestUserId == kGlobalUserUid) {
-    ci::UserList list = ci::GetUserList();
-    for (auto& l : list)
-      ValidatePackageRWFS(pkgid, std::get<0>(l));
-  } else {
-    ValidatePackageRWFS(pkgid, kTestUserId);
-  }
-}
-
-void ValidateExternalPackage_FS(const std::string& pkgid,
-    const std::string& appid, uid_t uid) {
-  ASSERT_EQ(app2ext_usr_enable_external_pkg(pkgid.c_str(), uid), 0);
-  bf::path root_path = ci::GetRootAppPath(false, uid);
-  ASSERT_TRUE(bf::exists(root_path / pkgid / ".mmc" / "bin"));
-  ASSERT_TRUE(bf::exists(root_path / pkgid / ".mmc" / "lib"));
-  ASSERT_TRUE(bf::exists(root_path / pkgid / ".mmc" / "res"));
-  ValidatePackage(pkgid, appid);
-  ASSERT_EQ(app2ext_usr_disable_external_pkg(pkgid.c_str(), uid), 0);
-}
-
-void ValidateExternalPackage(const std::string& pkgid,
-    const std::string& appid) {
-  std::string storage = ci::QueryStorageForPkgId(pkgid, kTestUserId);
-  bf::path ext_mount_path = ci::GetExternalCardPath();
-  if (bf::is_empty(ext_mount_path)) {
-    LOG(INFO) << "Sdcard not exists!";
-    ASSERT_EQ(storage, "installed_internal");
-  } else {
-    ASSERT_EQ(storage, "installed_external");
-  }
-  ValidateExternalPackage_FS(pkgid, appid, kTestUserId);
-}
-
-void CheckPackageNonExistance(const std::string& pkgid,
-                              const std::string& appid,
-                              bool is_readonly = false) {
-  ASSERT_FALSE(ci::QueryIsPackageInstalled(
-      pkgid, ci::GetRequestMode(kTestUserId),
-      kTestUserId));
-  PackageCheckCleanup(pkgid, appid, is_readonly);
-  if (kTestUserId == kGlobalUserUid) {
-    bf::path skel_path(kSkelDir);
-    ASSERT_FALSE(bf::exists(skel_path / pkgid));
-    ci::UserList list = ci::GetUserList();
-    for (auto& l : list) {
-      bf::path root_path = ci::GetRootAppPath(false, std::get<0>(l));
-      bf::path package_path = root_path / pkgid;
-      ASSERT_FALSE(bf::exists(package_path));
-    }
-  }
-}
-
-std::unique_ptr<ci::AppQueryInterface> CreateQueryInterface() {
-  std::unique_ptr<ci::AppQueryInterface> query_interface(
-      new tpk::TpkAppQueryInterface());
-  return query_interface;
-}
-
-std::unique_ptr<ci::AppInstaller> CreateInstaller(ci::PkgMgrPtr pkgmgr) {
-  std::unique_ptr<ci::AppInstaller> installer(new tpk::TpkInstaller(pkgmgr));
-  return installer;
-}
-
-ci::AppInstaller::Result RunInstallerWithPkgrmgr(ci::PkgMgrPtr pkgmgr,
-                                                 RequestResult mode) {
-  std::unique_ptr<ci::AppInstaller> installer = CreateInstaller(pkgmgr);
-  switch (mode) {
-  case RequestResult::FAIL:
-    installer->AddStep<ci::configuration::StepFail>();
-    break;
-  default:
-    break;
-  }
-  return installer->Run();
-}
-ci::AppInstaller::Result CallBackend(int argc,
-                                     const char* argv[],
-                                     RequestResult mode) {
-  TestPkgmgrInstaller pkgmgr_installer;
-  std::unique_ptr<ci::AppQueryInterface> query_interface =
-      CreateQueryInterface();
-  auto pkgmgr =
-      ci::PkgMgrInterface::Create(argc, const_cast<char**>(argv),
-                                  &pkgmgr_installer,
-                                  query_interface.get());
-  if (!pkgmgr) {
-    LOG(ERROR) << "Failed to initialize pkgmgr interface";
-    return ci::AppInstaller::Result::UNKNOWN;
-  }
-  return RunInstallerWithPkgrmgr(pkgmgr, mode);
-}
-
-ci::AppInstaller::Result Install(const bf::path& path,
-                                 RequestResult mode = RequestResult::NORMAL) {
-  const char* argv[] = {"", "-i", path.c_str(), "-u", kTestUserIdStr.c_str()};
-  return CallBackend(SIZEOFARRAY(argv), argv, mode);
-}
-
-ci::AppInstaller::Result InstallPreload(const bf::path& path,
-    RequestResult mode = RequestResult::NORMAL) {
-  const char* argv[] = {"", "-i", path.c_str(), "--preload"};
-  return CallBackend(SIZEOFARRAY(argv), argv, mode);
-}
 
-bool CheckAvailableExternalPath() {
-  bf::path ext_mount_path = ci::GetExternalCardPath();
-  LOG(DEBUG) << "ext_mount_path :" << ext_mount_path;
-  if (ext_mount_path.empty()) {
-    LOG(ERROR) << "Sdcard not exists!";
-    return false;
-  }
-  return true;
-}
-
-ci::AppInstaller::Result InstallExternal(const bf::path& path,
-                                 RequestResult mode = RequestResult::NORMAL) {
-  int default_storage = 0;
-  vconf_get_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT,
-                &default_storage);
-  vconf_set_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT, 1);
-
-  const char* argv[] = {"", "-i", path.c_str(), "-u", kTestUserIdStr.c_str()};
-  ci::AppInstaller::Result result = CallBackend(SIZEOFARRAY(argv), argv, mode);
-
-  vconf_set_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT,
-                default_storage);
-  return result;
-}
-
-ci::AppInstaller::Result MigrateLegacyExternalImage(const std::string& pkgid,
-                                 const bf::path& path,
-                                 const bf::path& legacy_path,
-                                 RequestResult mode = RequestResult::NORMAL) {
-  if (InstallExternal(path) != ci::AppInstaller::Result::OK) {
-    LOG(ERROR) << "Failed to install application. Cannot perform Migrate";
-    return ci::AppInstaller::Result::ERROR;
-  }
-
-  bf::path ext_mount_path = ci::GetExternalCardPath();
-  if (bf::is_empty(ext_mount_path)) {
-    LOG(ERROR) << "Sdcard not exists!";
-    return ci::AppInstaller::Result::ERROR;
-  }
-  bf::path app2sd_path = ext_mount_path / "app2sd";
-
-  char *image_name = app2ext_usr_getname_image(pkgid.c_str(),
-                     kGlobalUserUid);
-  if (!image_name) {
-    LOG(ERROR) << "Failed to get external image name";
-    return ci::AppInstaller::Result::ERROR;
-  }
-  bf::path org_image = app2sd_path / image_name;
-  free(image_name);
-
-  bs::error_code error;
-  bf::remove(org_image, error);
-  if (error) {
-    LOG(ERROR) << "Failed to remove org image";
-    return ci::AppInstaller::Result::ERROR;
-  }
-
-  bf::path db_path = tzplatform_getenv(TZ_SYS_DB);
-  bf::path app2sd_db = db_path / ".app2sd.db";
-  bf::path app2sd_db_journal = db_path / ".app2sd.db-journal";
-  bf::remove(app2sd_db, error);
-  if (error) {
-    LOG(ERROR) << "Failed to remove app2sd db";
-    return ci::AppInstaller::Result::ERROR;
-  }
-  bf::remove(app2sd_db_journal, error);
-  if (error) {
-    LOG(ERROR) << "Failed to remove app2sd journal db";
-    return ci::AppInstaller::Result::ERROR;
-  }
-
-  bf::path app2sd_migrate_db = legacy_path / kMigrateTestDBName;
-  if (!ci::CopyFile(app2sd_migrate_db, app2sd_db)) {
-    LOG(ERROR) << "Failed to copy test db";
-    return ci::AppInstaller::Result::ERROR;
-  }
-
-  bf::path legacy_src = legacy_path / pkgid;
-  bf::path legacy_dst = app2sd_path / pkgid;
-  if (!ci::CopyFile(legacy_src, legacy_dst)) {
-    LOG(ERROR) << "Failed to copy test image";
-    return ci::AppInstaller::Result::ERROR;
-  }
-  const char* argv[] = {"", "--migrate-extimg", pkgid.c_str(),
-                       "-u", kDefaultUserIdStr.c_str()};
-  return CallBackend(SIZEOFARRAY(argv), argv, mode);
-}
-
-ci::AppInstaller::Result InstallWithTEP(
-    const bf::path& path,
-    const bf::path& tep,
-    RequestResult mode = RequestResult::NORMAL) {
-  const char* argv[] = {"", "-i", path.c_str(), "-u", kTestUserIdStr.c_str(),
-                        "-e", tep.c_str()};
-  return CallBackend(SIZEOFARRAY(argv), argv, mode);
-}
-
-ci::AppInstaller::Result Update(const bf::path& path_old,
-                                const bf::path& path_new,
-                                RequestResult mode = RequestResult::NORMAL) {
-  if (Install(path_old) != ci::AppInstaller::Result::OK) {
-    LOG(ERROR) << "Failed to install application. Cannot update";
-    return ci::AppInstaller::Result::UNKNOWN;
-  }
-  return Install(path_new, mode);
-}
-
-ci::AppInstaller::Result MountInstall(const bf::path& path,
-                                 RequestResult mode = RequestResult::NORMAL) {
-  const char* argv[] = {"", "-w", path.c_str(), "-u", kTestUserIdStr.c_str()};
-  return CallBackend(SIZEOFARRAY(argv), argv, mode);
-}
-
-ci::AppInstaller::Result MountInstallWithTEP(
-    const bf::path& path,
-    const bf::path& tep,
-    RequestResult mode = RequestResult::NORMAL) {
-  const char* argv[] = {"", "-w", path.c_str(), "-u", kTestUserIdStr.c_str(),
-                        "-e", tep.c_str()};
-  return CallBackend(SIZEOFARRAY(argv), argv, mode);
-}
-
-ci::AppInstaller::Result MountUpdate(const bf::path& path_old,
-                                const bf::path& path_new,
-                                RequestResult mode = RequestResult::NORMAL) {
-  if (MountInstall(path_old) != ci::AppInstaller::Result::OK) {
-    LOG(ERROR) << "Failed to mount-install application. Cannot mount-update";
-    return ci::AppInstaller::Result::UNKNOWN;
-  }
-  return MountInstall(path_new, mode);
-}
-
-ci::AppInstaller::Result Uninstall(const std::string& pkgid, bool is_readonly,
-                                   RequestResult mode = RequestResult::NORMAL) {
-  if (is_readonly) {
-    const char* argv[] = {"", "-d", pkgid.c_str(), "--preload",
-        "--force-remove"};
-    return CallBackend(SIZEOFARRAY(argv), argv, mode);
-  } else {
-    const char* argv[] = {"", "-d", pkgid.c_str(), "-u",
-        kTestUserIdStr.c_str()};
-    return CallBackend(SIZEOFARRAY(argv), argv, mode);
-  }
-}
-
-ci::AppInstaller::Result EnablePackage(const std::string& path,
-                                 RequestResult mode = RequestResult::NORMAL) {
-  const char* argv[] = {"", "-A", path.c_str(), "-u", kTestUserIdStr.c_str()};
-  return CallBackend(SIZEOFARRAY(argv), argv, mode);
-}
-
-ci::AppInstaller::Result DisablePackage(const std::string& path,
-                                 RequestResult mode = RequestResult::NORMAL) {
-  const char* argv[] = {"", "-D", path.c_str(), "-u", kTestUserIdStr.c_str()};
-  return CallBackend(SIZEOFARRAY(argv), argv, mode);
-}
-
-ci::AppInstaller::Result RDSUpdate(const bf::path& path,
-                                   const std::string& pkgid,
-                                   RequestResult mode = RequestResult::NORMAL) {
-  if (Install(path) != ci::AppInstaller::Result::OK) {
-    LOG(ERROR) << "Failed to install application. Cannot perform RDS";
-    return ci::AppInstaller::Result::UNKNOWN;
-  }
-  const char* argv[] = {"", "-r", pkgid.c_str(), "-u",
-                        kTestUserIdStr.c_str()};
-  return CallBackend(SIZEOFARRAY(argv), argv, mode);
-}
-
-ci::AppInstaller::Result DeltaInstall(const bf::path& path,
-    const bf::path& delta_package) {
-  if (Install(path) != ci::AppInstaller::Result::OK) {
-    LOG(ERROR) << "Failed to install application. Cannot perform RDS";
-    return ci::AppInstaller::Result::UNKNOWN;
-  }
-  return Install(delta_package);
-}
-
-ci::AppInstaller::Result Recover(const bf::path& recovery_file,
-                                 RequestResult mode = RequestResult::NORMAL) {
-  const char* argv[] = {"", "-b", recovery_file.c_str(), "-u",
-                        kTestUserIdStr.c_str()};
-  return CallBackend(SIZEOFARRAY(argv), argv, mode);
-}
-
-void BackupPath(const bf::path& path) {
-  bf::path backup_path = path.string() + ".bck";
-  std::cout << "Backup path: " << path << " to " << backup_path << std::endl;
-  bs::error_code error;
-  bf::remove_all(backup_path, error);
-  if (error)
-    LOG(ERROR) << "Remove failed: " << backup_path
-      << " (" << error.message() << ")";
-  if (bf::exists(path)) {
-    bf::rename(path, backup_path, error);
-    if (error)
-      LOG(ERROR) << "Failed to setup test environment. Does some previous"
-        << " test crashed? Path: "
-        << backup_path << " should not exist.";
-    assert(!error);
-  }
-}
-
-void RestorePath(const bf::path& path) {
-  bf::path backup_path = path.string() + ".bck";
-  std::cout << "Restore path: " << path << " from " << backup_path << std::endl;
-  bs::error_code error;
-  bf::remove_all(path, error);
-  if (error)
-    LOG(ERROR) << "Remove failed: " << path
-      << " (" << error.message() << ")";
-  if (bf::exists(backup_path)) {
-    bf::rename(backup_path, path, error);
-    if (error)
-      LOG(ERROR) << "Failed to restore backup path: " << backup_path
-        << " (" << error.message() << ")";
-  }
-}
-
-std::vector<bf::path> SetupBackupDirectories(uid_t uid) {
-  std::vector<bf::path> entries;
-  bf::path db_dir = bf::path(tzplatform_getenv(TZ_SYS_DB));
-  if (uid != kGlobalUserUid)
-    db_dir = db_dir / "user" / std::to_string(uid);
-  for (auto e : kDBEntries) {
-    bf::path path = db_dir / e;
-    entries.emplace_back(path);
-  }
-
-  if (getuid() == 0) {
-    entries.emplace_back(kPreloadApps);
-    entries.emplace_back(kPreloadManifestDir);
-    entries.emplace_back(kPreloadIcons);
-  }
-
-  if (uid == kGlobalUserUid) {
-    entries.emplace_back(kSkelDir);
-    entries.emplace_back(kGlobalManifestDir);
-    ci::UserList list = ci::GetUserList();
-    for (auto l : list) {
-      bf::path apps = std::get<2>(l) / "apps_rw";
-      entries.emplace_back(apps);
-    }
-  } else {
-    tzplatform_set_user(uid);
-    bf::path approot = tzplatform_getenv(TZ_USER_APPROOT);
-    tzplatform_reset_user();
-    entries.emplace_back(approot);
-  }
-
-  bf::path apps_rw = ci::GetRootAppPath(false, uid);
-  entries.emplace_back(apps_rw);
-
-  return entries;
-}
-
-void UninstallAllAppsInDirectory(bf::path dir, bool is_readonly) {
-  if (bf::exists(dir)) {
-    for (auto& dir_entry : boost::make_iterator_range(
-        bf::directory_iterator(dir), bf::directory_iterator())) {
-      if (dir_entry.path().string().find("smoke") != std::string::npos &&
-          bf::is_directory(dir_entry)) {
-        if (Uninstall(dir_entry.path().filename().string(), is_readonly,
-            RequestResult::NORMAL) != ci::AppInstaller::Result::OK) {
-          LOG(ERROR) << "Cannot uninstall smoke test app: "
-              << dir_entry.path().filename().string();
-        }
-      }
-    }
-  }
-}
-
-void UninstallAllSmokeApps(uid_t uid) {
-  if (getuid() == 0) {
-    bf::path root_path = kPreloadApps;
-    UninstallAllAppsInDirectory(root_path, true);
-  }
-  bf::path apps_rw = ci::GetRootAppPath(false, uid);
-  UninstallAllAppsInDirectory(apps_rw, false);
-}
+#include "unit_tests/smoke_utils.h"
 
-}  // namespace
 
 namespace common_installer {
 
diff --git a/src/unit_tests/smoke_utils.cc b/src/unit_tests/smoke_utils.cc
new file mode 100644 (file)
index 0000000..b2cacbb
--- /dev/null
@@ -0,0 +1,601 @@
+// Copyright (c) 2017 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/filesystem/operations.hpp>
+#include <boost/range/iterator_range.hpp>
+#include <boost/system/error_code.hpp>
+
+
+#include <common/step/configuration/step_fail.h>
+#include <common/utils/subprocess.h>
+#include <common/utils/user_util.h>
+#include <common/request.h>
+
+#include <gtest/gtest.h>
+#include <gtest/gtest-death-test.h>
+
+#include <pkgmgr-info.h>
+#include <signal.h>
+#include <unistd.h>
+#include <tzplatform_config.h>
+#include <vconf.h>
+#include <vconf-internal-keys.h>
+
+#include <array>
+#include <cstdio>
+#include <cstdlib>
+#include <functional>
+
+#include "tpk/tpk_app_query_interface.h"
+
+#include "unit_tests/smoke_utils.h"
+
+
+const uid_t kGlobalUserUid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
+const uid_t kGlobalUserGid = tzplatform_getgid(TZ_SYS_GLOBALAPP_USER);
+const uid_t kDefaultUserUid = tzplatform_getuid(TZ_SYS_DEFAULT_USER);
+// TODO(s89.jang): Test local case also
+const uid_t kTestUserId = kGlobalUserUid;
+const gid_t kTestGroupId = kGlobalUserGid;
+const char kSystemShareGroupName[] = "system_share";
+const std::string& kTestUserIdStr = std::to_string(kTestUserId);
+const std::string& kDefaultUserIdStr = std::to_string(kDefaultUserUid);
+const char kLegacyExtImageDir[] = "legacy_extimage_dir";
+const char kMigrateTestDBName[] = "app2sd_migrate.db";
+
+const bf::path kSmokePackagesDirectory =
+    "/usr/share/tpk-backend-ut/test_samples/smoke/";
+
+// common entries
+const std::vector<std::string> kDBEntries = {
+  {".pkgmgr_parser.db"},
+  {".pkgmgr_parser.db-journal"},
+  {".pkgmgr_cert.db"},
+  {".pkgmgr_cert.db-journal"},
+  {".app2sd.db"},
+  {".app2sd.db-journal"},
+};
+// globaluser entries
+const char kGlobalManifestDir[] = "/opt/share/packages";
+const char kSkelDir[] = "/etc/skel/apps_rw";
+const char kPreloadApps[] = "/usr/apps";
+const char kPreloadManifestDir[] = "/usr/share/packages";
+const char kPreloadIcons[] = "/usr/share/icons";
+
+
+
+bool TouchFile(const bf::path& path) {
+  FILE* f = fopen(path.c_str(), "w+");
+  if (!f)
+    return false;
+  fclose(f);
+  return true;
+}
+
+
+void RemoveAllRecoveryFiles() {
+  bf::path root_path = ci::GetRootAppPath(false,
+      kTestUserId);
+  if (!bf::exists(root_path))
+    return;
+  for (auto& dir_entry : boost::make_iterator_range(
+      bf::directory_iterator(root_path), bf::directory_iterator())) {
+    if (bf::is_regular_file(dir_entry)) {
+      if (dir_entry.path().string().find("/tpk-recovery")
+          != std::string::npos) {
+        bs::error_code error;
+        bf::remove(dir_entry.path(), error);
+      }
+    }
+  }
+}
+
+bf::path FindRecoveryFile() {
+  bf::path root_path = ci::GetRootAppPath(false,
+      kTestUserId);
+  for (auto& dir_entry : boost::make_iterator_range(
+      bf::directory_iterator(root_path), bf::directory_iterator())) {
+    if (bf::is_regular_file(dir_entry)) {
+      if (dir_entry.path().string().find("/tpk-recovery")
+          != std::string::npos) {
+        return dir_entry.path();
+      }
+    }
+  }
+  return {};
+}
+
+bool ValidateFileContentInPackage(const std::string& pkgid,
+                                  const std::string& relative,
+                                  const std::string& expected,
+                                  bool is_readonly) {
+  bf::path root_path = ci::GetRootAppPath(is_readonly, kTestUserId);
+  bf::path file_path = root_path / pkgid / relative;
+  if (!bf::exists(file_path)) {
+    LOG(ERROR) << file_path << " doesn't exist";
+    return false;
+  }
+  FILE* handle = fopen(file_path.c_str(), "r");
+  if (!handle) {
+    LOG(ERROR) << file_path << " cannot  be open";
+    return false;
+  }
+  std::string content;
+  std::array<char, 200> buffer;
+  while (fgets(buffer.data(), buffer.size(), handle)) {
+    content += buffer.data();
+  }
+  fclose(handle);
+  return content == expected;
+}
+
+void ValidatePackageRWFS(const std::string& pkgid, uid_t uid) {
+  bf::path root_path = ci::GetRootAppPath(false, uid);
+  bf::path package_path = root_path / pkgid;
+  bf::path data_path = package_path / "data";
+  bf::path cache_path = package_path / "cache";
+  bf::path shared_data_path = package_path / "shared" / "data";
+
+  ASSERT_TRUE(bf::exists(data_path));
+  ASSERT_TRUE(bf::exists(cache_path));
+
+  struct stat stats;
+  stat(data_path.c_str(), &stats);
+  // gid of RW dirs should be system_share
+  boost::optional<gid_t> system_share =
+      ci::GetGidByGroupName(kSystemShareGroupName);
+  ASSERT_EQ(uid, stats.st_uid);
+  ASSERT_EQ(*system_share, stats.st_gid);
+  if (bf::exists(shared_data_path)) {
+    stat(shared_data_path.c_str(), &stats);
+    ASSERT_EQ(uid, stats.st_uid);
+    ASSERT_EQ(*system_share, stats.st_gid);
+  }
+
+  stat(cache_path.c_str(), &stats);
+  ASSERT_EQ(uid, stats.st_uid);
+  ASSERT_EQ(*system_share, stats.st_gid);
+}
+
+void ValidatePackageFS(const std::string& pkgid, const std::string& appid,
+    uid_t uid, gid_t gid, bool is_readonly) {
+  bf::path root_path = ci::GetRootAppPath(is_readonly, uid);
+  bf::path package_path = root_path / pkgid;
+  bf::path shared_path = package_path / "shared";
+  ASSERT_TRUE(bf::exists(root_path));
+  ASSERT_TRUE(bf::exists(package_path));
+  ASSERT_TRUE(bf::exists(shared_path));
+
+  bf::path manifest_path =
+      bf::path(getUserManifestPath(uid, is_readonly)) / (pkgid + ".xml");
+  ASSERT_TRUE(bf::exists(manifest_path));
+
+  // backups should not exist
+  bf::path package_backup = ci::GetBackupPathForPackagePath(package_path);
+  bf::path manifest_backup = ci::GetBackupPathForManifestFile(manifest_path);
+  ASSERT_FALSE(bf::exists(package_backup));
+  ASSERT_FALSE(bf::exists(manifest_backup));
+
+  for (bf::recursive_directory_iterator iter(package_path);
+      iter != bf::recursive_directory_iterator(); ++iter) {
+    if (bf::is_symlink(symlink_status(iter->path())))
+      continue;
+    if (iter->path().filename() == "data" ||
+        iter->path().filename() == ".mmc")
+      continue;
+    struct stat stats;
+    stat(iter->path().c_str(), &stats);
+    ASSERT_EQ(uid, stats.st_uid);
+    ASSERT_EQ(gid, stats.st_gid);
+  }
+}
+
+void PackageCheckCleanup(const std::string& pkgid, const std::string&,
+                         bool is_readonly) {
+  bf::path root_path = ci::GetRootAppPath(is_readonly,
+      kTestUserId);
+  bf::path package_path = root_path / pkgid;
+  ASSERT_FALSE(bf::exists(package_path));
+
+  bf::path manifest_path = bf::path(getUserManifestPath(
+      kTestUserId, is_readonly)) / (pkgid + ".xml");
+  ASSERT_FALSE(bf::exists(manifest_path));
+
+  // backups should not exist
+  bf::path package_backup = ci::GetBackupPathForPackagePath(package_path);
+  bf::path manifest_backup = ci::GetBackupPathForManifestFile(manifest_path);
+  ASSERT_FALSE(bf::exists(package_backup));
+  ASSERT_FALSE(bf::exists(manifest_backup));
+}
+
+void ValidatePackage(const std::string& pkgid, const std::string& appid,
+    bool is_readonly) {
+  ASSERT_TRUE(ci::QueryIsPackageInstalled(
+      pkgid, ci::GetRequestMode(kTestUserId), kTestUserId));
+  ValidatePackageFS(pkgid, appid, kTestUserId,
+      kTestGroupId, is_readonly);
+  if (kTestUserId == kGlobalUserUid) {
+    ci::UserList list = ci::GetUserList();
+    for (auto& l : list)
+      ValidatePackageRWFS(pkgid, std::get<0>(l));
+  } else {
+    ValidatePackageRWFS(pkgid, kTestUserId);
+  }
+}
+
+void ValidateExternalPackage_FS(const std::string& pkgid,
+    const std::string& appid, uid_t uid) {
+  ASSERT_EQ(app2ext_usr_enable_external_pkg(pkgid.c_str(), uid), 0);
+  bf::path root_path = ci::GetRootAppPath(false, uid);
+  ASSERT_TRUE(bf::exists(root_path / pkgid / ".mmc" / "bin"));
+  ASSERT_TRUE(bf::exists(root_path / pkgid / ".mmc" / "lib"));
+  ASSERT_TRUE(bf::exists(root_path / pkgid / ".mmc" / "res"));
+  ValidatePackage(pkgid, appid);
+  ASSERT_EQ(app2ext_usr_disable_external_pkg(pkgid.c_str(), uid), 0);
+}
+
+void ValidateExternalPackage(const std::string& pkgid,
+    const std::string& appid) {
+  std::string storage = ci::QueryStorageForPkgId(pkgid, kTestUserId);
+  bf::path ext_mount_path = ci::GetExternalCardPath();
+  if (bf::is_empty(ext_mount_path)) {
+    LOG(INFO) << "Sdcard not exists!";
+    ASSERT_EQ(storage, "installed_internal");
+  } else {
+    ASSERT_EQ(storage, "installed_external");
+  }
+  ValidateExternalPackage_FS(pkgid, appid, kTestUserId);
+}
+
+void CheckPackageNonExistance(const std::string& pkgid,
+                              const std::string& appid,
+                              bool is_readonly) {
+  ASSERT_FALSE(ci::QueryIsPackageInstalled(
+      pkgid, ci::GetRequestMode(kTestUserId), kTestUserId));
+  PackageCheckCleanup(pkgid, appid, is_readonly);
+  if (kTestUserId == kGlobalUserUid) {
+    bf::path skel_path(kSkelDir);
+    ASSERT_FALSE(bf::exists(skel_path / pkgid));
+    ci::UserList list = ci::GetUserList();
+    for (auto& l : list) {
+      bf::path root_path = ci::GetRootAppPath(false, std::get<0>(l));
+      bf::path package_path = root_path / pkgid;
+      ASSERT_FALSE(bf::exists(package_path));
+    }
+  }
+}
+
+std::unique_ptr<ci::AppQueryInterface> CreateQueryInterface() {
+  std::unique_ptr<ci::AppQueryInterface> query_interface(
+      new tpk::TpkAppQueryInterface());
+  return query_interface;
+}
+
+std::unique_ptr<ci::AppInstaller> CreateInstaller(ci::PkgMgrPtr pkgmgr) {
+  std::unique_ptr<ci::AppInstaller> installer(new tpk::TpkInstaller(pkgmgr));
+  return installer;
+}
+
+ci::AppInstaller::Result RunInstallerWithPkgrmgr(ci::PkgMgrPtr pkgmgr,
+                                                 RequestResult mode) {
+  std::unique_ptr<ci::AppInstaller> installer = CreateInstaller(pkgmgr);
+  switch (mode) {
+  case RequestResult::FAIL:
+    installer->AddStep<ci::configuration::StepFail>();
+    break;
+  default:
+    break;
+  }
+  return installer->Run();
+}
+ci::AppInstaller::Result CallBackend(int argc,
+                                     const char* argv[],
+                                     RequestResult mode) {
+  TestPkgmgrInstaller pkgmgr_installer;
+  std::unique_ptr<ci::AppQueryInterface> query_interface =
+      CreateQueryInterface();
+  auto pkgmgr =
+      ci::PkgMgrInterface::Create(argc, const_cast<char**>(argv),
+                                  &pkgmgr_installer,
+                                  query_interface.get());
+  if (!pkgmgr) {
+    LOG(ERROR) << "Failed to initialize pkgmgr interface";
+    return ci::AppInstaller::Result::UNKNOWN;
+  }
+  return RunInstallerWithPkgrmgr(pkgmgr, mode);
+}
+
+ci::AppInstaller::Result Install(const bf::path& path,
+                                 RequestResult mode) {
+  const char* argv[] = {"", "-i", path.c_str(), "-u", kTestUserIdStr.c_str()};
+  return CallBackend(SIZEOFARRAY(argv), argv, mode);
+}
+
+ci::AppInstaller::Result InstallPreload(const bf::path& path,
+    RequestResult mode) {
+  const char* argv[] = {"", "-i", path.c_str(), "--preload"};
+  return CallBackend(SIZEOFARRAY(argv), argv, mode);
+}
+
+bool CheckAvailableExternalPath() {
+  bf::path ext_mount_path = ci::GetExternalCardPath();
+  LOG(DEBUG) << "ext_mount_path :" << ext_mount_path;
+  if (ext_mount_path.empty()) {
+    LOG(ERROR) << "Sdcard not exists!";
+    return false;
+  }
+  return true;
+}
+
+ci::AppInstaller::Result InstallExternal(const bf::path& path,
+                                         RequestResult mode) {
+  int default_storage = 0;
+  vconf_get_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT,
+      &default_storage);
+  vconf_set_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT, 1);
+
+  const char* argv[] = {"", "-i", path.c_str(), "-u", kTestUserIdStr.c_str()};
+  ci::AppInstaller::Result result = CallBackend(SIZEOFARRAY(argv), argv, mode);
+
+  vconf_set_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT,
+      default_storage);
+  return result;
+}
+
+ci::AppInstaller::Result MigrateLegacyExternalImage(const std::string& pkgid,
+    const bf::path& path,
+    const bf::path& legacy_path,
+    RequestResult mode) {
+  if (InstallExternal(path) != ci::AppInstaller::Result::OK) {
+    LOG(ERROR) << "Failed to install application. Cannot perform Migrate";
+    return ci::AppInstaller::Result::ERROR;
+  }
+
+  bf::path ext_mount_path = ci::GetExternalCardPath();
+  if (bf::is_empty(ext_mount_path)) {
+    LOG(ERROR) << "Sdcard not exists!";
+    return ci::AppInstaller::Result::ERROR;
+  }
+  bf::path app2sd_path = ext_mount_path / "app2sd";
+
+  char *image_name = app2ext_usr_getname_image(pkgid.c_str(),
+                     kGlobalUserUid);
+  if (!image_name) {
+    LOG(ERROR) << "Failed to get external image name";
+    return ci::AppInstaller::Result::ERROR;
+  }
+  bf::path org_image = app2sd_path / image_name;
+  free(image_name);
+
+  bs::error_code error;
+  bf::remove(org_image, error);
+  if (error) {
+    LOG(ERROR) << "Failed to remove org image";
+    return ci::AppInstaller::Result::ERROR;
+  }
+
+  bf::path db_path = tzplatform_getenv(TZ_SYS_DB);
+  bf::path app2sd_db = db_path / ".app2sd.db";
+  bf::path app2sd_db_journal = db_path / ".app2sd.db-journal";
+  bf::remove(app2sd_db, error);
+  if (error) {
+    LOG(ERROR) << "Failed to remove app2sd db";
+    return ci::AppInstaller::Result::ERROR;
+  }
+  bf::remove(app2sd_db_journal, error);
+  if (error) {
+    LOG(ERROR) << "Failed to remove app2sd journal db";
+    return ci::AppInstaller::Result::ERROR;
+  }
+
+  bf::path app2sd_migrate_db = legacy_path / kMigrateTestDBName;
+  if (!ci::CopyFile(app2sd_migrate_db, app2sd_db)) {
+    LOG(ERROR) << "Failed to copy test db";
+    return ci::AppInstaller::Result::ERROR;
+  }
+
+  bf::path legacy_src = legacy_path / pkgid;
+  bf::path legacy_dst = app2sd_path / pkgid;
+  if (!ci::CopyFile(legacy_src, legacy_dst)) {
+    LOG(ERROR) << "Failed to copy test image";
+    return ci::AppInstaller::Result::ERROR;
+  }
+  const char* argv[] = {"", "--migrate-extimg", pkgid.c_str(),
+                       "-u", kDefaultUserIdStr.c_str()};
+  return CallBackend(SIZEOFARRAY(argv), argv, mode);
+}
+
+ci::AppInstaller::Result InstallWithTEP(
+    const bf::path& path,
+    const bf::path& tep,
+    RequestResult mode) {
+  const char* argv[] = {"", "-i", path.c_str(), "-u", kTestUserIdStr.c_str(),
+                        "-e", tep.c_str()};
+  return CallBackend(SIZEOFARRAY(argv), argv, mode);
+}
+
+ci::AppInstaller::Result Update(const bf::path& path_old,
+                                const bf::path& path_new,
+                                RequestResult mode) {
+  if (Install(path_old) != ci::AppInstaller::Result::OK) {
+    LOG(ERROR) << "Failed to install application. Cannot update";
+    return ci::AppInstaller::Result::UNKNOWN;
+  }
+  return Install(path_new, mode);
+}
+
+ci::AppInstaller::Result MountInstall(const bf::path& path,
+    RequestResult mode) {
+  const char* argv[] = {"", "-w", path.c_str(), "-u", kTestUserIdStr.c_str()};
+  return CallBackend(SIZEOFARRAY(argv), argv, mode);
+}
+
+ci::AppInstaller::Result MountInstallWithTEP(
+    const bf::path& path,
+    const bf::path& tep,
+    RequestResult mode) {
+  const char* argv[] = {"", "-w", path.c_str(), "-u", kTestUserIdStr.c_str(),
+      "-e", tep.c_str()};
+  return CallBackend(SIZEOFARRAY(argv), argv, mode);
+}
+
+ci::AppInstaller::Result MountUpdate(const bf::path& path_old,
+                                     const bf::path& path_new,
+                                     RequestResult mode) {
+  if (MountInstall(path_old) != ci::AppInstaller::Result::OK) {
+    LOG(ERROR) << "Failed to mount-install application. Cannot mount-update";
+    return ci::AppInstaller::Result::UNKNOWN;
+  }
+  return MountInstall(path_new, mode);
+}
+
+ci::AppInstaller::Result Uninstall(const std::string& pkgid, bool is_readonly,
+                                   RequestResult mode) {
+  if (is_readonly) {
+    const char* argv[] = {"", "-d", pkgid.c_str(), "--preload",
+        "--force-remove"};
+    return CallBackend(SIZEOFARRAY(argv), argv, mode);
+  } else {
+    const char* argv[] = {"", "-d", pkgid.c_str(), "-u",
+        kTestUserIdStr.c_str()};
+    return CallBackend(SIZEOFARRAY(argv), argv, mode);
+  }
+}
+
+ci::AppInstaller::Result EnablePackage(const std::string& path,
+                                       RequestResult mode) {
+  const char* argv[] = {"", "-A", path.c_str(), "-u", kTestUserIdStr.c_str()};
+  return CallBackend(SIZEOFARRAY(argv), argv, mode);
+}
+
+ci::AppInstaller::Result DisablePackage(const std::string& path,
+                                        RequestResult mode) {
+  const char* argv[] = {"", "-D", path.c_str(), "-u", kTestUserIdStr.c_str()};
+  return CallBackend(SIZEOFARRAY(argv), argv, mode);
+}
+
+ci::AppInstaller::Result RDSUpdate(const bf::path& path,
+                                   const std::string& pkgid,
+                                   RequestResult mode) {
+  if (Install(path) != ci::AppInstaller::Result::OK) {
+    LOG(ERROR) << "Failed to install application. Cannot perform RDS";
+    return ci::AppInstaller::Result::UNKNOWN;
+  }
+  const char* argv[] = {"", "-r", pkgid.c_str(), "-u",
+      kTestUserIdStr.c_str()};
+  return CallBackend(SIZEOFARRAY(argv), argv, mode);
+}
+
+ci::AppInstaller::Result DeltaInstall(const bf::path& path,
+    const bf::path& delta_package) {
+  if (Install(path) != ci::AppInstaller::Result::OK) {
+    LOG(ERROR) << "Failed to install application. Cannot perform RDS";
+    return ci::AppInstaller::Result::UNKNOWN;
+  }
+  return Install(delta_package);
+}
+
+ci::AppInstaller::Result Recover(const bf::path& recovery_file,
+                                 RequestResult mode) {
+  const char* argv[] = {"", "-b", recovery_file.c_str(), "-u",
+      kTestUserIdStr.c_str()};
+  return CallBackend(SIZEOFARRAY(argv), argv, mode);
+}
+
+void BackupPath(const bf::path& path) {
+  bf::path backup_path = path.string() + ".bck";
+  std::cout << "Backup path: " << path << " to " << backup_path << std::endl;
+  bs::error_code error;
+  bf::remove_all(backup_path, error);
+  if (error)
+    LOG(ERROR) << "Remove failed: " << backup_path
+    << " (" << error.message() << ")";
+  if (bf::exists(path)) {
+    bf::rename(path, backup_path, error);
+    if (error)
+      LOG(ERROR) << "Failed to setup test environment. Does some previous"
+      << " test crashed? Path: "
+      << backup_path << " should not exist.";
+    assert(!error);
+  }
+}
+
+void RestorePath(const bf::path& path) {
+  bf::path backup_path = path.string() + ".bck";
+  std::cout << "Restore path: " << path << " from " << backup_path << std::endl;
+  bs::error_code error;
+  bf::remove_all(path, error);
+  if (error)
+    LOG(ERROR) << "Remove failed: " << path
+    << " (" << error.message() << ")";
+  if (bf::exists(backup_path)) {
+    bf::rename(backup_path, path, error);
+    if (error)
+      LOG(ERROR) << "Failed to restore backup path: " << backup_path
+      << " (" << error.message() << ")";
+  }
+}
+
+std::vector<bf::path> SetupBackupDirectories(uid_t uid) {
+  std::vector<bf::path> entries;
+  bf::path db_dir = bf::path(tzplatform_getenv(TZ_SYS_DB));
+  if (uid != kGlobalUserUid)
+    db_dir = db_dir / "user" / std::to_string(uid);
+  for (auto e : kDBEntries) {
+    bf::path path = db_dir / e;
+    entries.emplace_back(path);
+  }
+
+  if (getuid() == 0) {
+    entries.emplace_back(kPreloadApps);
+    entries.emplace_back(kPreloadManifestDir);
+    entries.emplace_back(kPreloadIcons);
+  }
+
+  if (uid == kGlobalUserUid) {
+    entries.emplace_back(kSkelDir);
+    entries.emplace_back(kGlobalManifestDir);
+    ci::UserList list = ci::GetUserList();
+    for (auto l : list) {
+      bf::path apps = std::get<2>(l) / "apps_rw";
+      entries.emplace_back(apps);
+    }
+  } else {
+    tzplatform_set_user(uid);
+    bf::path approot = tzplatform_getenv(TZ_USER_APPROOT);
+    tzplatform_reset_user();
+    entries.emplace_back(approot);
+  }
+
+  bf::path apps_rw = ci::GetRootAppPath(false, uid);
+  entries.emplace_back(apps_rw);
+
+  return entries;
+}
+
+void UninstallAllAppsInDirectory(bf::path dir, bool is_readonly) {
+  if (bf::exists(dir)) {
+    for (auto& dir_entry : boost::make_iterator_range(
+        bf::directory_iterator(dir), bf::directory_iterator())) {
+      if (dir_entry.path().string().find("smoke") != std::string::npos &&
+          bf::is_directory(dir_entry)) {
+        if (Uninstall(dir_entry.path().filename().string(), is_readonly,
+            RequestResult::NORMAL) != ci::AppInstaller::Result::OK) {
+          LOG(ERROR) << "Cannot uninstall smoke test app: "
+              << dir_entry.path().filename().string();
+        }
+      }
+    }
+  }
+}
+
+void UninstallAllSmokeApps(uid_t uid) {
+  if (getuid() == 0) {
+    bf::path root_path = kPreloadApps;
+    UninstallAllAppsInDirectory(root_path, true);
+  }
+  bf::path apps_rw = ci::GetRootAppPath(false, uid);
+  UninstallAllAppsInDirectory(apps_rw, false);
+}
+
diff --git a/src/unit_tests/smoke_utils.h b/src/unit_tests/smoke_utils.h
new file mode 100644 (file)
index 0000000..6a29aef
--- /dev/null
@@ -0,0 +1,212 @@
+// Copyright (c) 2017 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.
+
+#ifndef UNIT_TESTS_SMOKE_UTILS_H_
+#define UNIT_TESTS_SMOKE_UTILS_H_
+
+#include <boost/filesystem/path.hpp>
+
+#include <common/pkgmgr_interface.h>
+#include <common/tzip_interface.h>
+#include <common/pkgmgr_query.h>
+#include <common/utils/file_util.h>
+#include <common/paths.h>
+
+#include <string>
+#include <vector>
+#include <memory>
+
+#include "tpk/tpk_installer.h"
+
+#define SIZEOFARRAY(ARR)                                                       \
+  sizeof(ARR) / sizeof(ARR[0])                                                 \
+
+
+namespace bf = boost::filesystem;
+namespace bs = boost::system;
+namespace ci = common_installer;
+
+extern const uid_t kGlobalUserUid;
+extern const uid_t kGlobalUserGid;
+extern const uid_t kDefaultUserUid;
+// TODO(s89.jang): Test local case also
+extern const uid_t kTestUserId;
+extern const gid_t kTestGroupId;
+extern const char kSystemShareGroupName[];
+extern const std::string& kTestUserIdStr;
+extern const std::string& kDefaultUserIdStr;
+extern const char kLegacyExtImageDir[];
+extern const char kMigrateTestDBName[];
+
+extern const bf::path kSmokePackagesDirectory;
+
+// common entries
+extern const std::vector<std::string> kDBEntries;
+
+// globaluser entries
+extern const char kGlobalManifestDir[];
+extern const char kSkelDir[];
+extern const char kPreloadApps[];
+extern const char kPreloadManifestDir[];
+extern const char kPreloadIcons[];
+
+enum class RequestResult {
+  NORMAL,
+  FAIL
+};
+
+class ScopedTzipInterface {
+ public:
+  explicit ScopedTzipInterface(const std::string& pkgid)
+      : pkg_path_(bf::path(ci::GetRootAppPath(false,
+            kTestUserId)) / pkgid),
+        interface_(ci::GetMountLocation(pkg_path_)),
+        mounted_(true) {
+    interface_.MountZip(ci::GetZipPackageLocation(pkg_path_, pkgid));
+  }
+
+  void Release() {
+    if (mounted_) {
+      interface_.UnmountZip();
+      mounted_ = false;
+    }
+  }
+
+  ~ScopedTzipInterface() {
+    Release();
+  }
+
+ private:
+  bf::path pkg_path_;
+  ci::TzipInterface interface_;
+  bool mounted_;
+};
+
+
+class TestPkgmgrInstaller : public ci::PkgmgrInstallerInterface {
+ public:
+  bool CreatePkgMgrInstaller(pkgmgr_installer** installer,
+                             ci::InstallationMode* mode) {
+    *installer = pkgmgr_installer_offline_new();
+    if (!*installer)
+      return false;
+    *mode = ci::InstallationMode::ONLINE;
+    return true;
+  }
+
+  bool ShouldCreateSignal() const {
+    return false;
+  }
+};
+
+bool TouchFile(const bf::path& path);
+
+void RemoveAllRecoveryFiles();
+
+bf::path FindRecoveryFile();
+
+bool ValidateFileContentInPackage(const std::string& pkgid,
+                                  const std::string& relative,
+                                  const std::string& expected,
+                                  bool is_readonly = false);
+
+void ValidatePackageRWFS(const std::string& pkgid, uid_t uid);
+
+void ValidatePackageFS(const std::string& pkgid, const std::string& appid,
+    uid_t uid, gid_t gid, bool is_readonly = false);
+
+void PackageCheckCleanup(const std::string& pkgid, const std::string&,
+                         bool is_readonly = false);
+
+void ValidatePackage(const std::string& pkgid, const std::string& appid,
+    bool is_readonly = false);
+
+void ValidateExternalPackage_FS(const std::string& pkgid,
+    const std::string& appid, uid_t uid);
+
+void ValidateExternalPackage(const std::string& pkgid,
+    const std::string& appid);
+
+void CheckPackageNonExistance(const std::string& pkgid,
+                              const std::string& appid,
+                              bool is_readonly = false);
+
+bool CheckAvailableExternalPath();
+
+std::unique_ptr<ci::AppQueryInterface> CreateQueryInterface();
+
+std::unique_ptr<ci::AppInstaller> CreateInstaller(ci::PkgMgrPtr pkgmgr);
+
+ci::AppInstaller::Result RunInstallerWithPkgrmgr(ci::PkgMgrPtr pkgmgr,
+                                                 RequestResult mode);
+ci::AppInstaller::Result CallBackend(int argc,
+                                     const char* argv[],
+                                     RequestResult mode);
+
+ci::AppInstaller::Result Install(const bf::path& path,
+                                 RequestResult mode = RequestResult::NORMAL);
+
+ci::AppInstaller::Result InstallPreload(const bf::path& path,
+    RequestResult mode = RequestResult::NORMAL);
+
+
+ci::AppInstaller::Result InstallExternal(const bf::path& path,
+    RequestResult mode = RequestResult::NORMAL);
+
+ci::AppInstaller::Result MigrateLegacyExternalImage(const std::string& pkgid,
+    const bf::path& path,
+    const bf::path& legacy_path,
+    RequestResult mode = RequestResult::NORMAL);
+
+ci::AppInstaller::Result InstallWithTEP(
+    const bf::path& path,
+    const bf::path& tep,
+    RequestResult mode = RequestResult::NORMAL);
+
+ci::AppInstaller::Result Update(const bf::path& path_old,
+                                const bf::path& path_new,
+                                RequestResult mode = RequestResult::NORMAL);
+
+ci::AppInstaller::Result MountInstall(const bf::path& path,
+    RequestResult mode = RequestResult::NORMAL);
+
+ci::AppInstaller::Result MountInstallWithTEP(
+    const bf::path& path,
+    const bf::path& tep,
+    RequestResult mode = RequestResult::NORMAL);
+
+ci::AppInstaller::Result MountUpdate(const bf::path& path_old,
+    const bf::path& path_new,
+    RequestResult mode = RequestResult::NORMAL);
+
+ci::AppInstaller::Result Uninstall(const std::string& pkgid, bool is_readonly,
+                                   RequestResult mode = RequestResult::NORMAL);
+
+ci::AppInstaller::Result EnablePackage(const std::string& path,
+    RequestResult mode = RequestResult::NORMAL);
+
+ci::AppInstaller::Result DisablePackage(const std::string& path,
+    RequestResult mode = RequestResult::NORMAL);
+
+ci::AppInstaller::Result RDSUpdate(const bf::path& path,
+                                   const std::string& pkgid,
+                                   RequestResult mode = RequestResult::NORMAL);
+
+ci::AppInstaller::Result DeltaInstall(const bf::path& path,
+    const bf::path& delta_package);
+
+ci::AppInstaller::Result Recover(const bf::path& recovery_file,
+    RequestResult mode = RequestResult::NORMAL);
+
+void BackupPath(const bf::path& path);
+
+void RestorePath(const bf::path& path);
+
+std::vector<bf::path> SetupBackupDirectories(uid_t uid);
+
+void UninstallAllAppsInDirectory(bf::path dir, bool is_readonly);
+
+void UninstallAllSmokeApps(uid_t uid);
+
+#endif  // UNIT_TESTS_SMOKE_UTILS_H_