[SmokeTest] Add request mode choice
[platform/core/appfw/wgt-backend.git] / src / unit_tests / smoke_test.cc
index e8e9a02..0cbbfb8 100644 (file)
@@ -6,24 +6,37 @@
 #include <boost/filesystem/path.hpp>
 #include <boost/range/iterator_range.hpp>
 #include <boost/system/error_code.hpp>
+#include <boost/format.hpp>
+#include <boost/program_options.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 <gum/gum-user.h>
+#include <gum/gum-user-service.h>
+#include <gum/common/gum-user-types.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 <getopt.h>
 
 #include <array>
 #include <cstdio>
 #include <cstdlib>
 #include <vector>
+#include <regex>
 
 #include "hybrid/hybrid_installer.h"
 #include "wgt/wgt_app_query_interface.h"
 
 namespace bf = boost::filesystem;
 namespace bs = boost::system;
+namespace bo = boost::program_options;
 namespace ci = common_installer;
 
 namespace {
+ci::RequestMode ParseRequestMode(int argc,  char** argv) {
+  bo::options_description desc("Available options");
+  desc.add_options()
+      ("request-mode", bo::value<std::string>(), "set request mode")
+      ("global-request,g", "set request mode to global")
+      ("user-request,u", "set request mode to user");
+
+  bo::variables_map vm;
+  bo::store(bo::parse_command_line(argc, argv, desc), vm);
+  bo::notify(vm);
+
+  if (vm.count("global-request")) {
+    std::cout << "Request mode was set to global." << std::endl;
+    return ci::RequestMode::GLOBAL;
+  }
+  if (vm.count("user-request")) {
+    std::cout << "Request mode was set to user." << std::endl;
+    return ci::RequestMode::USER;
+  }
+  if (vm.count("request-mode")) {
+    if (vm["request-mode"].as<std::string>() == "global") {
+      std::cout << "Request mode was set to global." << std::endl;
+      return ci::RequestMode::GLOBAL;
+    }
+    if (vm["request-mode"].as<std::string>() == "user") {
+      std::cout << "Request mode was set to user." << std::endl;
+      return ci::RequestMode::USER;
+    }
+    std::cout << "Cannot set request mode to "
+              << vm["request-mode"].as<std::string>() << std::endl;
+    std::cout << "Request mode was set to global." << std::endl;
+    return ci::RequestMode::GLOBAL;
+
+  }
+}
+
+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);
+uid_t kTestUserId = kGlobalUserUid;
+gid_t kTestGroupId = kGlobalUserGid;
+std::string kTestUserIdStr = std::to_string(kTestUserId);
+const char kNormalUserName[] = "smokeuser";
+const char kSystemShareGroupName[] = "system_share";
+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/wgt-backend-ut/test_samples/smoke/";
 
-const char kApplicationDir[] = ".applications";
-const char kApplicationDirBackup[] = ".applications.bck";
-const char KUserAppsDir[] = "apps_rw";
-const char KUserAppsDirBackup[] = "apps_rw.bck";
+enum RWDirectory {
+    DATA,
+    CACHE,
+    SHARED_CACHE,
+    SHARED_DATA,
+    SHARED_TRUSTED
+};
+
+const char* rwDirectories[] = {
+  "data",
+  "cache",
+  "shared/cache",
+  "shared/data",
+  "shared/trusted",
+};
+
+// 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,
@@ -54,18 +142,28 @@ enum class RequestResult {
 class ScopedTzipInterface {
  public:
   explicit ScopedTzipInterface(const std::string& pkgid)
-      : pkg_path_(bf::path(ci::GetRootAppPath(false)) / pkgid),
-        interface_(ci::GetMountLocation(pkg_path_)) {
+      : 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() {
-    interface_.UnmountZip();
+    Release();
   }
 
  private:
   bf::path pkg_path_;
   ci::TzipInterface interface_;
+  bool mounted_;
 };
 
 class TestPkgmgrInstaller : public ci::PkgmgrInstallerInterface {
@@ -97,14 +195,72 @@ bool TouchFile(const bf::path& path) {
   return true;
 }
 
+bool AddUser(const char *user_name) {
+  GumUser* user = nullptr;
+  user = gum_user_create_sync(FALSE);
+  if (user == nullptr)
+    LOG(WARNING) << "Failed to create gum user! (user name: "
+                 << user_name << ")";
+  g_object_set(G_OBJECT(user), "username", user_name, "usertype",
+      GUM_USERTYPE_NORMAL, NULL);
+  gboolean rval = FALSE;
+  rval = gum_user_add_sync(user);
+  g_object_unref(user);
+  return rval;
+}
+
+bool DeleteUser(const char *user_name, bool rem_home_dir) {
+  bool rval = FALSE;
+  GumUser* guser = gum_user_get_by_name_sync(user_name, FALSE);
+  if(guser)
+    rval = gum_user_delete_sync(guser, rem_home_dir);
+  return rval;
+}
+
+bool AddTestUser(const char *user_name) {
+  std::cout << "Adding test user: " << user_name << std::endl;
+  bool ret = AddUser(user_name);
+  if (boost::optional<uid_t> uid = ci::GetUidByUserName(user_name)) {
+    kTestUserId = *uid;
+    kTestUserIdStr = std::to_string(kTestUserId);
+    std::cout << "User created properly: uid=" << *uid;
+    if (boost::optional<gid_t> gid = ci::GetGidByUid(*uid)) {
+      kTestGroupId = *gid;
+      std::cout << " gid=" << *gid;
+    }
+    std::cout << std::endl;
+    return true;
+  }
+  LOG(ERROR) << "Adding test user failed";
+  return false;
+}
+
+bool DeleteTestUser(const char *user_name) {
+  std::cout << "Deleting test user: " << user_name << std::endl;
+  uid_t test_uid;
+  if (boost::optional<uid_t> uid = ci::GetUidByUserName(user_name))
+    test_uid = *uid;
+  bool ret = DeleteUser(user_name, true);
+  if (boost::optional<uid_t> uid = ci::GetUidByUserName(user_name));
+  else {
+    std::cout << "User deleted properly: user_name=" << user_name
+              << " uid=" << test_uid << std::endl;
+    return true;
+  }
+  LOG(ERROR) << "Deleting test user failed";
+  return false;
+}
+
 void RemoveAllRecoveryFiles() {
-  bf::path root_path = ci::GetRootAppPath(false);
+  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("/recovery") != std::string::npos) {
+      if (dir_entry.path().string().find("/wgt-recovery")
+          != std::string::npos) {
         bs::error_code error;
         bf::remove(dir_entry.path(), error);
       }
@@ -113,11 +269,13 @@ void RemoveAllRecoveryFiles() {
 }
 
 bf::path FindRecoveryFile() {
-  bf::path root_path = ci::GetRootAppPath(false);
+  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("/recovery") != std::string::npos) {
+      if (dir_entry.path().string().find("/wgt-recovery")
+          != std::string::npos) {
         return dir_entry.path();
       }
     }
@@ -125,11 +283,17 @@ bf::path FindRecoveryFile() {
   return {};
 }
 
+bf::path GetPackageRoot(const std::string& pkgid, uid_t uid) {
+  bf::path root_path = ci::GetRootAppPath(false, uid);
+  return root_path / pkgid;
+}
+
 bool ValidateFileContentInPackage(const std::string& pkgid,
                                   const std::string& relative,
-                                  const std::string& expected) {
-  bf::path root_path = ci::GetRootAppPath(false);
-  bf::path file_path = root_path / pkgid / relative;
+                                  const std::string& expected,
+                                  bool is_readonly = false) {
+  bf::path file_path = ci::GetRootAppPath(is_readonly, kTestUserId);
+  file_path = file_path / pkgid / relative;
   if (!bf::exists(file_path)) {
     LOG(ERROR) << file_path << " doesn't exist";
     return false;
@@ -148,21 +312,77 @@ bool ValidateFileContentInPackage(const std::string& pkgid,
   return content == expected;
 }
 
+void AddDataFiles(const std::string& pkgid, uid_t uid) {
+  if (uid == kGlobalUserUid) {
+    ci::UserList list = ci::GetUserList();
+    for (auto l : list) {
+      auto pkg_path = GetPackageRoot(pkgid, std::get<0>(l));
+      ASSERT_TRUE(TouchFile(pkg_path / "data" / "file1.txt"));
+      ASSERT_TRUE(TouchFile(pkg_path / "data" / "file2.txt"));
+    }
+  } else {
+    auto pkg_path = GetPackageRoot(pkgid, uid);
+    ASSERT_TRUE(TouchFile(pkg_path / "data" / "file1.txt"));
+    ASSERT_TRUE(TouchFile(pkg_path / "data" / "file2.txt"));
+  }
+}
+
+void ValidateDataFiles(const std::string& pkgid, uid_t uid) {
+  if (uid == kGlobalUserUid) {
+    ci::UserList list = ci::GetUserList();
+    for (auto l : list) {
+      auto pkg_path = GetPackageRoot(pkgid, std::get<0>(l));
+      ASSERT_TRUE(bf::exists(pkg_path / "data" / "file1.txt"));
+      ASSERT_TRUE(bf::exists(pkg_path / "data" / "file2.txt"));
+    }
+  } else {
+    auto pkg_path = GetPackageRoot(pkgid, uid);
+    ASSERT_TRUE(bf::exists(pkg_path / "data" / "file1.txt"));
+    ASSERT_TRUE(bf::exists(pkg_path / "data" / "file2.txt"));
+  }
+}
+
+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 / rwDirectories[DATA];
+  bf::path cache_path = package_path / rwDirectories[CACHE];
+  bf::path shared_data_path = package_path / rwDirectories[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::vector<std::string>& appids) {
-  bf::path root_path = ci::GetRootAppPath(false);
+                       const std::vector<std::string>& appids,
+                       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 data_path = package_path / "data";
   bf::path shared_path = package_path / "shared";
-  bf::path cache_path = package_path / "cache";
   ASSERT_TRUE(bf::exists(root_path));
   ASSERT_TRUE(bf::exists(package_path));
-  ASSERT_TRUE(bf::exists(data_path));
   ASSERT_TRUE(bf::exists(shared_path));
-  ASSERT_TRUE(bf::exists(cache_path));
 
   bf::path manifest_path =
-      bf::path(getUserManifestPath(getuid(), false)) / (pkgid + ".xml");
+      bf::path(getUserManifestPath(uid, is_readonly)) / (pkgid + ".xml");
   ASSERT_TRUE(bf::exists(manifest_path));
 
   for (auto& appid : appids) {
@@ -183,16 +403,35 @@ void ValidatePackageFS(const std::string& pkgid,
   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;
+    bool is_rw_dir = false;
+    for(const auto rw_dir : rwDirectories) {
+      bf::path rw_dir_path = rw_dir;
+      is_rw_dir |= ci::MakeRelativePath(iter->path(), package_path) == rw_dir_path;
+    }
+    if (is_rw_dir || iter->path().filename() == ".mmc") {
+      iter.no_push();
+      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::vector<std::string>& appids) {
-  bf::path root_path = ci::GetRootAppPath(false);
+    const std::vector<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(getuid(), false)) / (pkgid + ".xml");
+  bf::path manifest_path = bf::path(getUserManifestPath(kTestUserId,
+      is_readonly)) / (pkgid + ".xml");
   ASSERT_FALSE(bf::exists(manifest_path));
 
   // backups should not exist
@@ -203,15 +442,75 @@ void PackageCheckCleanup(const std::string& pkgid,
 }
 
 void ValidatePackage(const std::string& pkgid,
-                     const std::vector<std::string>& appids) {
-  ASSERT_TRUE(ci::QueryIsPackageInstalled(pkgid, ci::GetRequestMode()));
-  ValidatePackageFS(pkgid, appids);
+    const std::vector<std::string>& appids, bool is_readonly = false) {
+  ASSERT_TRUE(ci::QueryIsPackageInstalled(
+      pkgid, ci::GetRequestMode(kTestUserId), kTestUserId));
+  ValidatePackageFS(pkgid, appids, 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 ValidateExternalPackageFS(const std::string& pkgid,
+                               const std::vector<std::string>& appids,
+                               uid_t uid, gid_t gid) {
+  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" / "res"));
+  ValidatePackageFS(pkgid, appids, uid, gid, false);
+  ASSERT_EQ(app2ext_usr_disable_external_pkg(pkgid.c_str(), uid), 0);
+}
+
+void ValidateExternalPackage(const std::string& pkgid,
+                             const std::vector<std::string>& appids) {
+  ASSERT_TRUE(ci::QueryIsPackageInstalled(
+      pkgid, ci::GetRequestMode(kTestUserId),
+      kTestUserId));
+  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");
+  }
+  ValidateExternalPackageFS(pkgid, appids, kTestUserId, kTestGroupId);
+  if (kTestUserId == kGlobalUserUid) {
+    ci::UserList list = ci::GetUserList();
+    for (auto& l : list)
+      ValidatePackageRWFS(pkgid, std::get<0>(l));
+  } else {
+    ValidatePackageRWFS(pkgid, kTestUserId);
+  }
 }
 
 void CheckPackageNonExistance(const std::string& pkgid,
                               const std::vector<std::string>& appids) {
-  ASSERT_FALSE(ci::QueryIsPackageInstalled(pkgid, ci::GetRequestMode()));
+  ASSERT_FALSE(ci::QueryIsPackageInstalled(
+      pkgid, ci::GetRequestMode(kTestUserId),
+      kTestUserId));
   PackageCheckCleanup(pkgid, appids);
+  if (kTestUserId == kGlobalUserUid) {
+      ci::UserList list = ci::GetUserList();
+      bf::path skel_path(kSkelDir);
+      ASSERT_FALSE(bf::exists(skel_path / pkgid));
+      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));
+      }
+  }
+}
+
+void CheckPackageReadonlyNonExistance(const std::string& pkgid,
+                                      const std::vector<std::string>& appids) {
+  ASSERT_FALSE(ci::QueryIsPackageInstalled(
+      pkgid, ci::GetRequestMode(kTestUserId), kTestUserId));
+  PackageCheckCleanup(pkgid, appids, true);
 }
 
 std::unique_ptr<ci::AppQueryInterface> CreateQueryInterface() {
@@ -268,53 +567,138 @@ ci::AppInstaller::Result CallBackend(int argc,
 ci::AppInstaller::Result Install(const bf::path& path,
                                  PackageType type,
                                  RequestResult mode = RequestResult::NORMAL) {
-  const char* argv[] = {"", "-i", path.c_str()};
+  const char* argv[] = {"", "-i", path.c_str(), "-u", kTestUserIdStr.c_str()};
   return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
 }
 
-ci::AppInstaller::Result Update(const bf::path& path_old,
-                                const bf::path& path_new,
-                                PackageType type,
-                                RequestResult mode = RequestResult::NORMAL) {
-  if (Install(path_old, type) != ci::AppInstaller::Result::OK) {
-    LOG(ERROR) << "Failed to install application. Cannot update";
-    return ci::AppInstaller::Result::UNKNOWN;
+ci::AppInstaller::Result InstallPreload(const bf::path& path, PackageType type,
+    RequestResult mode = RequestResult::NORMAL) {
+  const char* argv[] = {"", "-i", path.c_str(), "--preload"};
+  return CallBackend(SIZEOFARRAY(argv), argv, type, 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 Install(path_new, type, mode);
+  return true;
 }
 
-ci::AppInstaller::Result MountInstall(const bf::path& path,
-    PackageType type, RequestResult mode = RequestResult::NORMAL) {
-  const char* argv[] = {"", "-w", path.c_str()};
-  return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
+ci::AppInstaller::Result InstallExternal(const bf::path& path,
+                                 PackageType type,
+                                 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, type, mode);
+
+  vconf_set_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT,
+                default_storage);
+  return result;
 }
 
-ci::AppInstaller::Result MountUpdate(const bf::path& path_old,
-    const bf::path& path_new, PackageType type,
-    RequestResult mode = RequestResult::NORMAL) {
-  if (MountInstall(path_old, type) != ci::AppInstaller::Result::OK) {
-    LOG(ERROR) << "Failed to mount-install application. Cannot mount-update";
-    return ci::AppInstaller::Result::UNKNOWN;
+ci::AppInstaller::Result MigrateLegacyExternalImage(const std::string& pkgid,
+                                 const bf::path& path,
+                                 const bf::path& legacy_path,
+                                 PackageType type,
+                                 RequestResult mode = RequestResult::NORMAL) {
+  if (InstallExternal(path, type) != 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;
   }
-  return MountInstall(path_new, type, mode);
+
+  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, type, mode);
+}
+
+ci::AppInstaller::Result MountInstall(const bf::path& path,
+    PackageType type, RequestResult mode = RequestResult::NORMAL) {
+  const char* argv[] = {"", "-w", path.c_str(), "-u", kTestUserIdStr.c_str()};
+  return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
 }
 
 ci::AppInstaller::Result Uninstall(const std::string& pkgid,
                                    PackageType type,
+                                   bool is_preload,
                                    RequestResult mode = RequestResult::NORMAL) {
-  const char* argv[] = {"", "-d", pkgid.c_str()};
-  return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
+  if (is_preload) {
+    const char* argv[] = {"", "-d", pkgid.c_str(), "--preload",
+        "--force-remove"};
+    return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
+  } else {
+    const char* argv[] = {"", "-d", pkgid.c_str(), "-u",
+        kTestUserIdStr.c_str()};
+    return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
+  }
 }
 
-ci::AppInstaller::Result Reinstall(const bf::path& path,
-                                   const bf::path& delta_dir,
+ci::AppInstaller::Result RDSUpdate(const bf::path& path,
+                                   const std::string& pkgid,
                                    PackageType type,
                                    RequestResult mode = RequestResult::NORMAL) {
   if (Install(path, type) != ci::AppInstaller::Result::OK) {
     LOG(ERROR) << "Failed to install application. Cannot perform RDS";
     return ci::AppInstaller::Result::UNKNOWN;
   }
-  const char* argv[] = {"", "-r", delta_dir.c_str()};
+  const char* argv[] = {"", "-r", pkgid.c_str(), "-u",
+                        kTestUserIdStr.c_str()};
   return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
 }
 
@@ -327,42 +711,127 @@ ci::AppInstaller::Result DeltaInstall(const bf::path& path,
   return Install(delta_package, type);
 }
 
-ci::AppInstaller::Result Clear(const std::string& pkgid,
-                                   PackageType type,
-                                   RequestResult mode = RequestResult::NORMAL) {
-  const char* argv[] = {"", "-c", pkgid.c_str()};
-  return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
-}
-
 ci::AppInstaller::Result EnablePackage(const std::string& pkgid,
                                   PackageType type,
                                   RequestResult mode = RequestResult::NORMAL) {
-  const char* argv[] = {"", "-A", pkgid.c_str()};
+  const char* argv[] = {"", "-A", pkgid.c_str(), "-u", kTestUserIdStr.c_str()};
   return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
 }
 
 ci::AppInstaller::Result DisablePackage(const std::string& pkgid,
                                   PackageType type,
                                   RequestResult mode = RequestResult::NORMAL) {
-  const char* argv[] = {"", "-D", pkgid.c_str()};
+  const char* argv[] = {"", "-D", pkgid.c_str(), "-u", kTestUserIdStr.c_str()};
   return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
 }
 
 ci::AppInstaller::Result Recover(const bf::path& recovery_file,
                                  PackageType type,
                                  RequestResult mode = RequestResult::NORMAL) {
-  const char* argv[] = {"", "-b", recovery_file.c_str()};
-  TestPkgmgrInstaller pkgmgr_installer;
-  std::unique_ptr<ci::AppQueryInterface> query_interface =
-      CreateQueryInterface();
-  auto pkgmgr =
-      ci::PkgMgrInterface::Create(SIZEOFARRAY(argv), const_cast<char**>(argv),
-                                  &pkgmgr_installer, query_interface.get());
-  if (!pkgmgr) {
-    LOG(ERROR) << "Failed to initialize pkgmgr interface";
-    return ci::AppInstaller::Result::UNKNOWN;
+  const char* argv[] = {"", "-b", recovery_file.c_str(), "-u",
+                        kTestUserIdStr.c_str()};
+  return CallBackend(SIZEOFARRAY(argv), argv, type, 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);
   }
-  return RunInstallerWithPkgrmgr(pkgmgr, type, mode);
+}
+
+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() {
+  std::vector<bf::path> entries;
+  bf::path db_dir = bf::path(tzplatform_getenv(TZ_SYS_DB));
+  if (kTestUserId != kGlobalUserUid)
+    db_dir = db_dir / "user" / std::to_string(kTestUserId);
+  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 (kTestUserId == 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(kTestUserId);
+    bf::path approot = tzplatform_getenv(TZ_USER_APPROOT);
+    tzplatform_reset_user();
+    entries.emplace_back(approot);
+  }
+
+  bf::path apps_rw = ci::GetRootAppPath(false, kTestUserId);
+  entries.emplace_back(apps_rw);
+
+  return entries;
+}
+
+void UninstallAllAppsInDirectory(bf::path dir, bool is_preload) {
+  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)) {
+        std::string package = dir_entry.path().filename().string();
+        std::regex pkg_regex("smoke[a-zA-Z]{3,}[1-9]{2,}");
+        if (std::regex_match(package, pkg_regex)) {
+          if(Uninstall(dir_entry.path().filename().string(), PackageType::WGT,
+              is_preload, RequestResult::NORMAL) !=
+              ci::AppInstaller::Result::OK) {
+            LOG(ERROR) << "Cannot uninstall smoke test app: "
+                << dir_entry.path().filename().string();
+          }
+        }
+      }
+    }
+  }
+}
+
+void UninstallAllSmokeApps(ci::RequestMode request_mode) {
+  if (getuid() == 0 && request_mode == ci::RequestMode::GLOBAL) {
+    bf::path root_path = kPreloadApps;
+    UninstallAllAppsInDirectory(root_path, true);
+  }
+  bf::path apps_rw = ci::GetRootAppPath(false, kTestUserId);
+  UninstallAllAppsInDirectory(apps_rw, false);
 }
 
 }  // namespace
@@ -371,50 +840,50 @@ namespace common_installer {
 
 class SmokeEnvironment : public testing::Environment {
  public:
-  explicit SmokeEnvironment(const bf::path& home) : home_(home) {
+  explicit SmokeEnvironment(ci::RequestMode mode) {\
+    request_mode_ = mode;
   }
   void SetUp() override {
-    bs::error_code error;
-    bf::remove_all(home_ / kApplicationDirBackup, error);
-    bf::remove_all(home_ / KUserAppsDirBackup, error);
-    if (bf::exists(home_ / KUserAppsDir)) {
-      bf::rename(home_ / KUserAppsDir, home_ / KUserAppsDirBackup, error);
-      if (error)
-        LOG(ERROR) << "Failed to setup test environment. Does some previous"
-                   << " test crashed? Directory: "
-                   << (home_ / KUserAppsDirBackup) << " should not exist.";
-      assert(!error);
-    }
-    if (bf::exists(home_ / kApplicationDir)) {
-      bf::rename(home_ / kApplicationDir, home_ / kApplicationDirBackup, error);
-      if (error)
-        LOG(ERROR) << "Failed to setup test environment. Does some previous"
-                   << " test crashed? Directory: "
-                   << (home_ / kApplicationDirBackup) << " should not exist.";
-      assert(!error);
+    if (request_mode_ == ci::RequestMode::USER)
+      ASSERT_TRUE(AddTestUser(kNormalUserName));
+    else {
+      kTestUserId = kGlobalUserUid;
+      kTestGroupId = kGlobalUserGid;
+      kTestUserIdStr = std::to_string(kTestUserId);
     }
+    backups_ = SetupBackupDirectories();
+    for (auto& path : backups_)
+      BackupPath(path);
   }
   void TearDown() override {
-    bs::error_code error;
-    bf::remove_all(home_ / kApplicationDir, error);
-    bf::remove_all(home_ / KUserAppsDir, error);
-    if (bf::exists(home_ / KUserAppsDirBackup))
-      bf::rename(home_ / KUserAppsDirBackup, home_ / KUserAppsDir, error);
-    if (bf::exists(home_ / kApplicationDirBackup))
-      bf::rename(home_ / kApplicationDirBackup, home_ / kApplicationDir, error);
+    ASSERT_TRUE(request_mode_ == ci::RequestMode::GLOBAL ||
+                (request_mode_ == ci::RequestMode::USER &&
+                kGlobalUserUid != kTestUserId));
+    UninstallAllSmokeApps(request_mode_);
+    for (auto& path : backups_)
+      RestorePath(path);
+    if (request_mode_ == ci::RequestMode::USER)
+      ASSERT_TRUE(DeleteTestUser(kNormalUserName));
   }
 
  private:
-  bf::path home_;
+  ci::RequestMode request_mode_;
+  std::vector<bf::path> backups_;
 };
 
 class SmokeTest : public testing::Test {
 };
 
+class PreloadSmokeTest : public testing::Test {
+  void SetUp() override {
+    ASSERT_EQ(kGlobalUserUid, kTestUserId);
+  }
+};
+
 TEST_F(SmokeTest, InstallationMode) {
   bf::path path = kSmokePackagesDirectory / "InstallationMode.wgt";
-  std::string pkgid = "smokeapp03";
-  std::string appid = "smokeapp03.InstallationMode";
+  std::string pkgid = "smokewgt03";
+  std::string appid = "smokewgt03.InstallationMode";
   ASSERT_EQ(Install(path, PackageType::WGT), ci::AppInstaller::Result::OK);
   ValidatePackage(pkgid, {appid});
 }
@@ -422,44 +891,54 @@ TEST_F(SmokeTest, InstallationMode) {
 TEST_F(SmokeTest, UpdateMode) {
   bf::path path_old = kSmokePackagesDirectory / "UpdateMode.wgt";
   bf::path path_new = kSmokePackagesDirectory / "UpdateMode_2.wgt";
-  std::string pkgid = "smokeapp04";
-  std::string appid = "smokeapp04.UpdateMode";
-  ASSERT_EQ(Update(path_old, path_new, PackageType::WGT),
-            ci::AppInstaller::Result::OK);
+  std::string pkgid = "smokewgt04";
+  std::string appid = "smokewgt04.UpdateMode";
+  ASSERT_EQ(Install(path_old, PackageType::WGT), ci::AppInstaller::Result::OK);
+  AddDataFiles(pkgid, kTestUserId);
+  ASSERT_EQ(Install(path_new, PackageType::WGT), ci::AppInstaller::Result::OK);
   ValidatePackage(pkgid, {appid});
 
   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "2\n"));
+  ValidateDataFiles(pkgid, kTestUserId);
 }
 
 TEST_F(SmokeTest, DeinstallationMode) {
   bf::path path = kSmokePackagesDirectory / "DeinstallationMode.wgt";
-  std::string pkgid = "smokeapp05";
-  std::string appid = "smokeapp05.DeinstallationMode";
+  std::string pkgid = "smokewgt05";
+  std::string appid = "smokewgt05.DeinstallationMode";
   ASSERT_EQ(Install(path, PackageType::WGT),
             ci::AppInstaller::Result::OK);
-  ASSERT_EQ(Uninstall(pkgid, PackageType::WGT), ci::AppInstaller::Result::OK);
+  ASSERT_EQ(Uninstall(pkgid, PackageType::WGT, false),
+            ci::AppInstaller::Result::OK);
   CheckPackageNonExistance(pkgid, {appid});
 }
 
 TEST_F(SmokeTest, RDSMode) {
   bf::path path = kSmokePackagesDirectory / "RDSMode.wgt";
+  std::string pkgid = "smokewgt11";
+  std::string appid = "smokewgt11.RDSMode";
   bf::path delta_directory = kSmokePackagesDirectory / "delta_dir/";
-  std::string pkgid = "smokeapp11";
-  std::string appid = "smokeapp11.RDSMode";
-  ASSERT_EQ(Reinstall(path, delta_directory, PackageType::WGT),
+  bf::path sdk_expected_directory =
+      bf::path(ci::GetRootAppPath(false, kTestUserId)) / "tmp" / pkgid;
+  bs::error_code error;
+  bf::create_directories(sdk_expected_directory.parent_path(), error);
+  ASSERT_FALSE(error);
+  ASSERT_TRUE(CopyDir(delta_directory, sdk_expected_directory));
+  ASSERT_EQ(RDSUpdate(path, pkgid, PackageType::WGT),
             ci::AppInstaller::Result::OK);
   ValidatePackage(pkgid, {appid});
 
   // Check delta modifications
-  bf::path root_path = ci::GetRootAppPath(false);
-  ASSERT_FALSE(bf::exists(root_path / pkgid / "res" / "wgt" / "DELETED"));
-  ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "ADDED"));
-  ValidateFileContentInPackage(pkgid, "res/wgt/MODIFIED", "2\n");
+  ASSERT_FALSE(bf::exists(GetPackageRoot(pkgid, kTestUserId) /
+      "res" / "wgt" / "DELETED"));
+  ASSERT_TRUE(bf::exists(GetPackageRoot(pkgid, kTestUserId) /
+      "res" / "wgt" / "ADDED"));
+  ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/MODIFIED", "2\n"));
 }
 
 TEST_F(SmokeTest, EnablePkg) {
   bf::path path = kSmokePackagesDirectory / "EnablePkg.wgt";
-  std::string pkgid = "smokeapp22";
+  std::string pkgid = "smokewgt22";
   ASSERT_EQ(Install(path, PackageType::WGT),
             ci::AppInstaller::Result::OK);
   ASSERT_EQ(DisablePackage(pkgid, PackageType::WGT),
@@ -467,66 +946,55 @@ TEST_F(SmokeTest, EnablePkg) {
   ASSERT_EQ(EnablePackage(pkgid, PackageType::WGT),
             ci::AppInstaller::Result::OK);
 
-  ASSERT_TRUE(ci::QueryIsPackageInstalled(pkgid, ci::GetRequestMode()));
+  ASSERT_TRUE(ci::QueryIsPackageInstalled(pkgid,
+      ci::GetRequestMode(kTestUserId),
+      kTestUserId));
 }
 
 TEST_F(SmokeTest, DisablePkg) {
   bf::path path = kSmokePackagesDirectory / "DisablePkg.wgt";
-  std::string pkgid = "smokeapp21";
-  std::string appid = "smokeapp21.DisablePkg";
+  std::string pkgid = "smokewgt21";
+  std::string appid = "smokewgt21.DisablePkg";
   ASSERT_EQ(Install(path, PackageType::WGT),
             ci::AppInstaller::Result::OK);
   ASSERT_EQ(DisablePackage(pkgid, PackageType::WGT),
             ci::AppInstaller::Result::OK);
-  ASSERT_FALSE(ci::QueryIsPackageInstalled(pkgid, ci::GetRequestMode()));
-  ValidatePackageFS(pkgid, {appid});
-}
-
-TEST_F(SmokeTest, ClearMode) {
-  bf::path path = kSmokePackagesDirectory / "ClearMode.wgt";
-  std::string pkgid = "smokeapp20";
-  std::string appid = "smokeapp20.ClearMode";
-  ASSERT_EQ(Install(path, PackageType::WGT),
-            ci::AppInstaller::Result::OK);
-  bf::path root_path = ci::GetRootAppPath(false);
-  bs::error_code error;
-  bf::create_directory(root_path / pkgid / "data" / "dir", error);
-  ASSERT_FALSE(error);
-  ASSERT_TRUE(TouchFile(root_path / pkgid / "data" / "dir" / "file"));
-  ASSERT_TRUE(TouchFile(root_path / pkgid / "data" / "file"));
-  ASSERT_EQ(Clear(pkgid, PackageType::WGT), ci::AppInstaller::Result::OK);
+  ASSERT_TRUE(ci::QueryIsDisabledPackage(pkgid, kTestUserId));
   ValidatePackage(pkgid, {appid});
-  ASSERT_FALSE(bf::exists(root_path / pkgid / "data" / "dir" / "file"));
-  ASSERT_FALSE(bf::exists(root_path / pkgid / "res" / "file"));
 }
 
 TEST_F(SmokeTest, DeltaMode) {
   bf::path path = kSmokePackagesDirectory / "DeltaMode.wgt";
   bf::path delta_package = kSmokePackagesDirectory / "DeltaMode.delta";
-  std::string pkgid = "smokeapp17";
-  std::string appid = "smokeapp17.DeltaMode";
+  std::string pkgid = "smokewgt17";
+  std::string appid = "smokewgt17.DeltaMode";
   ASSERT_EQ(DeltaInstall(path, delta_package, PackageType::WGT),
             ci::AppInstaller::Result::OK);
   ValidatePackage(pkgid, {appid});
 
   // Check delta modifications
-  bf::path root_path = ci::GetRootAppPath(false);
-  ASSERT_FALSE(bf::exists(root_path / pkgid / "res" / "wgt" / "DELETED"));
-  ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "ADDED"));
-  ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "css" / "style.css"));  // NOLINT
-  ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "images" / "tizen_32.png"));  // NOLINT
-  ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "js" / "main.js"));
-  ValidateFileContentInPackage(pkgid, "res/wgt/MODIFIED", "version 2\n");
+  ASSERT_FALSE(bf::exists(GetPackageRoot(pkgid, kTestUserId) /
+      "res" / "wgt" / "DELETED"));
+  ASSERT_TRUE(bf::exists(GetPackageRoot(pkgid, kTestUserId) /
+      "res" / "wgt" / "ADDED"));
+  ASSERT_TRUE(bf::exists(GetPackageRoot(pkgid, kTestUserId) /
+      "res" / "wgt" / "css" / "style.css"));
+  ASSERT_TRUE(bf::exists(GetPackageRoot(pkgid, kTestUserId) /
+      "res" / "wgt" / "images" / "tizen_32.png"));
+  ASSERT_TRUE(bf::exists(GetPackageRoot(pkgid, kTestUserId) /
+      "res" / "wgt" / "js" / "main.js"));
+  ASSERT_TRUE(ValidateFileContentInPackage(
+      pkgid, "res/wgt/MODIFIED", "version 2\n"));
 }
 
 TEST_F(SmokeTest, RecoveryMode_ForInstallation) {
   bf::path path = kSmokePackagesDirectory / "RecoveryMode_ForInstallation.wgt";
   Subprocess backend_crash("/usr/bin/wgt-backend-ut/smoke-test-helper");
-  backend_crash.Run("-i", path.string());
+  backend_crash.Run("-i", path.string(), "-u", kTestUserIdStr.c_str());
   ASSERT_NE(backend_crash.Wait(), 0);
 
-  std::string pkgid = "smokeapp09";
-  std::string appid = "smokeapp09.RecoveryModeForInstallation";
+  std::string pkgid = "smokewgt09";
+  std::string appid = "smokewgt09.RecoveryModeForInstallation";
   bf::path recovery_file = FindRecoveryFile();
   ASSERT_FALSE(recovery_file.empty());
   ASSERT_EQ(Recover(recovery_file, PackageType::WGT),
@@ -538,15 +1006,14 @@ TEST_F(SmokeTest, RecoveryMode_ForUpdate) {
   bf::path path_old = kSmokePackagesDirectory / "RecoveryMode_ForUpdate.wgt";
   bf::path path_new = kSmokePackagesDirectory / "RecoveryMode_ForUpdate_2.wgt";
   RemoveAllRecoveryFiles();
-  Subprocess backend_test("/usr/bin/wgt-backend");
-  backend_test.Run("-i", path_old.string());
-  ASSERT_EQ(backend_test.Wait(), 0);
+  ASSERT_EQ(Install(path_old, PackageType::WGT), ci::AppInstaller::Result::OK);
+  std::string pkgid = "smokewgt10";
+  std::string appid = "smokewgt10.RecoveryModeForUpdate";
+  AddDataFiles(pkgid, kTestUserId);
   Subprocess backend_crash("/usr/bin/wgt-backend-ut/smoke-test-helper");
-  backend_crash.Run("-i", path_new.string());
+  backend_crash.Run("-i", path_new.string(), "-u", kTestUserIdStr.c_str());
   ASSERT_NE(backend_crash.Wait(), 0);
 
-  std::string pkgid = "smokeapp10";
-  std::string appid = "smokeapp10.RecoveryModeForUpdate";
   bf::path recovery_file = FindRecoveryFile();
   ASSERT_FALSE(recovery_file.empty());
   ASSERT_EQ(Recover(recovery_file, PackageType::WGT),
@@ -554,22 +1021,91 @@ TEST_F(SmokeTest, RecoveryMode_ForUpdate) {
   ValidatePackage(pkgid, {appid});
 
   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "1\n"));
+  ValidateDataFiles(pkgid, kTestUserId);
+}
+
+TEST_F(SmokeTest, RecoveryMode_ForDelta) {
+  bf::path path_old = kSmokePackagesDirectory / "RecoveryMode_ForDelta.wgt";
+  bf::path path_new = kSmokePackagesDirectory / "RecoveryMode_ForDelta.delta";
+  RemoveAllRecoveryFiles();
+  ASSERT_EQ(Install(path_old, PackageType::WGT), ci::AppInstaller::Result::OK);
+  Subprocess backend_crash("/usr/bin/wgt-backend-ut/smoke-test-helper");
+  backend_crash.Run("-i", path_new.string(), "-u", kTestUserIdStr.c_str());
+  ASSERT_NE(backend_crash.Wait(), 0);
+
+  std::string pkgid = "smokewgt30";
+  std::string appid = "smokewgt30.RecoveryModeForDelta";
+  bf::path recovery_file = FindRecoveryFile();
+  ASSERT_FALSE(recovery_file.empty());
+  ASSERT_EQ(Recover(recovery_file, PackageType::WGT),
+            ci::AppInstaller::Result::OK);
+  ValidatePackage(pkgid, {appid});
+
+  ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "1\n"));
+}
+
+TEST_F(SmokeTest, RecoveryMode_ForMountInstall) {
+  bf::path path = kSmokePackagesDirectory / "RecoveryMode_ForMountInstall.wgt";
+  RemoveAllRecoveryFiles();
+  Subprocess backend_crash("/usr/bin/wgt-backend-ut/smoke-test-helper");
+  backend_crash.Run("-w", path.string(), "-u", kTestUserIdStr.c_str());
+  ASSERT_NE(backend_crash.Wait(), 0);
+
+  std::string pkgid = "smokewgt31";
+  std::string appid = "smokewgt31.RecoveryModeForMountInstall";
+  bf::path recovery_file = FindRecoveryFile();
+  ASSERT_FALSE(recovery_file.empty());
+  ASSERT_EQ(Recover(recovery_file, PackageType::WGT),
+            ci::AppInstaller::Result::OK);
+  CheckPackageNonExistance(pkgid, {appid});
+}
+
+TEST_F(SmokeTest, RecoveryMode_ForMountUpdate) {
+  bf::path path_old =
+      kSmokePackagesDirectory / "RecoveryMode_ForMountUpdate.wgt";
+  bf::path path_new =
+      kSmokePackagesDirectory / "RecoveryMode_ForMountUpdate_2.wgt";
+  std::string pkgid = "smokewgt32";
+  std::string appid = "smokewgt32.RecoveryModeForMountUpdate";
+  RemoveAllRecoveryFiles();
+  ASSERT_EQ(MountInstall(path_old, PackageType::WGT),
+            ci::AppInstaller::Result::OK);
+  AddDataFiles(pkgid, kTestUserId);
+  Subprocess backend_crash("/usr/bin/wgt-backend-ut/smoke-test-helper");
+  backend_crash.Run("-w", path_new.string(), "-u", kTestUserIdStr.c_str());
+  ASSERT_NE(backend_crash.Wait(), 0);
+
+  // Filesystem may be mounted after crash
+  ScopedTzipInterface poweroff_unmount_interface(pkgid);
+  poweroff_unmount_interface.Release();
+
+  bf::path recovery_file = FindRecoveryFile();
+  ASSERT_FALSE(recovery_file.empty());
+  ASSERT_EQ(Recover(recovery_file, PackageType::WGT),
+            ci::AppInstaller::Result::OK);
+
+  ScopedTzipInterface interface(pkgid);
+  ValidatePackage(pkgid, {appid});
+  ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "1\n"));
+  ValidateDataFiles(pkgid, kTestUserId);
 }
 
 TEST_F(SmokeTest, InstallationMode_GoodSignature) {
+  // pkgid: smokewgt08
   bf::path path = kSmokePackagesDirectory / "InstallationMode_GoodSignature.wgt";  // NOLINT
   ASSERT_EQ(Install(path, PackageType::WGT), ci::AppInstaller::Result::OK);
 }
 
 TEST_F(SmokeTest, InstallationMode_WrongSignature) {
+  // pkgid: smokewgt12
   bf::path path = kSmokePackagesDirectory / "InstallationMode_WrongSignature.wgt";  // NOLINT
   ASSERT_EQ(Install(path, PackageType::WGT), ci::AppInstaller::Result::ERROR);
 }
 
 TEST_F(SmokeTest, InstallationMode_Rollback) {
   bf::path path = kSmokePackagesDirectory / "InstallationMode_Rollback.wgt";
-  std::string pkgid = "smokeapp06";
-  std::string appid = "smokeapp06.InstallationModeRollback";
+  std::string pkgid = "smokewgt06";
+  std::string appid = "smokewgt06.InstallationModeRollback";
   ASSERT_EQ(Install(path, PackageType::WGT, RequestResult::FAIL),
             ci::AppInstaller::Result::ERROR);
   CheckPackageNonExistance(pkgid, {appid});
@@ -578,22 +1114,45 @@ TEST_F(SmokeTest, InstallationMode_Rollback) {
 TEST_F(SmokeTest, UpdateMode_Rollback) {
   bf::path path_old = kSmokePackagesDirectory / "UpdateMode_Rollback.wgt";
   bf::path path_new = kSmokePackagesDirectory / "UpdateMode_Rollback_2.wgt";
-  std::string pkgid = "smokeapp07";
-  std::string appid = "smokeapp07.UpdateModeRollback";
-  ASSERT_EQ(Update(path_old, path_new, PackageType::WGT, RequestResult::FAIL),
-                   ci::AppInstaller::Result::ERROR);
+  std::string pkgid = "smokewgt07";
+  std::string appid = "smokewgt07.UpdateModeRollback";
+  ASSERT_EQ(Install(path_old, PackageType::WGT), ci::AppInstaller::Result::OK);
+  AddDataFiles(pkgid, kTestUserId);
+  ASSERT_EQ(Install(path_new, PackageType::WGT, RequestResult::FAIL),
+                    ci::AppInstaller::Result::ERROR);
   ValidatePackage(pkgid, {appid});
 
   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "1\n"));
+  ValidateDataFiles(pkgid, kTestUserId);
+}
+
+TEST_F(SmokeTest, DeltaMode_Rollback) {
+  bf::path path = kSmokePackagesDirectory / "DeltaMode_Rollback.wgt";
+  bf::path delta_package = kSmokePackagesDirectory / "DeltaMode_Rollback.delta";
+  std::string pkgid = "smokewgt01";
+  std::string appid = "smokewgt01.DeltaMode";
+  ASSERT_EQ(Install(path, PackageType::WGT), ci::AppInstaller::Result::OK);
+  AddDataFiles(pkgid, kTestUserId);
+  ASSERT_EQ(Install(delta_package, PackageType::WGT, RequestResult::FAIL),
+            ci::AppInstaller::Result::ERROR);
+
+  ValidatePackage(pkgid, {appid});
+  ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/MODIFIED",
+                                           "version 1\n"));
+  ValidateDataFiles(pkgid, kTestUserId);
+  ASSERT_TRUE(bf::exists(GetPackageRoot(pkgid, kTestUserId) /
+                         "res/wgt/DELETED"));
+  ASSERT_FALSE(bf::exists(GetPackageRoot(pkgid, kTestUserId) /
+                          "res/wgt/ADDED"));
 }
 
 TEST_F(SmokeTest, InstallationMode_Hybrid) {
   bf::path path = kSmokePackagesDirectory / "InstallationMode_Hybrid.wgt";
   std::string pkgid = "smokehyb01";
+  // Excutable for native app doesn't create symlink
   std::string appid1 = "smokehyb01.Web";
-  std::string appid2 = "smokehyb01.Native";
   ASSERT_EQ(Install(path, PackageType::HYBRID), ci::AppInstaller::Result::OK);
-  ValidatePackage(pkgid, {appid1, appid2});
+  ValidatePackage(pkgid, {appid1});
 }
 
 TEST_F(SmokeTest, UpdateMode_Hybrid) {
@@ -601,24 +1160,27 @@ TEST_F(SmokeTest, UpdateMode_Hybrid) {
   bf::path path_new = kSmokePackagesDirectory / "UpdateMode_Hybrid_2.wgt";
   std::string pkgid = "smokehyb02";
   std::string appid1 = "smokehyb02.Web";
-  std::string appid2 = "smokehyb02.Native";
-  ASSERT_EQ(Update(path_old, path_new, PackageType::HYBRID),
+  ASSERT_EQ(Install(path_old, PackageType::HYBRID),
             ci::AppInstaller::Result::OK);
-  ValidatePackage(pkgid, {appid1, appid2});
+//  AddDataFiles(pkgid, kTestUserId);
+  ASSERT_EQ(Install(path_new, PackageType::HYBRID),
+            ci::AppInstaller::Result::OK);
+  ValidatePackage(pkgid, {appid1});
 
   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "2\n"));
   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "VERSION", "2\n"));
+//  ValidateDataFiles(pkgid, kTestUserId);
 }
 
 TEST_F(SmokeTest, DeinstallationMode_Hybrid) {
   bf::path path = kSmokePackagesDirectory / "DeinstallationMode_Hybrid.wgt";
   std::string pkgid = "smokehyb03";
   std::string appid1 = "smokehyb03.Web";
-  std::string appid2 = "smokehyb03.Native";
   ASSERT_EQ(Install(path, PackageType::HYBRID),
             ci::AppInstaller::Result::OK);
-  ASSERT_EQ(Uninstall(pkgid, PackageType::WGT), ci::AppInstaller::Result::OK);
-  CheckPackageNonExistance(pkgid, {appid1, appid2});
+  ASSERT_EQ(Uninstall(pkgid, PackageType::HYBRID, false),
+            ci::AppInstaller::Result::OK);
+  CheckPackageNonExistance(pkgid, {appid1});
 }
 
 TEST_F(SmokeTest, DeltaMode_Hybrid) {
@@ -626,13 +1188,13 @@ TEST_F(SmokeTest, DeltaMode_Hybrid) {
   bf::path delta_package = kSmokePackagesDirectory / "DeltaMode_Hybrid.delta";
   std::string pkgid = "smokehyb04";
   std::string appid1 = "smokehyb04.Web";
-  std::string appid2 = "smokehyb04.Native";
   ASSERT_EQ(DeltaInstall(path, delta_package, PackageType::HYBRID),
             ci::AppInstaller::Result::OK);
-  ValidatePackage(pkgid, {appid1, appid2});
+  ValidatePackage(pkgid, {appid1});
 
   // Check delta modifications
-  bf::path root_path = ci::GetRootAppPath(false);
+  bf::path root_path = ci::GetRootAppPath(false,
+      kTestUserId);
   ASSERT_FALSE(bf::exists(root_path / pkgid / "res" / "wgt" / "DELETED"));
   ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "ADDED"));
   ASSERT_FALSE(bf::exists(root_path / pkgid / "lib" / "DELETED"));
@@ -640,14 +1202,127 @@ TEST_F(SmokeTest, DeltaMode_Hybrid) {
   ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "css" / "style.css"));  // NOLINT
   ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "images" / "tizen_32.png"));  // NOLINT
   ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "js" / "main.js"));
-  ValidateFileContentInPackage(pkgid, "res/wgt/MODIFIED", "version 2\n");
-  ValidateFileContentInPackage(pkgid, "lib/MODIFIED", "version 2\n");
+  ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/MODIFIED", "version 2\n"));  // NOLINT
+  ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "lib/MODIFIED", "version 2\n"));  // NOLINT
+}
+
+TEST_F(SmokeTest, MountInstallationMode_Hybrid) {
+  bf::path path = kSmokePackagesDirectory / "MountInstallationMode_Hybrid.wgt";
+  std::string pkgid = "smokehyb05";
+  std::string appid1 = "smokehyb05.web";
+  ASSERT_EQ(MountInstall(path, PackageType::HYBRID),
+            ci::AppInstaller::Result::OK);
+  ScopedTzipInterface interface(pkgid);
+  ValidatePackage(pkgid, {appid1});
+}
+
+TEST_F(SmokeTest, MountUpdateMode_Hybrid) {
+  bf::path path_old = kSmokePackagesDirectory / "MountUpdateMode_Hybrid.wgt";
+  bf::path path_new = kSmokePackagesDirectory / "MountUpdateMode_Hybrid_2.wgt";
+  std::string pkgid = "smokehyb06";
+  std::string appid1 = "smokehyb06.web";
+  ASSERT_EQ(MountInstall(path_old, PackageType::HYBRID),
+            ci::AppInstaller::Result::OK);
+  AddDataFiles(pkgid, kTestUserId);
+  ASSERT_EQ(MountInstall(path_new, PackageType::HYBRID),
+            ci::AppInstaller::Result::OK);
+  ScopedTzipInterface interface(pkgid);
+  ValidatePackage(pkgid, {appid1});
+
+  ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "2\n"));
+  ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "lib/VERSION", "2\n"));
+  ValidateDataFiles(pkgid, kTestUserId);
+}
+
+TEST_F(SmokeTest, InstallationMode_Rollback_Hybrid) {
+  bf::path path = kSmokePackagesDirectory /
+      "InstallationMode_Rollback_Hybrid.wgt";
+  std::string pkgid = "smokehyb07";
+  std::string appid1 = "smokehyb07.web";
+  ASSERT_EQ(Install(path, PackageType::HYBRID, RequestResult::FAIL),
+            ci::AppInstaller::Result::ERROR);
+  CheckPackageNonExistance(pkgid, {appid1});
+}
+
+TEST_F(SmokeTest, UpdateMode_Rollback_Hybrid) {
+  bf::path path_old = kSmokePackagesDirectory /
+      "UpdateMode_Rollback_Hybrid.wgt";
+  bf::path path_new = kSmokePackagesDirectory /
+      "UpdateMode_Rollback_Hybrid_2.wgt";
+  std::string pkgid = "smokehyb08";
+  std::string appid1 = "smokehyb08.web";
+  ASSERT_EQ(Install(path_old, PackageType::HYBRID),
+            ci::AppInstaller::Result::OK);
+  AddDataFiles(pkgid, kTestUserId);
+  ASSERT_EQ(Install(path_new, PackageType::HYBRID,
+      RequestResult::FAIL), ci::AppInstaller::Result::ERROR);
+  ValidatePackage(pkgid, {appid1});
+
+  ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "1\n"));
+  ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "lib/VERSION", "1\n"));
+  ValidateDataFiles(pkgid, kTestUserId);
+}
+
+TEST_F(SmokeTest, DeltaMode_Rollback_Hybrid) {
+  bf::path path = kSmokePackagesDirectory / "DeltaMode_Rollback_Hybrid.wgt";
+  bf::path delta_package = kSmokePackagesDirectory /
+      "DeltaMode_Rollback_Hybrid.delta";
+  std::string pkgid = "smokehyb11";
+  std::string appid1 = "smokehyb11.web";
+  ASSERT_EQ(Install(path, PackageType::HYBRID), ci::AppInstaller::Result::OK);
+  AddDataFiles(pkgid, kTestUserId);
+  ASSERT_EQ(Install(delta_package, PackageType::HYBRID, RequestResult::FAIL),
+            ci::AppInstaller::Result::ERROR);
+
+  ValidatePackage(pkgid, {appid1});
+  // Check delta modifications
+  bf::path root_path = GetPackageRoot(pkgid, kTestUserId);
+  ASSERT_TRUE(bf::exists(root_path / "res" / "wgt" / "DELETED"));
+  ASSERT_FALSE(bf::exists(root_path / "res" / "wgt" / "ADDED"));
+  ASSERT_TRUE(bf::exists(root_path / "lib" / "DELETED"));
+  ASSERT_FALSE(bf::exists(root_path / "lib" / "ADDED"));
+  ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/MODIFIED",
+                                           "version 1\n"));
+  ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "lib/MODIFIED",
+                                           "version 1\n"));
+  ValidateDataFiles(pkgid, kTestUserId);
+}
+
+TEST_F(SmokeTest, MountInstallationMode_Rollback_Hybrid) {
+  bf::path path = kSmokePackagesDirectory /
+      "MountInstallationMode_Rollback_Hybrid.wgt";
+  std::string pkgid = "smokehyb09";
+  std::string appid1 = "smokehyb09.web";
+  ASSERT_EQ(MountInstall(path, PackageType::HYBRID, RequestResult::FAIL),
+      ci::AppInstaller::Result::ERROR);
+  ScopedTzipInterface interface(pkgid);
+  CheckPackageNonExistance(pkgid, {appid1});
+}
+
+TEST_F(SmokeTest, MountUpdateMode_Rollback_Hybrid) {
+  bf::path path_old = kSmokePackagesDirectory /
+      "MountUpdateMode_Rollback_Hybrid.wgt";
+  bf::path path_new = kSmokePackagesDirectory /
+      "MountUpdateMode_Rollback_Hybrid_2.wgt";
+  std::string pkgid = "smokehyb10";
+  std::string appid1 = "smokehyb10.web";
+  ASSERT_EQ(MountInstall(path_old, PackageType::HYBRID),
+            ci::AppInstaller::Result::OK);
+  AddDataFiles(pkgid, kTestUserId);
+  ASSERT_EQ(MountInstall(path_new, PackageType::HYBRID,
+      RequestResult::FAIL), ci::AppInstaller::Result::ERROR);
+  ScopedTzipInterface interface(pkgid);
+  ValidatePackage(pkgid, {appid1});
+
+  ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "1\n"));
+  ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "lib/VERSION", "1\n"));
+  ValidateDataFiles(pkgid, kTestUserId);
 }
 
 TEST_F(SmokeTest, MountInstallationMode) {
   bf::path path = kSmokePackagesDirectory / "MountInstallationMode.wgt";
-  std::string pkgid = "smokeapp28";
-  std::string appid = "smokeapp28.InstallationMode";
+  std::string pkgid = "smokewgt28";
+  std::string appid = "smokewgt28.InstallationMode";
   ASSERT_EQ(MountInstall(path, PackageType::WGT), ci::AppInstaller::Result::OK);
   ScopedTzipInterface interface(pkgid);
   ValidatePackage(pkgid, {appid});
@@ -656,26 +1331,205 @@ TEST_F(SmokeTest, MountInstallationMode) {
 TEST_F(SmokeTest, MountUpdateMode) {
   bf::path path_old = kSmokePackagesDirectory / "MountUpdateMode.wgt";
   bf::path path_new = kSmokePackagesDirectory / "MountUpdateMode_2.wgt";
-  std::string pkgid = "smokeapp29";
-  std::string appid = "smokeapp29.UpdateMode";
-  ASSERT_EQ(MountUpdate(path_old, path_new, PackageType::WGT),
+  std::string pkgid = "smokewgt29";
+  std::string appid = "smokewgt29.UpdateMode";
+  ASSERT_EQ(MountInstall(path_old, PackageType::WGT),
+            ci::AppInstaller::Result::OK);
+  AddDataFiles(pkgid, kTestUserId);
+  ASSERT_EQ(MountInstall(path_new, PackageType::WGT),
             ci::AppInstaller::Result::OK);
   ScopedTzipInterface interface(pkgid);
   ValidatePackage(pkgid, {appid});
 
   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "2\n"));
+  ValidateDataFiles(pkgid, kTestUserId);
+}
+
+TEST_F(SmokeTest, MountInstallationMode_Rollback) {
+  bf::path path =
+      kSmokePackagesDirectory / "MountInstallationMode_Rollback.wgt";
+  std::string pkgid = "smokewgt33";
+  std::string appid = "smokewgt33.web";
+  ASSERT_EQ(MountInstall(path, PackageType::WGT, RequestResult::FAIL),
+            ci::AppInstaller::Result::ERROR);
+  ScopedTzipInterface interface(pkgid);
+  CheckPackageNonExistance(pkgid, {appid});
+}
+
+TEST_F(SmokeTest, MountUpdateMode_Rollback) {
+  bf::path path_old = kSmokePackagesDirectory / "MountUpdateMode_Rollback.wgt";
+  bf::path path_new =
+      kSmokePackagesDirectory / "MountUpdateMode_Rollback_2.wgt";
+  std::string pkgid = "smokewgt34";
+  std::string appid = "smokewgt34.web";
+  ASSERT_EQ(MountInstall(path_old, PackageType::WGT),
+            ci::AppInstaller::Result::OK);
+  AddDataFiles(pkgid, kTestUserId);
+  ASSERT_EQ(MountInstall(path_new, PackageType::WGT,
+      RequestResult::FAIL), ci::AppInstaller::Result::ERROR);
+  ScopedTzipInterface interface(pkgid);
+  ValidatePackage(pkgid, {appid});
+
+  ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "1\n"));
+  ValidateDataFiles(pkgid, kTestUserId);
+}
+
+TEST_F(SmokeTest, UserDefinedPlugins) {
+  bf::path path = kSmokePackagesDirectory / "SimpleEchoPrivilege.wgt";
+  std::string pkgid = "smokewgt02";
+  std::string appid = "smokewgt02.SimpleEcho";
+  std::string call_privilege = "http://tizen.org/privilege/call";
+  std::string location_privilege = "http://tizen.org/privilege/location";
+  std::string power_privilege = "http://tizen.org/privilege/power";
+
+  ASSERT_EQ(Install(path, PackageType::WGT), ci::AppInstaller::Result::OK);
+  ValidatePackage(pkgid, {appid});
+  std::vector<std::string> res;
+  ASSERT_TRUE(ci::QueryPrivilegesForPkgId(pkgid, kTestUserId, &res));
+  ASSERT_TRUE(std::find(res.begin(), res.end(), call_privilege) != res.end());
+  ASSERT_TRUE(std::find(res.begin(), res.end(), location_privilege)
+          != res.end());
+  ASSERT_TRUE(std::find(res.begin(), res.end(), power_privilege) != res.end());
+}
+
+TEST_F(SmokeTest, InstallExternalMode) {
+  ASSERT_TRUE(CheckAvailableExternalPath());
+  bf::path path = kSmokePackagesDirectory / "InstallExternalMode.wgt";
+  std::string pkgid = "smokewgt35";
+  std::string appid = "smokewgt35.web";
+  ASSERT_EQ(InstallExternal(path, PackageType::WGT),
+      ci::AppInstaller::Result::OK);
+  ValidateExternalPackage(pkgid, {appid});
+}
+
+TEST_F(SmokeTest, MigrateLegacyExternalImageMode) {
+  ASSERT_TRUE(CheckAvailableExternalPath());
+  bf::path path =
+      kSmokePackagesDirectory / "MigrateLegacyExternalImageMode.wgt";
+  std::string pkgid = "smokewgt36";
+  std::string appid = "smokewgt36.web";
+  bf::path legacy_path = kSmokePackagesDirectory / kLegacyExtImageDir;
+  ASSERT_EQ(MigrateLegacyExternalImage(pkgid, path, legacy_path,
+      PackageType::WGT), ci::AppInstaller::Result::OK);
+  ValidateExternalPackage(pkgid, {appid});
+}
+
+TEST_F(PreloadSmokeTest, InstallationMode_Preload) {
+  ASSERT_EQ(getuid(), 0) << "Test cannot be run by normal user";
+  bf::path path = kSmokePackagesDirectory / "InstallationMode_Preload.wgt";
+  std::string pkgid = "smokewgt37";
+  std::string appid = "smokewgt37.InstallationModePreload";
+  ASSERT_EQ(InstallPreload(path, PackageType::WGT),
+            ci::AppInstaller::Result::OK);
+  ValidatePackage(pkgid, {appid}, true);
+}
+
+TEST_F(PreloadSmokeTest, UpdateMode_Preload) {
+  ASSERT_EQ(getuid(), 0) << "Test cannot be run by normal user";
+  bf::path path_old = kSmokePackagesDirectory / "UpdateMode_Preload.wgt";
+  bf::path path_new = kSmokePackagesDirectory / "UpdateMode_Preload2.wgt";
+  std::string pkgid = "smokewgt38";
+  std::string appid = "smokewgt38.UpdateModePreload";
+  ASSERT_EQ(InstallPreload(path_old, PackageType::WGT),
+            ci::AppInstaller::Result::OK);
+  AddDataFiles(pkgid, kTestUserId);
+  ASSERT_EQ(InstallPreload(path_new, PackageType::WGT),
+            ci::AppInstaller::Result::OK);
+  ValidatePackage(pkgid, {appid}, true);
+
+  ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "2",
+                                           true));
+  ValidateDataFiles(pkgid, kTestUserId);
+}
+
+TEST_F(PreloadSmokeTest, DeinstallationMode_Preload) {
+  ASSERT_EQ(getuid(), 0) << "Test cannot be run by normal user";
+  bf::path path = kSmokePackagesDirectory / "DeinstallationMode_Preload.wgt";
+  std::string pkgid = "smokewgt39";
+  std::string appid = "smokewgt39.DeinstallationModePreload";
+  ASSERT_EQ(InstallPreload(path, PackageType::WGT),
+            ci::AppInstaller::Result::OK);
+  ASSERT_EQ(Uninstall(pkgid, PackageType::WGT, true),
+            ci::AppInstaller::Result::OK);
+  CheckPackageReadonlyNonExistance(pkgid, {appid});
+}
+
+TEST_F(SmokeTest, SharedRes24) {
+  bf::path path = kSmokePackagesDirectory / "SharedRes24.wgt";
+  std::string pkgid = "smokeSh2xx";
+  std::string appid = "smokeSh2xx.SharedRes24";
+  ASSERT_EQ(Install(path, PackageType::WGT), ci::AppInstaller::Result::OK);
+  ValidatePackage(pkgid, {appid});
+  bf::path root_path = ci::GetRootAppPath(false, kTestUserId);
+  ASSERT_TRUE(bf::is_regular_file(root_path / pkgid / "res" / "wgt" / "shared" / "res" / "NOT-SHARED-WGT"));  // NOLINT
+  ASSERT_FALSE(bf::exists(root_path / pkgid / "shared" / "res" / "NOT-SHARED-WGT"));  // NOLINT
+}
+
+TEST_F(SmokeTest, SharedRes30) {
+  bf::path path = kSmokePackagesDirectory / "SharedRes30.wgt";
+  std::string pkgid = "smokeSh3xx";
+  std::string appid = "smokeSh3xx.SharedRes30";
+  ASSERT_EQ(Install(path, PackageType::WGT), ci::AppInstaller::Result::OK);
+  ValidatePackage(pkgid, {appid});
+  bf::path root_path = ci::GetRootAppPath(false, kTestUserId);
+  ASSERT_TRUE(bf::is_regular_file(root_path / pkgid / "res" / "wgt" / "shared" / "res" / "SHARED-WGT"));  // NOLINT
+  ASSERT_TRUE(bf::is_symlink(root_path / pkgid / "shared" / "res" / "SHARED-WGT"));  // NOLINT
+}
+
+TEST_F(SmokeTest, SharedRes30Delta) {
+  bf::path path = kSmokePackagesDirectory / "SharedRes30Delta.wgt";
+  bf::path delta_package = kSmokePackagesDirectory / "SharedRes30Delta.delta";
+  std::string pkgid = "smokeSh3De";
+  std::string appid = "smokeSh3De.SharedRes30Delta";
+  ASSERT_EQ(DeltaInstall(path, delta_package, PackageType::WGT),
+            ci::AppInstaller::Result::OK);
+  ValidatePackage(pkgid, {appid});
+  // Check delta modifications
+  bf::path root_path = ci::GetRootAppPath(false, kTestUserId);
+  ASSERT_TRUE(bf::is_regular_file(root_path / pkgid / "res" / "wgt" / "shared" / "res" / "SHARED-WGT-2"));  // NOLINT
+  ASSERT_TRUE(bf::is_symlink(root_path / pkgid / "shared" / "res" / "SHARED-WGT-2"));  // NOLINT
+  ASSERT_FALSE(bf::exists(root_path / pkgid / "res" / "wgt" / "shared" / "res" / "SHARED-WGT-1"));  // NOLINT
+  ASSERT_FALSE(bf::exists(root_path / pkgid / "shared" / "res" / "SHARED-WGT-1"));  // NOLINT
+}
+
+TEST_F(SmokeTest, SharedRes30Hybrid) {
+  bf::path path = kSmokePackagesDirectory / "SharedRes30Hybrid.wgt";
+  std::string pkgid = "smokeSh3Hy";
+  std::string appid1 = "smokeSh3Hy.SharedRes30Hybrid";
+  std::string appid2 = "sharedres30hybridserivce";
+  ASSERT_EQ(Install(path, PackageType::HYBRID), ci::AppInstaller::Result::OK);
+  ValidatePackage(pkgid, {appid1, appid2});
+  bf::path root_path = ci::GetRootAppPath(false, kTestUserId);
+  ASSERT_TRUE(bf::is_regular_file(root_path / pkgid / "res" / "wgt" / "shared" / "res" / "SHARED-WGT"));  // NOLINT
+  ASSERT_TRUE(bf::is_symlink(root_path / pkgid / "shared" / "res" / "SHARED-WGT"));  // NOLINT
+  ASSERT_TRUE(bf::is_regular_file(root_path / pkgid / "shared" / "res" / "SHARED-TPK"));  // NOLINT
+  ASSERT_TRUE(bf::is_symlink(root_path / pkgid / "res" / "wgt" / "shared" / "res" / "SHARED-TPK"));  // NOLINT
+}
+
+TEST_F(SmokeTest, SharedRes30HybridDelta) {
+  bf::path path = kSmokePackagesDirectory / "SharedRes30HybridDelta.wgt";
+  bf::path delta_package = kSmokePackagesDirectory / "SharedRes30HybridDelta.delta";
+  std::string pkgid = "smokeSh3HD";
+  std::string appid1 = "smokeSh3HD.SharedRes30HybridDelta";
+  std::string appid2 = "sharedres30hybriddeltaserivce";
+  ASSERT_EQ(DeltaInstall(path, delta_package, PackageType::HYBRID),
+            ci::AppInstaller::Result::OK);
+  ValidatePackage(pkgid, {appid1, appid2});
+  // Check delta modifications
+  bf::path root_path = ci::GetRootAppPath(false, kTestUserId);
+  ASSERT_TRUE(bf::is_regular_file(root_path / pkgid / "res" / "wgt" / "shared" / "res" / "SHARED-WGT-2"));  // NOLINT
+  ASSERT_TRUE(bf::is_symlink(root_path / pkgid / "shared" / "res" / "SHARED-WGT-2"));  // NOLINT
+  ASSERT_TRUE(bf::is_regular_file(root_path / pkgid / "shared" / "res" / "SHARED-TPK-2"));  // NOLINT
+  ASSERT_TRUE(bf::is_symlink(root_path / pkgid / "res" / "wgt" / "shared" / "res" / "SHARED-TPK-2"));  // NOLINT
+  ASSERT_FALSE(bf::exists(root_path / pkgid / "res" / "wgt" / "shared" / "res" / "SHARED-WGT-1"));  // NOLINT
+  ASSERT_FALSE(bf::exists(root_path / pkgid / "shared" / "res" / "SHARED-WGT-1"));  // NOLINT
 }
 
 }  // namespace common_installer
 
 int main(int argc,  char** argv) {
   testing::InitGoogleTest(&argc, argv);
-  const char* directory = getenv("HOME");
-  if (!directory) {
-    LOG(ERROR) << "Cannot get $HOME value";
-    return 1;
-  }
-  testing::AddGlobalTestEnvironment(
-      new common_installer::SmokeEnvironment(directory));
+  testing::Environment *env = testing::AddGlobalTestEnvironment(
+      new common_installer::SmokeEnvironment(ParseRequestMode(argc, argv)));
   return RUN_ALL_TESTS();
 }