From ad0b24c375c41a68cd2f279a0358cc54fb525259 Mon Sep 17 00:00:00 2001 From: Piotr Ganicz Date: Mon, 20 Mar 2017 13:28:21 +0100 Subject: [PATCH 01/16] Export Smoke Utils This change exports utility functions to smoke_utils.h Change-Id: I080275d4add34c417710f6c792fe0108780d284f --- src/unit_tests/CMakeLists.txt | 2 + src/unit_tests/smoke_test.cc | 837 +----------------------------------------- src/unit_tests/smoke_utils.cc | 757 ++++++++++++++++++++++++++++++++++++++ src/unit_tests/smoke_utils.h | 242 ++++++++++++ 4 files changed, 1008 insertions(+), 830 deletions(-) create mode 100644 src/unit_tests/smoke_utils.cc create mode 100644 src/unit_tests/smoke_utils.h diff --git a/src/unit_tests/CMakeLists.txt b/src/unit_tests/CMakeLists.txt index 7b0f80d..5aa1409 100644 --- a/src/unit_tests/CMakeLists.txt +++ b/src/unit_tests/CMakeLists.txt @@ -3,6 +3,8 @@ SET(DESTINATION_DIR wgt-backend-ut) # Executables ADD_EXECUTABLE(${TARGET_SMOKE_TEST} smoke_test.cc + smoke_utils.h + smoke_utils.cc ) ADD_EXECUTABLE(${TARGET_SMOKE_TEST_HELPER} smoke_test_helper.cc diff --git a/src/unit_tests/smoke_test.cc b/src/unit_tests/smoke_test.cc index 37790e0..f446f8a 100644 --- a/src/unit_tests/smoke_test.cc +++ b/src/unit_tests/smoke_test.cc @@ -2,839 +2,15 @@ // Use of this source code is governed by an apache-2.0 license that can be // found in the LICENSE file. -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include + +#include #include #include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "hybrid/hybrid_installer.h" -#include "wgt/wgt_app_query_interface.h" -#include "wgt/wgt_installer.h" - -#define SIZEOFARRAY(ARR) \ - sizeof(ARR) / sizeof(ARR[0]) \ - -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(), "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() == "global") { - std::cout << "Request mode was set to global." << std::endl; - return ci::RequestMode::GLOBAL; - } - if (vm["request-mode"].as() == "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::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/"; - -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 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_; -}; - -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; - } -}; - -enum class PackageType { - WGT, - HYBRID -}; - -bool TouchFile(const bf::path& path) { - FILE* f = fopen(path.c_str(), "w+"); - if (!f) - return false; - fclose(f); - 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 = ci::GetUidByUserName(user_name)) { - kTestUserId = *uid; - kTestUserIdStr = std::to_string(kTestUserId); - std::cout << "User created properly: uid=" << *uid; - if (boost::optional 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 = ci::GetUidByUserName(user_name)) - test_uid = *uid; - bool ret = DeleteUser(user_name, true); - if (boost::optional 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, - 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("/wgt-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("/wgt-recovery") - != std::string::npos) { - return dir_entry.path(); - } - } - } - 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, - 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; - } - FILE* handle = fopen(file_path.c_str(), "r"); - if (!handle) { - LOG(ERROR) << file_path << " cannot be open"; - return false; - } - std::string content; - std::array buffer; - while (fgets(buffer.data(), buffer.size(), handle)) { - content += buffer.data(); - } - fclose(handle); - 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 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& 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 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)); - - for (auto& appid : appids) { - bf::path binary_path = package_path / "bin" / appid; - ASSERT_TRUE(bf::exists(binary_path)); - } - - bf::path widget_root_path = package_path / "res" / "wgt"; - bf::path config_path = widget_root_path / "config.xml"; - ASSERT_TRUE(bf::exists(widget_root_path)); - ASSERT_TRUE(bf::exists(config_path)); - - bf::path private_tmp_path = package_path / "tmp"; - ASSERT_TRUE(bf::exists(private_tmp_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; - 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&, 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::vector& 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& 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& 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& appids) { - 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& appids) { - ASSERT_FALSE(ci::QueryIsPackageInstalled( - pkgid, ci::GetRequestMode(kTestUserId), kTestUserId)); - PackageCheckCleanup(pkgid, appids, true); -} - -std::unique_ptr CreateQueryInterface() { - std::unique_ptr query_interface( - new wgt::WgtAppQueryInterface()); - return query_interface; -} - -std::unique_ptr CreateInstaller(ci::PkgMgrPtr pkgmgr, - PackageType type) { - switch (type) { - case PackageType::WGT: - return std::unique_ptr(new wgt::WgtInstaller(pkgmgr)); - case PackageType::HYBRID: - return std::unique_ptr( - new hybrid::HybridInstaller(pkgmgr)); - default: - LOG(ERROR) << "Unknown installer type"; - return nullptr; - } -} - -ci::AppInstaller::Result RunInstallerWithPkgrmgr(ci::PkgMgrPtr pkgmgr, - PackageType type, - RequestResult mode) { - std::unique_ptr installer = CreateInstaller(pkgmgr, type); - switch (mode) { - case RequestResult::FAIL: - installer->AddStep(); - break; - default: - break; - } - return installer->Run(); -} -ci::AppInstaller::Result CallBackend(int argc, - const char* argv[], - PackageType type, - RequestResult mode = RequestResult::NORMAL - ) { - TestPkgmgrInstaller pkgmgr_installer; - std::unique_ptr query_interface = - CreateQueryInterface(); - auto pkgmgr = - ci::PkgMgrInterface::Create(argc, const_cast(argv), - &pkgmgr_installer, query_interface.get()); - if (!pkgmgr) { - LOG(ERROR) << "Failed to initialize pkgmgr interface"; - return ci::AppInstaller::Result::UNKNOWN; - } - return RunInstallerWithPkgrmgr(pkgmgr, type, mode); -} - -ci::AppInstaller::Result Install(const bf::path& path, - PackageType type, - RequestResult mode = RequestResult::NORMAL) { - const char* argv[] = {"", "-i", path.c_str(), "-u", kTestUserIdStr.c_str()}; - return CallBackend(SIZEOFARRAY(argv), argv, type, mode); -} - -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 true; -} - -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 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; - } - - 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) { - 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 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", pkgid.c_str(), "-u", - kTestUserIdStr.c_str()}; - return CallBackend(SIZEOFARRAY(argv), argv, type, mode); -} - -ci::AppInstaller::Result DeltaInstall(const bf::path& path, - const bf::path& delta_package, PackageType type) { - if (Install(path, type) != ci::AppInstaller::Result::OK) { - LOG(ERROR) << "Failed to install application. Cannot perform delta update"; - return ci::AppInstaller::Result::UNKNOWN; - } - return Install(delta_package, type); -} - -ci::AppInstaller::Result EnablePackage(const std::string& pkgid, - PackageType type, - RequestResult mode = RequestResult::NORMAL) { - 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(), "-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(), "-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); - } -} +#include "unit_tests/smoke_utils.h" -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 SetupBackupDirectories() { - std::vector 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 namespace common_installer { @@ -844,9 +20,9 @@ class SmokeEnvironment : public testing::Environment { request_mode_ = mode; } void SetUp() override { - if (request_mode_ == ci::RequestMode::USER) + if (request_mode_ == ci::RequestMode::USER) { ASSERT_TRUE(AddTestUser(kNormalUserName)); - else { + } else { kTestUserId = kGlobalUserUid; kTestGroupId = kGlobalUserGid; kTestUserIdStr = std::to_string(kTestUserId); @@ -1508,7 +684,8 @@ TEST_F(SmokeTest, SharedRes30Hybrid) { TEST_F(SmokeTest, SharedRes30HybridDelta) { bf::path path = kSmokePackagesDirectory / "SharedRes30HybridDelta.wgt"; - bf::path delta_package = kSmokePackagesDirectory / "SharedRes30HybridDelta.delta"; + bf::path delta_package = kSmokePackagesDirectory / + "SharedRes30HybridDelta.delta"; std::string pkgid = "smokeSh3HD"; std::string appid1 = "smokeSh3HD.SharedRes30HybridDelta"; std::string appid2 = "sharedres30hybriddeltaserivce"; diff --git a/src/unit_tests/smoke_utils.cc b/src/unit_tests/smoke_utils.cc new file mode 100644 index 0000000..c1750f1 --- /dev/null +++ b/src/unit_tests/smoke_utils.cc @@ -0,0 +1,757 @@ +// 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 +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "wgt/wgt_installer.h" + +#include "unit_tests/smoke_utils.h" + +namespace bo = boost::program_options; + +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; +const char kNormalUserName[] = "smokeuser"; +const char kSystemShareGroupName[] = "system_share"; +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/wgt-backend-ut/test_samples/smoke/"; + + +const char* rwDirectories[] = { + "data", + "cache", + "shared/cache", + "shared/data", + "shared/trusted", +}; + +// common entries +const std::vector 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"; + + +ci::RequestMode ParseRequestMode(int argc, char** argv) { + bo::options_description desc("Available options"); + desc.add_options() + ("request-mode", bo::value(), "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() == "global") { + std::cout << "Request mode was set to global." << std::endl; + return ci::RequestMode::GLOBAL; + } + if (vm["request-mode"].as() == "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::endl; + std::cout << "Request mode was set to global." << std::endl; + return ci::RequestMode::GLOBAL; + } +} + +bool TouchFile(const bf::path& path) { + FILE* f = fopen(path.c_str(), "w+"); + if (!f) + return false; + fclose(f); + 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 = ci::GetUidByUserName(user_name)) { + kTestUserId = *uid; + kTestUserIdStr = std::to_string(kTestUserId); + std::cout << "User created properly: uid=" << *uid; + if (boost::optional 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 = ci::GetUidByUserName(user_name)) + test_uid = *uid; + bool ret = DeleteUser(user_name, true); + if (!ci::GetUidByUserName(user_name)) { + 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, + 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("/wgt-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("/wgt-recovery") + != std::string::npos) { + return dir_entry.path(); + } + } + } + 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, + bool is_readonly) { + 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; + } + FILE* handle = fopen(file_path.c_str(), "r"); + if (!handle) { + LOG(ERROR) << file_path << " cannot be open"; + return false; + } + std::string content; + std::array buffer; + while (fgets(buffer.data(), buffer.size(), handle)) { + content += buffer.data(); + } + fclose(handle); + 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 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& 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 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)); + + for (auto& appid : appids) { + bf::path binary_path = package_path / "bin" / appid; + ASSERT_TRUE(bf::exists(binary_path)); + } + + bf::path widget_root_path = package_path / "res" / "wgt"; + bf::path config_path = widget_root_path / "config.xml"; + ASSERT_TRUE(bf::exists(widget_root_path)); + ASSERT_TRUE(bf::exists(config_path)); + + bf::path private_tmp_path = package_path / "tmp"; + ASSERT_TRUE(bf::exists(private_tmp_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; + 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&, 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::vector& appids, bool is_readonly) { + 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& 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& 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& appids) { + 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& appids) { + ASSERT_FALSE(ci::QueryIsPackageInstalled( + pkgid, ci::GetRequestMode(kTestUserId), kTestUserId)); + PackageCheckCleanup(pkgid, appids, true); +} + +std::unique_ptr CreateQueryInterface() { + std::unique_ptr query_interface( + new wgt::WgtAppQueryInterface()); + return query_interface; +} + +std::unique_ptr CreateInstaller(ci::PkgMgrPtr pkgmgr, + PackageType type) { + switch (type) { + case PackageType::WGT: + return std::unique_ptr(new wgt::WgtInstaller(pkgmgr)); + case PackageType::HYBRID: + return std::unique_ptr( + new hybrid::HybridInstaller(pkgmgr)); + default: + LOG(ERROR) << "Unknown installer type"; + return nullptr; + } +} + +ci::AppInstaller::Result RunInstallerWithPkgrmgr(ci::PkgMgrPtr pkgmgr, + PackageType type, + RequestResult mode) { + std::unique_ptr installer = CreateInstaller(pkgmgr, type); + switch (mode) { + case RequestResult::FAIL: + installer->AddStep(); + break; + default: + break; + } + return installer->Run(); +} +ci::AppInstaller::Result CallBackend(int argc, + const char* argv[], + PackageType type, + RequestResult mode) { + TestPkgmgrInstaller pkgmgr_installer; + std::unique_ptr query_interface = + CreateQueryInterface(); + auto pkgmgr = + ci::PkgMgrInterface::Create(argc, const_cast(argv), + &pkgmgr_installer, query_interface.get()); + if (!pkgmgr) { + LOG(ERROR) << "Failed to initialize pkgmgr interface"; + return ci::AppInstaller::Result::UNKNOWN; + } + return RunInstallerWithPkgrmgr(pkgmgr, type, mode); +} + +ci::AppInstaller::Result Install(const bf::path& path, + PackageType type, + RequestResult mode) { + const char* argv[] = {"", "-i", path.c_str(), "-u", kTestUserIdStr.c_str()}; + return CallBackend(SIZEOFARRAY(argv), argv, type, mode); +} + +ci::AppInstaller::Result InstallPreload(const bf::path& path, PackageType type, + RequestResult mode) { + 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 true; +} + +ci::AppInstaller::Result InstallExternal(const bf::path& path, + PackageType type, + 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, type, 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, + PackageType type, + RequestResult mode) { + 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; + } + + 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) { + 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) { + 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 RDSUpdate(const bf::path& path, + const std::string& pkgid, + PackageType type, + RequestResult mode) { + 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", pkgid.c_str(), "-u", + kTestUserIdStr.c_str()}; + return CallBackend(SIZEOFARRAY(argv), argv, type, mode); +} + +ci::AppInstaller::Result DeltaInstall(const bf::path& path, + const bf::path& delta_package, PackageType type) { + if (Install(path, type) != ci::AppInstaller::Result::OK) { + LOG(ERROR) << "Failed to install application. Cannot perform delta update"; + return ci::AppInstaller::Result::UNKNOWN; + } + return Install(delta_package, type); +} + +ci::AppInstaller::Result EnablePackage(const std::string& pkgid, + PackageType type, + RequestResult mode) { + 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) { + 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) { + 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); + } +} + +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 SetupBackupDirectories() { + std::vector 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); +} diff --git a/src/unit_tests/smoke_utils.h b/src/unit_tests/smoke_utils.h new file mode 100644 index 0000000..efc2551 --- /dev/null +++ b/src/unit_tests/smoke_utils.h @@ -0,0 +1,242 @@ +// 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 + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "hybrid/hybrid_installer.h" +#include "wgt/wgt_app_query_interface.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; +extern uid_t kTestUserId; +extern gid_t kTestGroupId; +extern std::string kTestUserIdStr; +extern const char kNormalUserName[]; +extern const char kSystemShareGroupName[]; +extern const std::string& kDefaultUserIdStr; +extern const char kLegacyExtImageDir[]; +extern const char kMigrateTestDBName[]; + +extern const bf::path kSmokePackagesDirectory; + +enum RWDirectory { + DATA, + CACHE, + SHARED_CACHE, + SHARED_DATA, + SHARED_TRUSTED +}; + +extern const char* rwDirectories[]; + +// common entries +extern const std::vector 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; + } +}; + +enum class PackageType { + WGT, + HYBRID +}; + +ci::RequestMode ParseRequestMode(int argc, char** argv); + +bool TouchFile(const bf::path& path); + +bool AddUser(const char *user_name); + +bool DeleteUser(const char *user_name, bool rem_home_dir); + +bool AddTestUser(const char *user_name); + +bool DeleteTestUser(const char *user_name); + +void RemoveAllRecoveryFiles(); + +bf::path FindRecoveryFile(); + +bf::path GetPackageRoot(const std::string& pkgid, uid_t uid); + +bool ValidateFileContentInPackage(const std::string& pkgid, + const std::string& relative, + const std::string& expected, + bool is_readonly = false); + +void AddDataFiles(const std::string& pkgid, uid_t uid); + +void ValidateDataFiles(const std::string& pkgid, uid_t uid); + +void ValidatePackageRWFS(const std::string& pkgid, uid_t uid); + +void ValidatePackageFS(const std::string& pkgid, + const std::vector& appids, + uid_t uid, gid_t gid, bool is_readonly); + +void PackageCheckCleanup(const std::string& pkgid, + const std::vector&, bool is_readonly = false); + +void ValidatePackage(const std::string& pkgid, + const std::vector& appids, bool is_readonly = false); + +void ValidateExternalPackageFS(const std::string& pkgid, + const std::vector& appids, + uid_t uid, gid_t gid); + +void ValidateExternalPackage(const std::string& pkgid, + const std::vector& appids); + +void CheckPackageNonExistance(const std::string& pkgid, + const std::vector& appids); + +void CheckPackageReadonlyNonExistance(const std::string& pkgid, + const std::vector& appids); + +std::unique_ptr CreateQueryInterface(); + +std::unique_ptr CreateInstaller(ci::PkgMgrPtr pkgmgr, + PackageType type); + +ci::AppInstaller::Result RunInstallerWithPkgrmgr(ci::PkgMgrPtr pkgmgr, + PackageType type, + RequestResult mode); +ci::AppInstaller::Result CallBackend(int argc, + const char* argv[], + PackageType type, + RequestResult mode + = RequestResult::NORMAL); + +ci::AppInstaller::Result Install(const bf::path& path, + PackageType type, + RequestResult mode = RequestResult::NORMAL); + +ci::AppInstaller::Result InstallPreload(const bf::path& path, PackageType type, + RequestResult mode = RequestResult::NORMAL); + +bool CheckAvailableExternalPath(); + +ci::AppInstaller::Result InstallExternal(const bf::path& path, + PackageType type, + RequestResult mode = RequestResult::NORMAL); + +ci::AppInstaller::Result MigrateLegacyExternalImage(const std::string& pkgid, + const bf::path& path, + const bf::path& legacy_path, + PackageType type, + RequestResult mode = RequestResult::NORMAL); + +ci::AppInstaller::Result MountInstall(const bf::path& path, + PackageType type, RequestResult mode = RequestResult::NORMAL); + +ci::AppInstaller::Result Uninstall(const std::string& pkgid, + PackageType type, + bool is_preload, + RequestResult mode = RequestResult::NORMAL); + +ci::AppInstaller::Result RDSUpdate(const bf::path& path, + const std::string& pkgid, + PackageType type, + RequestResult mode = RequestResult::NORMAL); + +ci::AppInstaller::Result DeltaInstall(const bf::path& path, + const bf::path& delta_package, PackageType type); + +ci::AppInstaller::Result EnablePackage(const std::string& pkgid, + PackageType type, + RequestResult mode = RequestResult::NORMAL); + +ci::AppInstaller::Result DisablePackage(const std::string& pkgid, + PackageType type, + RequestResult mode = RequestResult::NORMAL); + +ci::AppInstaller::Result Recover(const bf::path& recovery_file, + PackageType type, + RequestResult mode = RequestResult::NORMAL); + +void BackupPath(const bf::path& path); + +void RestorePath(const bf::path& path); + +std::vector SetupBackupDirectories(); + +void UninstallAllAppsInDirectory(bf::path dir, bool is_preload); + +void UninstallAllSmokeApps(ci::RequestMode request_mode); + + +#endif // UNIT_TESTS_SMOKE_UTILS_H_ -- 2.7.4 From bbce0a0830cbaffba1f8b0a78109f20e142b1049 Mon Sep 17 00:00:00 2001 From: Piotr Ganicz Date: Mon, 20 Mar 2017 15:41:46 +0100 Subject: [PATCH 02/16] Extensive tests for Recovery and Rollback This commit creates new executable (extensive-smoke-test) for new type of tests which will be testing recovery and rollback modes after each step in each installation mode. Requires: - https://review.tizen.org/gerrit/#/c/116059/ - https://review.tizen.org/gerrit/#/c/119925/ Change-Id: Ib39dfd3df2f42ff33644904f682775a6a9b113f7 --- CMakeLists.txt | 1 + src/unit_tests/CMakeLists.txt | 13 ++ src/unit_tests/extensive_smoke_test.cc | 388 +++++++++++++++++++++++++++++++++ src/unit_tests/smoke_test.cc | 96 ++++---- src/unit_tests/smoke_test_helper.cc | 14 +- src/unit_tests/smoke_utils.cc | 142 ++++++++---- src/unit_tests/smoke_utils.h | 40 +++- 7 files changed, 603 insertions(+), 91 deletions(-) create mode 100644 src/unit_tests/extensive_smoke_test.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 465821f..86b3f98 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,7 @@ SET(TARGET_WGT_BACKEND "wgt-backend") SET(TARGET_LIBNAME_HYBRID "hybrid-installer") SET(TARGET_SMOKE_TEST "smoke-test") +SET(TARGET_SMOKE_TEST_EXTENSIVE "extensive-smoke-test") SET(TARGET_SMOKE_TEST_HELPER "smoke-test-helper") SET(TARGET_MANIFEST_TEST "manifest-test") diff --git a/src/unit_tests/CMakeLists.txt b/src/unit_tests/CMakeLists.txt index 5aa1409..6b0aac1 100644 --- a/src/unit_tests/CMakeLists.txt +++ b/src/unit_tests/CMakeLists.txt @@ -6,6 +6,11 @@ ADD_EXECUTABLE(${TARGET_SMOKE_TEST} smoke_utils.h smoke_utils.cc ) +ADD_EXECUTABLE(${TARGET_SMOKE_TEST_EXTENSIVE} + extensive_smoke_test.cc + smoke_utils.h + smoke_utils.cc +) ADD_EXECUTABLE(${TARGET_SMOKE_TEST_HELPER} smoke_test_helper.cc ) @@ -14,6 +19,7 @@ ADD_EXECUTABLE(${TARGET_MANIFEST_TEST} ) TARGET_INCLUDE_DIRECTORIES(${TARGET_SMOKE_TEST} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../) +TARGET_INCLUDE_DIRECTORIES(${TARGET_SMOKE_TEST_EXTENSIVE} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../) TARGET_INCLUDE_DIRECTORIES(${TARGET_SMOKE_TEST_HELPER} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../) TARGET_INCLUDE_DIRECTORIES(${TARGET_MANIFEST_TEST} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../) @@ -24,6 +30,11 @@ APPLY_PKG_CONFIG(${TARGET_SMOKE_TEST} PUBLIC GTEST GUM_DEPS ) +APPLY_PKG_CONFIG(${TARGET_SMOKE_TEST_EXTENSIVE} PUBLIC + Boost + GTEST + GUM_DEPS +) APPLY_PKG_CONFIG(${TARGET_MANIFEST_TEST} PUBLIC Boost GTEST @@ -33,9 +44,11 @@ APPLY_PKG_CONFIG(${TARGET_MANIFEST_TEST} PUBLIC # GTest main libraries is still missing, so additional linking of # GTEST_MAIN_LIBRARIES is needed. TARGET_LINK_LIBRARIES(${TARGET_SMOKE_TEST} PRIVATE ${TARGET_LIBNAME_WGT} ${TARGET_LIBNAME_HYBRID} ${GTEST_MAIN_LIBRARIES}) +TARGET_LINK_LIBRARIES(${TARGET_SMOKE_TEST_EXTENSIVE} PRIVATE ${TARGET_LIBNAME_WGT} ${TARGET_LIBNAME_HYBRID} ${GTEST_MAIN_LIBRARIES}) TARGET_LINK_LIBRARIES(${TARGET_SMOKE_TEST_HELPER} PRIVATE ${TARGET_LIBNAME_WGT}) TARGET_LINK_LIBRARIES(${TARGET_MANIFEST_TEST} PRIVATE ${TARGET_LIBNAME_WGT} ${GTEST_MAIN_LIBRARIES}) INSTALL(TARGETS ${TARGET_SMOKE_TEST} DESTINATION ${BINDIR}/${DESTINATION_DIR}) +INSTALL(TARGETS ${TARGET_SMOKE_TEST_EXTENSIVE} DESTINATION ${BINDIR}/${DESTINATION_DIR}) INSTALL(TARGETS ${TARGET_SMOKE_TEST_HELPER} DESTINATION ${BINDIR}/${DESTINATION_DIR}) INSTALL(TARGETS ${TARGET_MANIFEST_TEST} DESTINATION ${BINDIR}/${DESTINATION_DIR}) diff --git a/src/unit_tests/extensive_smoke_test.cc b/src/unit_tests/extensive_smoke_test.cc new file mode 100644 index 0000000..58f11f6 --- /dev/null +++ b/src/unit_tests/extensive_smoke_test.cc @@ -0,0 +1,388 @@ +// 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 + +#include + +#include +#include + +#include "unit_tests/smoke_utils.h" + + +namespace common_installer { + +class SmokeEnvironment : public testing::Environment { + public: + explicit SmokeEnvironment(ci::RequestMode mode) {\ + request_mode_ = mode; + } + void SetUp() override { + 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 { + 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: + ci::RequestMode request_mode_; + std::vector backups_; +}; + +class SmokeTest : public testing::Test { +}; + +class PreloadSmokeTest : public testing::Test { + void SetUp() override { + ASSERT_EQ(kGlobalUserUid, kTestUserId); + } +}; + +TEST_F(SmokeTest, RecoveryMode_ForInstallation) { + bf::path path = kSmokePackagesDirectory / "RecoveryMode_ForInstallation.wgt"; + std::string pkgid = "smokewgt09"; + std::string appid = "smokewgt09.RecoveryModeForInstallation"; + + std::vector args = + {"", "-i", path.string(), "-u", kTestUserIdStr.c_str()}; + CrashAfterEachStep(args, [=](int step) -> bool { + if (step >= 1) { + bf::path recovery_file = FindRecoveryFile(); + EXTENDED_ASSERT_FALSE(recovery_file.empty()); + EXTENDED_ASSERT_EQ(Recover(recovery_file, PackageType::WGT), + ci::AppInstaller::Result::OK); + EXTENDED_ASSERT_TRUE(CheckPackageNonExistance(pkgid, {appid})); + } + return true; + }); +} + +TEST_F(SmokeTest, RecoveryMode_ForUpdate) { + bf::path path_old = kSmokePackagesDirectory / "RecoveryMode_ForUpdate.wgt"; + bf::path path_new = kSmokePackagesDirectory / "RecoveryMode_ForUpdate_2.wgt"; + RemoveAllRecoveryFiles(); + ASSERT_EQ(Install(path_old, PackageType::WGT), ci::AppInstaller::Result::OK); + std::string pkgid = "smokewgt10"; + std::string appid = "smokewgt10.RecoveryModeForUpdate"; + AddDataFiles(pkgid, kTestUserId); + + std::vector args = + {"", "-i", path_new.string(), "-u", kTestUserIdStr.c_str()}; + CrashAfterEachStep(args, [=](int step) -> bool { + if (step >= 1) { + bf::path recovery_file = FindRecoveryFile(); + EXTENDED_ASSERT_FALSE(recovery_file.empty()); + EXTENDED_ASSERT_EQ(Recover(recovery_file, PackageType::WGT), + ci::AppInstaller::Result::OK); + EXTENDED_ASSERT_TRUE(ValidatePackage(pkgid, {appid})); + + EXTENDED_ASSERT_TRUE(ValidateFileContentInPackage(pkgid, + "res/wgt/VERSION", "1\n")); + EXTENDED_ASSERT_TRUE(ValidateDataFiles(pkgid, kTestUserId)); + } + return true; + }); +} + +TEST_F(SmokeTest, RecoveryMode_ForDelta) { + bf::path path_old = kSmokePackagesDirectory / "RecoveryMode_ForDelta.wgt"; + bf::path path_new = kSmokePackagesDirectory / "RecoveryMode_ForDelta.delta"; + std::string pkgid = "smokewgt30"; + std::string appid = "smokewgt30.RecoveryModeForDelta"; + bf::path recovery_file = FindRecoveryFile(); + RemoveAllRecoveryFiles(); + std::vector args = + {"", "-i", path_new.string(), "-u", kTestUserIdStr.c_str()}; + CrashAfterEachStep(args, [=](int step) -> bool { + if (step >= 1) { + EXTENDED_ASSERT_FALSE(recovery_file.empty()); + EXTENDED_ASSERT_EQ(Recover(recovery_file, PackageType::WGT), + ci::AppInstaller::Result::OK); + EXTENDED_ASSERT_TRUE(ValidatePackage(pkgid, {appid})); + + EXTENDED_ASSERT_TRUE(ValidateFileContentInPackage(pkgid, + "res/wgt/VERSION", "1\n")); + } + return true; + }); +} + +TEST_F(SmokeTest, RecoveryMode_ForMountInstall) { + bf::path path = kSmokePackagesDirectory / "RecoveryMode_ForMountInstall.wgt"; + std::string pkgid = "smokewgt31"; + std::string appid = "smokewgt31.RecoveryModeForMountInstall"; + RemoveAllRecoveryFiles(); + std::vector args = + {"", "-w", path.string(), "-u", kTestUserIdStr.c_str()}; + CrashAfterEachStep(args, [=](int step) -> bool { + if (step >= 1) { + bf::path recovery_file = FindRecoveryFile(); + EXTENDED_ASSERT_FALSE(recovery_file.empty()); + EXTENDED_ASSERT_EQ(Recover(recovery_file, PackageType::WGT), + ci::AppInstaller::Result::OK); + EXTENDED_ASSERT_TRUE(CheckPackageNonExistance(pkgid, {appid})); + } + return true; + }); +} + +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); + std::vector args = + {"", "-w", path_new.string(), "-u", kTestUserIdStr.c_str()}; + CrashAfterEachStep(args, [=](int step) -> bool { + if (step >= 1) { + // Filesystem may be mounted after crash + ScopedTzipInterface poweroff_unmount_interface(pkgid); + poweroff_unmount_interface.Release(); + + bf::path recovery_file = FindRecoveryFile(); + EXTENDED_ASSERT_FALSE(recovery_file.empty()); + EXTENDED_ASSERT_EQ(Recover(recovery_file, PackageType::WGT), + ci::AppInstaller::Result::OK); + + ScopedTzipInterface interface(pkgid); + EXTENDED_ASSERT_TRUE(ValidatePackage(pkgid, {appid})); + EXTENDED_ASSERT_TRUE(ValidateFileContentInPackage( + pkgid, "res/wgt/VERSION", "1\n")); + EXTENDED_ASSERT_TRUE(ValidateDataFiles(pkgid, kTestUserId)); + } + return true; + }); +} + + +TEST_F(SmokeTest, InstallationMode_Rollback) { + bf::path path = kSmokePackagesDirectory / "InstallationMode_Rollback.wgt"; + std::string pkgid = "smokewgt06"; + std::string appid = "smokewgt06.InstallationModeRollback"; + + const char* argv[] = {"", "-i", path.c_str(), "-u", kTestUserIdStr.c_str()}; + TestRollbackAfterEachStep(SIZEOFARRAY(argv), argv, [=]() -> bool { + EXTENDED_ASSERT_EQ(Install(path, PackageType::WGT, RequestResult::FAIL), + ci::AppInstaller::Result::ERROR); + EXTENDED_ASSERT_TRUE(CheckPackageNonExistance(pkgid, {appid})); + return true; + }); +} + +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 = "smokewgt07"; + std::string appid = "smokewgt07.UpdateModeRollback"; + ASSERT_EQ(Install(path_old, PackageType::WGT), ci::AppInstaller::Result::OK); + AddDataFiles(pkgid, kTestUserId); + const char* argv[] = + {"", "-i", path_new.c_str(), "-u", kTestUserIdStr.c_str()}; + TestRollbackAfterEachStep(SIZEOFARRAY(argv), argv, [=]() -> bool { + EXTENDED_ASSERT_EQ(Install(path_new, PackageType::WGT, RequestResult::FAIL), + ci::AppInstaller::Result::ERROR); + EXTENDED_ASSERT_TRUE(ValidatePackage(pkgid, {appid})); + + EXTENDED_ASSERT_TRUE(ValidateFileContentInPackage(pkgid, + "res/wgt/VERSION", "1\n")); + EXTENDED_ASSERT_TRUE(ValidateDataFiles(pkgid, kTestUserId)); + return true; + }); +} + +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); + const char* argv[] = + {"", "-i", delta_package.c_str(), "-u", kTestUserIdStr.c_str()}; + TestRollbackAfterEachStep(SIZEOFARRAY(argv), argv, [=]() -> bool { + EXTENDED_ASSERT_TRUE(ValidatePackage(pkgid, {appid})); + EXTENDED_ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/MODIFIED", + "version 1\n")); + EXTENDED_ASSERT_TRUE(ValidateDataFiles(pkgid, kTestUserId)); + EXTENDED_ASSERT_TRUE(bf::exists(GetPackageRoot(pkgid, kTestUserId) / + "res/wgt/DELETED")); + EXTENDED_ASSERT_FALSE(bf::exists(GetPackageRoot(pkgid, kTestUserId) / + "res/wgt/ADDED")); + return true; + }); +} + +TEST_F(SmokeTest, InstallationMode_Rollback_Hybrid) { + bf::path path = kSmokePackagesDirectory / + "InstallationMode_Rollback_Hybrid.wgt"; + std::string pkgid = "smokehyb07"; + std::string appid1 = "smokehyb07.web"; + const char* argv[] = {"", "-i", path.c_str(), "-u", kTestUserIdStr.c_str()}; + TestRollbackAfterEachStep(SIZEOFARRAY(argv), argv, [=]() -> bool { + EXTENDED_ASSERT_TRUE(CheckPackageNonExistance(pkgid, {appid1})); + return true; + }, PackageType::HYBRID); +} + +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); + const char* argv[] = + {"", "-i", path_new.c_str(), "-u", kTestUserIdStr.c_str()}; + TestRollbackAfterEachStep(SIZEOFARRAY(argv), argv, [=]() -> bool { + EXTENDED_ASSERT_TRUE(ValidatePackage(pkgid, {appid1})); + + EXTENDED_ASSERT_TRUE(ValidateFileContentInPackage(pkgid, + "res/wgt/VERSION", "1\n")); + EXTENDED_ASSERT_TRUE(ValidateFileContentInPackage(pkgid, + "lib/VERSION", "1\n")); + EXTENDED_ASSERT_TRUE(ValidateDataFiles(pkgid, kTestUserId)); + return true; + }, PackageType::HYBRID); +} + +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); + const char* argv[] = {"", "-i", path.c_str(), "-u", kTestUserIdStr.c_str()}; + TestRollbackAfterEachStep(SIZEOFARRAY(argv), argv, [=]() -> bool { + EXTENDED_ASSERT_TRUE(ValidatePackage(pkgid, {appid1})); + // Check delta modifications + bf::path root_path = GetPackageRoot(pkgid, kTestUserId); + EXTENDED_ASSERT_TRUE(bf::exists(root_path / "res" / "wgt" / "DELETED")); + EXTENDED_ASSERT_FALSE(bf::exists(root_path / "res" / "wgt" / "ADDED")); + EXTENDED_ASSERT_TRUE(bf::exists(root_path / "lib" / "DELETED")); + EXTENDED_ASSERT_FALSE(bf::exists(root_path / "lib" / "ADDED")); + EXTENDED_ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/MODIFIED", + "version 1\n")); + EXTENDED_ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "lib/MODIFIED", + "version 1\n")); + EXTENDED_ASSERT_TRUE(ValidateDataFiles(pkgid, kTestUserId)); + return true; + }); +} + +TEST_F(SmokeTest, MountInstallationMode_Rollback_Hybrid) { + bf::path path = kSmokePackagesDirectory / + "MountInstallationMode_Rollback_Hybrid.wgt"; + std::string pkgid = "smokehyb09"; + std::string appid1 = "smokehyb09.web"; + const char* argv[] = {"", "-w", path.c_str(), "-u", kTestUserIdStr.c_str()}; + TestRollbackAfterEachStep(SIZEOFARRAY(argv), argv, [=]() -> bool { + ScopedTzipInterface interface(pkgid); + EXTENDED_ASSERT_TRUE(CheckPackageNonExistance(pkgid, {appid1})); + return true; + }, PackageType::HYBRID); +} + +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); + const char* argv[] = + {"", "-w", path_new.c_str(), "-u", kTestUserIdStr.c_str()}; + TestRollbackAfterEachStep(SIZEOFARRAY(argv), argv, [=]() -> bool { + ScopedTzipInterface interface(pkgid); + EXTENDED_ASSERT_TRUE(ValidatePackage(pkgid, {appid1})); + + EXTENDED_ASSERT_TRUE(ValidateFileContentInPackage(pkgid, + "res/wgt/VERSION", "1\n")); + EXTENDED_ASSERT_TRUE(ValidateFileContentInPackage(pkgid, + "lib/VERSION", "1\n")); + EXTENDED_ASSERT_TRUE(ValidateDataFiles(pkgid, kTestUserId)); + return true; + }); +} + +TEST_F(SmokeTest, MountInstallationMode_Rollback) { + bf::path path = + kSmokePackagesDirectory / "MountInstallationMode_Rollback.wgt"; + std::string pkgid = "smokewgt33"; + std::string appid = "smokewgt33.web"; + const char* argv[] = {"", "-w", path.c_str(), "-u", kTestUserIdStr.c_str()}; + TestRollbackAfterEachStep(SIZEOFARRAY(argv), argv, [=]() -> bool { + ScopedTzipInterface interface(pkgid); + EXTENDED_ASSERT_TRUE(CheckPackageNonExistance(pkgid, {appid})); + return true; + }); +} + +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); + const char* argv[] = + {"", "-w", path_new.c_str(), "-u", kTestUserIdStr.c_str()}; + TestRollbackAfterEachStep(SIZEOFARRAY(argv), argv, [=]() -> bool { + EXTENDED_ASSERT_EQ(MountInstall(path_new, PackageType::WGT, + RequestResult::FAIL), ci::AppInstaller::Result::ERROR); + ScopedTzipInterface interface(pkgid); + EXTENDED_ASSERT_TRUE(ValidatePackage(pkgid, {appid})); + + EXTENDED_ASSERT_TRUE(ValidateFileContentInPackage(pkgid, + "res/wgt/VERSION", "1\n")); + EXTENDED_ASSERT_TRUE(ValidateDataFiles(pkgid, kTestUserId)); + return true; + }); +} + +} // namespace common_installer + +int main(int argc, char** argv) { + ci::RequestMode request_mode = ParseRequestMode(argc, argv); + if (getuid() != 0 || request_mode != ci::RequestMode::GLOBAL) { + std::cout << "Skip tests for preload request" << std::endl; + ::testing::GTEST_FLAG(filter) = "SmokeTest.*"; + } + testing::InitGoogleTest(&argc, argv); + testing::Environment *env = testing::AddGlobalTestEnvironment( + new common_installer::SmokeEnvironment(request_mode)); + return RUN_ALL_TESTS(); +} diff --git a/src/unit_tests/smoke_test.cc b/src/unit_tests/smoke_test.cc index f446f8a..38c2b01 100644 --- a/src/unit_tests/smoke_test.cc +++ b/src/unit_tests/smoke_test.cc @@ -61,7 +61,7 @@ TEST_F(SmokeTest, InstallationMode) { std::string pkgid = "smokewgt03"; std::string appid = "smokewgt03.InstallationMode"; ASSERT_EQ(Install(path, PackageType::WGT), ci::AppInstaller::Result::OK); - ValidatePackage(pkgid, {appid}); + ASSERT_TRUE(ValidatePackage(pkgid, {appid})); } TEST_F(SmokeTest, UpdateMode) { @@ -72,10 +72,10 @@ TEST_F(SmokeTest, 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(ValidatePackage(pkgid, {appid})); ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "2\n")); - ValidateDataFiles(pkgid, kTestUserId); + ASSERT_TRUE(ValidateDataFiles(pkgid, kTestUserId)); } TEST_F(SmokeTest, DeinstallationMode) { @@ -86,7 +86,7 @@ TEST_F(SmokeTest, DeinstallationMode) { ci::AppInstaller::Result::OK); ASSERT_EQ(Uninstall(pkgid, PackageType::WGT, false), ci::AppInstaller::Result::OK); - CheckPackageNonExistance(pkgid, {appid}); + ASSERT_TRUE(CheckPackageNonExistance(pkgid, {appid})); } TEST_F(SmokeTest, RDSMode) { @@ -102,7 +102,7 @@ TEST_F(SmokeTest, RDSMode) { ASSERT_TRUE(CopyDir(delta_directory, sdk_expected_directory)); ASSERT_EQ(RDSUpdate(path, pkgid, PackageType::WGT), ci::AppInstaller::Result::OK); - ValidatePackage(pkgid, {appid}); + ASSERT_TRUE(ValidatePackage(pkgid, {appid})); // Check delta modifications ASSERT_FALSE(bf::exists(GetPackageRoot(pkgid, kTestUserId) / @@ -136,7 +136,7 @@ TEST_F(SmokeTest, DisablePkg) { ASSERT_EQ(DisablePackage(pkgid, PackageType::WGT), ci::AppInstaller::Result::OK); ASSERT_TRUE(ci::QueryIsDisabledPackage(pkgid, kTestUserId)); - ValidatePackage(pkgid, {appid}); + ASSERT_TRUE(ValidatePackage(pkgid, {appid})); } TEST_F(SmokeTest, DeltaMode) { @@ -146,7 +146,7 @@ TEST_F(SmokeTest, DeltaMode) { std::string appid = "smokewgt17.DeltaMode"; ASSERT_EQ(DeltaInstall(path, delta_package, PackageType::WGT), ci::AppInstaller::Result::OK); - ValidatePackage(pkgid, {appid}); + ASSERT_TRUE(ValidatePackage(pkgid, {appid})); // Check delta modifications ASSERT_FALSE(bf::exists(GetPackageRoot(pkgid, kTestUserId) / @@ -175,7 +175,7 @@ TEST_F(SmokeTest, RecoveryMode_ForInstallation) { ASSERT_FALSE(recovery_file.empty()); ASSERT_EQ(Recover(recovery_file, PackageType::WGT), ci::AppInstaller::Result::OK); - CheckPackageNonExistance(pkgid, {appid}); + ASSERT_TRUE(CheckPackageNonExistance(pkgid, {appid})); } TEST_F(SmokeTest, RecoveryMode_ForUpdate) { @@ -194,10 +194,10 @@ TEST_F(SmokeTest, RecoveryMode_ForUpdate) { ASSERT_FALSE(recovery_file.empty()); ASSERT_EQ(Recover(recovery_file, PackageType::WGT), ci::AppInstaller::Result::OK); - ValidatePackage(pkgid, {appid}); + ASSERT_TRUE(ValidatePackage(pkgid, {appid})); ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "1\n")); - ValidateDataFiles(pkgid, kTestUserId); + ASSERT_TRUE(ValidateDataFiles(pkgid, kTestUserId)); } TEST_F(SmokeTest, RecoveryMode_ForDelta) { @@ -215,7 +215,7 @@ TEST_F(SmokeTest, RecoveryMode_ForDelta) { ASSERT_FALSE(recovery_file.empty()); ASSERT_EQ(Recover(recovery_file, PackageType::WGT), ci::AppInstaller::Result::OK); - ValidatePackage(pkgid, {appid}); + ASSERT_TRUE(ValidatePackage(pkgid, {appid})); ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "1\n")); } @@ -233,7 +233,7 @@ TEST_F(SmokeTest, RecoveryMode_ForMountInstall) { ASSERT_FALSE(recovery_file.empty()); ASSERT_EQ(Recover(recovery_file, PackageType::WGT), ci::AppInstaller::Result::OK); - CheckPackageNonExistance(pkgid, {appid}); + ASSERT_TRUE(CheckPackageNonExistance(pkgid, {appid})); } TEST_F(SmokeTest, RecoveryMode_ForMountUpdate) { @@ -261,9 +261,9 @@ TEST_F(SmokeTest, RecoveryMode_ForMountUpdate) { ci::AppInstaller::Result::OK); ScopedTzipInterface interface(pkgid); - ValidatePackage(pkgid, {appid}); + ASSERT_TRUE(ValidatePackage(pkgid, {appid})); ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "1\n")); - ValidateDataFiles(pkgid, kTestUserId); + ASSERT_TRUE(ValidateDataFiles(pkgid, kTestUserId)); } TEST_F(SmokeTest, InstallationMode_GoodSignature) { @@ -284,7 +284,7 @@ TEST_F(SmokeTest, InstallationMode_Rollback) { std::string appid = "smokewgt06.InstallationModeRollback"; ASSERT_EQ(Install(path, PackageType::WGT, RequestResult::FAIL), ci::AppInstaller::Result::ERROR); - CheckPackageNonExistance(pkgid, {appid}); + ASSERT_TRUE(CheckPackageNonExistance(pkgid, {appid})); } TEST_F(SmokeTest, UpdateMode_Rollback) { @@ -296,10 +296,10 @@ TEST_F(SmokeTest, UpdateMode_Rollback) { AddDataFiles(pkgid, kTestUserId); ASSERT_EQ(Install(path_new, PackageType::WGT, RequestResult::FAIL), ci::AppInstaller::Result::ERROR); - ValidatePackage(pkgid, {appid}); + ASSERT_TRUE(ValidatePackage(pkgid, {appid})); ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "1\n")); - ValidateDataFiles(pkgid, kTestUserId); + ASSERT_TRUE(ValidateDataFiles(pkgid, kTestUserId)); } TEST_F(SmokeTest, DeltaMode_Rollback) { @@ -312,10 +312,10 @@ TEST_F(SmokeTest, DeltaMode_Rollback) { ASSERT_EQ(Install(delta_package, PackageType::WGT, RequestResult::FAIL), ci::AppInstaller::Result::ERROR); - ValidatePackage(pkgid, {appid}); + ASSERT_TRUE(ValidatePackage(pkgid, {appid})); ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/MODIFIED", "version 1\n")); - ValidateDataFiles(pkgid, kTestUserId); + ASSERT_TRUE(ValidateDataFiles(pkgid, kTestUserId)); ASSERT_TRUE(bf::exists(GetPackageRoot(pkgid, kTestUserId) / "res/wgt/DELETED")); ASSERT_FALSE(bf::exists(GetPackageRoot(pkgid, kTestUserId) / @@ -328,7 +328,7 @@ TEST_F(SmokeTest, InstallationMode_Hybrid) { // Excutable for native app doesn't create symlink std::string appid1 = "smokehyb01.Web"; ASSERT_EQ(Install(path, PackageType::HYBRID), ci::AppInstaller::Result::OK); - ValidatePackage(pkgid, {appid1}); + ASSERT_TRUE(ValidatePackage(pkgid, {appid1})); } TEST_F(SmokeTest, UpdateMode_Hybrid) { @@ -341,7 +341,7 @@ TEST_F(SmokeTest, UpdateMode_Hybrid) { // AddDataFiles(pkgid, kTestUserId); ASSERT_EQ(Install(path_new, PackageType::HYBRID), ci::AppInstaller::Result::OK); - ValidatePackage(pkgid, {appid1}); + ASSERT_TRUE(ValidatePackage(pkgid, {appid1})); ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "2\n")); ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "VERSION", "2\n")); @@ -356,7 +356,7 @@ TEST_F(SmokeTest, DeinstallationMode_Hybrid) { ci::AppInstaller::Result::OK); ASSERT_EQ(Uninstall(pkgid, PackageType::HYBRID, false), ci::AppInstaller::Result::OK); - CheckPackageNonExistance(pkgid, {appid1}); + ASSERT_TRUE(CheckPackageNonExistance(pkgid, {appid1})); } TEST_F(SmokeTest, DeltaMode_Hybrid) { @@ -366,7 +366,7 @@ TEST_F(SmokeTest, DeltaMode_Hybrid) { std::string appid1 = "smokehyb04.Web"; ASSERT_EQ(DeltaInstall(path, delta_package, PackageType::HYBRID), ci::AppInstaller::Result::OK); - ValidatePackage(pkgid, {appid1}); + ASSERT_TRUE(ValidatePackage(pkgid, {appid1})); // Check delta modifications bf::path root_path = ci::GetRootAppPath(false, @@ -389,7 +389,7 @@ TEST_F(SmokeTest, MountInstallationMode_Hybrid) { ASSERT_EQ(MountInstall(path, PackageType::HYBRID), ci::AppInstaller::Result::OK); ScopedTzipInterface interface(pkgid); - ValidatePackage(pkgid, {appid1}); + ASSERT_TRUE(ValidatePackage(pkgid, {appid1})); } TEST_F(SmokeTest, MountUpdateMode_Hybrid) { @@ -403,11 +403,11 @@ TEST_F(SmokeTest, MountUpdateMode_Hybrid) { ASSERT_EQ(MountInstall(path_new, PackageType::HYBRID), ci::AppInstaller::Result::OK); ScopedTzipInterface interface(pkgid); - ValidatePackage(pkgid, {appid1}); + ASSERT_TRUE(ValidatePackage(pkgid, {appid1})); ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "2\n")); ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "lib/VERSION", "2\n")); - ValidateDataFiles(pkgid, kTestUserId); + ASSERT_TRUE(ValidateDataFiles(pkgid, kTestUserId)); } TEST_F(SmokeTest, InstallationMode_Rollback_Hybrid) { @@ -417,7 +417,7 @@ TEST_F(SmokeTest, InstallationMode_Rollback_Hybrid) { std::string appid1 = "smokehyb07.web"; ASSERT_EQ(Install(path, PackageType::HYBRID, RequestResult::FAIL), ci::AppInstaller::Result::ERROR); - CheckPackageNonExistance(pkgid, {appid1}); + ASSERT_TRUE(CheckPackageNonExistance(pkgid, {appid1})); } TEST_F(SmokeTest, UpdateMode_Rollback_Hybrid) { @@ -432,11 +432,11 @@ TEST_F(SmokeTest, UpdateMode_Rollback_Hybrid) { AddDataFiles(pkgid, kTestUserId); ASSERT_EQ(Install(path_new, PackageType::HYBRID, RequestResult::FAIL), ci::AppInstaller::Result::ERROR); - ValidatePackage(pkgid, {appid1}); + ASSERT_TRUE(ValidatePackage(pkgid, {appid1})); ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "1\n")); ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "lib/VERSION", "1\n")); - ValidateDataFiles(pkgid, kTestUserId); + ASSERT_TRUE(ValidateDataFiles(pkgid, kTestUserId)); } TEST_F(SmokeTest, DeltaMode_Rollback_Hybrid) { @@ -450,7 +450,7 @@ TEST_F(SmokeTest, DeltaMode_Rollback_Hybrid) { ASSERT_EQ(Install(delta_package, PackageType::HYBRID, RequestResult::FAIL), ci::AppInstaller::Result::ERROR); - ValidatePackage(pkgid, {appid1}); + ASSERT_TRUE(ValidatePackage(pkgid, {appid1})); // Check delta modifications bf::path root_path = GetPackageRoot(pkgid, kTestUserId); ASSERT_TRUE(bf::exists(root_path / "res" / "wgt" / "DELETED")); @@ -461,7 +461,7 @@ TEST_F(SmokeTest, DeltaMode_Rollback_Hybrid) { "version 1\n")); ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "lib/MODIFIED", "version 1\n")); - ValidateDataFiles(pkgid, kTestUserId); + ASSERT_TRUE(ValidateDataFiles(pkgid, kTestUserId)); } TEST_F(SmokeTest, MountInstallationMode_Rollback_Hybrid) { @@ -472,7 +472,7 @@ TEST_F(SmokeTest, MountInstallationMode_Rollback_Hybrid) { ASSERT_EQ(MountInstall(path, PackageType::HYBRID, RequestResult::FAIL), ci::AppInstaller::Result::ERROR); ScopedTzipInterface interface(pkgid); - CheckPackageNonExistance(pkgid, {appid1}); + ASSERT_TRUE(CheckPackageNonExistance(pkgid, {appid1})); } TEST_F(SmokeTest, MountUpdateMode_Rollback_Hybrid) { @@ -488,11 +488,11 @@ TEST_F(SmokeTest, MountUpdateMode_Rollback_Hybrid) { ASSERT_EQ(MountInstall(path_new, PackageType::HYBRID, RequestResult::FAIL), ci::AppInstaller::Result::ERROR); ScopedTzipInterface interface(pkgid); - ValidatePackage(pkgid, {appid1}); + ASSERT_TRUE(ValidatePackage(pkgid, {appid1})); ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "1\n")); ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "lib/VERSION", "1\n")); - ValidateDataFiles(pkgid, kTestUserId); + ASSERT_TRUE(ValidateDataFiles(pkgid, kTestUserId)); } TEST_F(SmokeTest, MountInstallationMode) { @@ -501,7 +501,7 @@ TEST_F(SmokeTest, MountInstallationMode) { std::string appid = "smokewgt28.InstallationMode"; ASSERT_EQ(MountInstall(path, PackageType::WGT), ci::AppInstaller::Result::OK); ScopedTzipInterface interface(pkgid); - ValidatePackage(pkgid, {appid}); + ASSERT_TRUE(ValidatePackage(pkgid, {appid})); } TEST_F(SmokeTest, MountUpdateMode) { @@ -515,10 +515,10 @@ TEST_F(SmokeTest, MountUpdateMode) { ASSERT_EQ(MountInstall(path_new, PackageType::WGT), ci::AppInstaller::Result::OK); ScopedTzipInterface interface(pkgid); - ValidatePackage(pkgid, {appid}); + ASSERT_TRUE(ValidatePackage(pkgid, {appid})); ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "2\n")); - ValidateDataFiles(pkgid, kTestUserId); + ASSERT_TRUE(ValidateDataFiles(pkgid, kTestUserId)); } TEST_F(SmokeTest, MountInstallationMode_Rollback) { @@ -529,7 +529,7 @@ TEST_F(SmokeTest, MountInstallationMode_Rollback) { ASSERT_EQ(MountInstall(path, PackageType::WGT, RequestResult::FAIL), ci::AppInstaller::Result::ERROR); ScopedTzipInterface interface(pkgid); - CheckPackageNonExistance(pkgid, {appid}); + ASSERT_TRUE(CheckPackageNonExistance(pkgid, {appid})); } TEST_F(SmokeTest, MountUpdateMode_Rollback) { @@ -544,10 +544,10 @@ TEST_F(SmokeTest, MountUpdateMode_Rollback) { ASSERT_EQ(MountInstall(path_new, PackageType::WGT, RequestResult::FAIL), ci::AppInstaller::Result::ERROR); ScopedTzipInterface interface(pkgid); - ValidatePackage(pkgid, {appid}); + ASSERT_TRUE(ValidatePackage(pkgid, {appid})); ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "1\n")); - ValidateDataFiles(pkgid, kTestUserId); + ASSERT_TRUE(ValidateDataFiles(pkgid, kTestUserId)); } TEST_F(SmokeTest, UserDefinedPlugins) { @@ -559,7 +559,7 @@ TEST_F(SmokeTest, UserDefinedPlugins) { std::string power_privilege = "http://tizen.org/privilege/power"; ASSERT_EQ(Install(path, PackageType::WGT), ci::AppInstaller::Result::OK); - ValidatePackage(pkgid, {appid}); + ASSERT_TRUE(ValidatePackage(pkgid, {appid})); std::vector res; ASSERT_TRUE(ci::QueryPrivilegesForPkgId(pkgid, kTestUserId, &res)); ASSERT_TRUE(std::find(res.begin(), res.end(), call_privilege) != res.end()); @@ -597,7 +597,7 @@ TEST_F(PreloadSmokeTest, InstallationMode_Preload) { std::string appid = "smokewgt37.InstallationModePreload"; ASSERT_EQ(InstallPreload(path, PackageType::WGT), ci::AppInstaller::Result::OK); - ValidatePackage(pkgid, {appid}, true); + ASSERT_TRUE(ValidatePackage(pkgid, {appid}, true)); } TEST_F(PreloadSmokeTest, UpdateMode_Preload) { @@ -611,11 +611,11 @@ TEST_F(PreloadSmokeTest, UpdateMode_Preload) { AddDataFiles(pkgid, kTestUserId); ASSERT_EQ(InstallPreload(path_new, PackageType::WGT), ci::AppInstaller::Result::OK); - ValidatePackage(pkgid, {appid}, true); + ASSERT_TRUE(ValidatePackage(pkgid, {appid}, true)); ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "2", true)); - ValidateDataFiles(pkgid, kTestUserId); + ASSERT_TRUE(ValidateDataFiles(pkgid, kTestUserId)); } TEST_F(PreloadSmokeTest, DeinstallationMode_Preload) { @@ -646,7 +646,7 @@ TEST_F(SmokeTest, SharedRes30) { std::string pkgid = "smokeSh3xx"; std::string appid = "smokeSh3xx.SharedRes30"; ASSERT_EQ(Install(path, PackageType::WGT), ci::AppInstaller::Result::OK); - ValidatePackage(pkgid, {appid}); + ASSERT_TRUE(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 @@ -659,7 +659,7 @@ TEST_F(SmokeTest, SharedRes30Delta) { std::string appid = "smokeSh3De.SharedRes30Delta"; ASSERT_EQ(DeltaInstall(path, delta_package, PackageType::WGT), ci::AppInstaller::Result::OK); - ValidatePackage(pkgid, {appid}); + ASSERT_TRUE(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 @@ -674,7 +674,7 @@ TEST_F(SmokeTest, SharedRes30Hybrid) { std::string appid1 = "smokeSh3Hy.SharedRes30Hybrid"; std::string appid2 = "sharedres30hybridserivce"; ASSERT_EQ(Install(path, PackageType::HYBRID), ci::AppInstaller::Result::OK); - ValidatePackage(pkgid, {appid1, appid2}); + ASSERT_TRUE(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 @@ -691,7 +691,7 @@ TEST_F(SmokeTest, SharedRes30HybridDelta) { std::string appid2 = "sharedres30hybriddeltaserivce"; ASSERT_EQ(DeltaInstall(path, delta_package, PackageType::HYBRID), ci::AppInstaller::Result::OK); - ValidatePackage(pkgid, {appid1, appid2}); + ASSERT_TRUE(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 diff --git a/src/unit_tests/smoke_test_helper.cc b/src/unit_tests/smoke_test_helper.cc index 0d37d1c..4501e89 100644 --- a/src/unit_tests/smoke_test_helper.cc +++ b/src/unit_tests/smoke_test_helper.cc @@ -31,6 +31,14 @@ class StepCrash : public ci::Step { // this main of test binay in done purely for recovery smoke test. int main(int argc, char** argv) { + int index = -1; + int backend_argc = argc; + if (!strcmp(argv[argc-2], "-idx")) { + index = atoi(argv[argc-1]); + backend_argc = argc - 2; + LOG(DEBUG) << "Step crash after " << index << " step."; + } + ci::PkgmgrInstaller pkgmgr_installer; wgt::WgtAppQueryInterface query_interface; auto pkgmgr = ci::PkgMgrInterface::Create(argc, argv, &pkgmgr_installer, @@ -41,7 +49,11 @@ int main(int argc, char** argv) { } wgt::WgtInstaller installer(pkgmgr); - installer.AddStep(); + if (index != -1) { + installer.AddStepAtIndex(index); + } else { + installer.AddStep(); + } return (installer.Run() == ci::AppInstaller::Result::OK) ? 0 : 1; } diff --git a/src/unit_tests/smoke_utils.cc b/src/unit_tests/smoke_utils.cc index c1750f1..fff20f4 100644 --- a/src/unit_tests/smoke_utils.cc +++ b/src/unit_tests/smoke_utils.cc @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -249,82 +250,83 @@ void AddDataFiles(const std::string& pkgid, uid_t uid) { } } -void ValidateDataFiles(const std::string& pkgid, uid_t uid) { +bool 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")); + EXTENDED_ASSERT_TRUE(bf::exists(pkg_path / "data" / "file1.txt")); + EXTENDED_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")); + EXTENDED_ASSERT_TRUE(bf::exists(pkg_path / "data" / "file1.txt")); + EXTENDED_ASSERT_TRUE(bf::exists(pkg_path / "data" / "file2.txt")); } + return true; } -void ValidatePackageRWFS(const std::string& pkgid, uid_t uid) { +bool 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)); + EXTENDED_ASSERT_TRUE(bf::exists(data_path)); + EXTENDED_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 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; + EXTENDED_ASSERT_EQ(uid, stats.st_uid); + EXTENDED_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) << "Invalid gid: " << shared_data_path; - ASSERT_EQ(*system_share, stats.st_gid) << "Invalid gid: " - << shared_data_path; + EXTENDED_ASSERT_EQ(uid, stats.st_uid); + EXTENDED_ASSERT_EQ(*system_share, stats.st_gid); } 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; + EXTENDED_ASSERT_EQ(uid, stats.st_uid); + EXTENDED_ASSERT_EQ(*system_share, stats.st_gid); + return true; } -void ValidatePackageFS(const std::string& pkgid, +bool ValidatePackageFS(const std::string& pkgid, const std::vector& 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 shared_path = package_path / "shared"; - ASSERT_TRUE(bf::exists(root_path)); - ASSERT_TRUE(bf::exists(package_path)); - ASSERT_TRUE(bf::exists(shared_path)); + EXTENDED_ASSERT_TRUE(bf::exists(root_path)); + EXTENDED_ASSERT_TRUE(bf::exists(package_path)); + EXTENDED_ASSERT_TRUE(bf::exists(shared_path)); bf::path manifest_path = bf::path(getUserManifestPath(uid, is_readonly)) / (pkgid + ".xml"); - ASSERT_TRUE(bf::exists(manifest_path)); + EXTENDED_ASSERT_TRUE(bf::exists(manifest_path)); for (auto& appid : appids) { bf::path binary_path = package_path / "bin" / appid; - ASSERT_TRUE(bf::exists(binary_path)); + EXTENDED_ASSERT_TRUE(bf::exists(binary_path)); } bf::path widget_root_path = package_path / "res" / "wgt"; bf::path config_path = widget_root_path / "config.xml"; - ASSERT_TRUE(bf::exists(widget_root_path)); - ASSERT_TRUE(bf::exists(config_path)); + EXTENDED_ASSERT_TRUE(bf::exists(widget_root_path)); + EXTENDED_ASSERT_TRUE(bf::exists(config_path)); bf::path private_tmp_path = package_path / "tmp"; - ASSERT_TRUE(bf::exists(private_tmp_path)); + EXTENDED_ASSERT_TRUE(bf::exists(private_tmp_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)); + EXTENDED_ASSERT_FALSE(bf::exists(package_backup)); + EXTENDED_ASSERT_FALSE(bf::exists(manifest_backup)); for (bf::recursive_directory_iterator iter(package_path); iter != bf::recursive_directory_iterator(); ++iter) { @@ -342,9 +344,10 @@ void ValidatePackageFS(const std::string& pkgid, } 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(); + EXTENDED_ASSERT_EQ(uid, stats.st_uid); + EXTENDED_ASSERT_EQ(gid, stats.st_gid); } + return true; } void PackageCheckCleanup(const std::string& pkgid, @@ -364,18 +367,20 @@ void PackageCheckCleanup(const std::string& pkgid, ASSERT_FALSE(bf::exists(manifest_backup)); } -void ValidatePackage(const std::string& pkgid, +bool ValidatePackage(const std::string& pkgid, const std::vector& appids, bool is_readonly) { - ASSERT_TRUE(ci::QueryIsPackageInstalled( + EXTENDED_ASSERT_TRUE(ci::QueryIsPackageInstalled( pkgid, ci::GetRequestMode(kTestUserId), kTestUserId)); - ValidatePackageFS(pkgid, appids, kTestUserId, kTestGroupId, is_readonly); + EXTENDED_ASSERT_TRUE(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)); + EXTENDED_ASSERT_TRUE(ValidatePackageRWFS(pkgid, std::get<0>(l))); } else { - ValidatePackageRWFS(pkgid, kTestUserId); + EXTENDED_ASSERT_TRUE(ValidatePackageRWFS(pkgid, kTestUserId)); } + return true; } void ValidateExternalPackageFS(const std::string& pkgid, @@ -411,22 +416,23 @@ void ValidateExternalPackage(const std::string& pkgid, } } -void CheckPackageNonExistance(const std::string& pkgid, +bool CheckPackageNonExistance(const std::string& pkgid, const std::vector& appids) { - ASSERT_FALSE(ci::QueryIsPackageInstalled( + EXTENDED_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)); + EXTENDED_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)); + EXTENDED_ASSERT_FALSE(bf::exists(package_path)); } } + return true; } void CheckPackageReadonlyNonExistance(const std::string& pkgid, @@ -456,6 +462,68 @@ std::unique_ptr CreateInstaller(ci::PkgMgrPtr pkgmgr, } } +void TestRollbackAfterEachStep(int argc, const char*argv[], + std::function validator, + PackageType type) { + TestPkgmgrInstaller pkgmgr_installer; + std::unique_ptr query_interface = + CreateQueryInterface(); + auto pkgmgr = + ci::PkgMgrInterface::Create(argc, const_cast(argv), + &pkgmgr_installer, + query_interface.get()); + if (!pkgmgr) { + LOG(ERROR) << "Failed to initialize pkgmgr interface"; + return; + } + std::unique_ptr backend = CreateInstaller(pkgmgr, type); + int i; + for (i = backend->StepCount()-1; i >= 0; i--) { + backend->AddStepAtIndex(i); + LOG(DEBUG) << "StepFail is inserted at: " << i; + ASSERT_EQ(ci::AppInstaller::Result::ERROR, + backend->Run()); + if (!validator()) + break; + } + ASSERT_EQ(-1, i); +} + +void CrashAfterEachStep(std::vector args, + std::function validator, + PackageType type) { + std::unique_ptr argv(new const char*[args.size()]); + for (size_t i = 0; i < args.size(); ++i) { + argv[i] = args[i].c_str(); + } + TestPkgmgrInstaller pkgmgr_installer; + std::unique_ptr query_interface = + CreateQueryInterface(); + auto pkgmgr = + ci::PkgMgrInterface::Create(args.size(), const_cast(argv.get()), + &pkgmgr_installer, + query_interface.get()); + if (!pkgmgr) { + LOG(ERROR) << "Failed to initialize pkgmgr interface"; + return; + } + std::unique_ptr backend = CreateInstaller(pkgmgr, type); + int stepCount = backend->StepCount(); + + args.push_back("-idx"); + args.push_back(std::to_string(stepCount)); + int i; + for (i = 0; i < stepCount; i++) { + ci::Subprocess backend_crash("/usr/bin/tpk-backend-ut/smoke-test-helper"); + args.back() = std::to_string(i); + backend_crash.Run(args); + ASSERT_NE(backend_crash.Wait(), 0); + if (!validator(i)) + break; + } + ASSERT_EQ(stepCount, i); +} + ci::AppInstaller::Result RunInstallerWithPkgrmgr(ci::PkgMgrPtr pkgmgr, PackageType type, RequestResult mode) { diff --git a/src/unit_tests/smoke_utils.h b/src/unit_tests/smoke_utils.h index efc2551..d0a4b47 100644 --- a/src/unit_tests/smoke_utils.h +++ b/src/unit_tests/smoke_utils.h @@ -5,6 +5,7 @@ #ifndef UNIT_TESTS_SMOKE_UTILS_H_ #define UNIT_TESTS_SMOKE_UTILS_H_ + #include #include @@ -25,6 +26,27 @@ #define SIZEOFARRAY(ARR) \ sizeof(ARR) / sizeof(ARR[0]) \ +#define EXTENDED_ASSERT_TRUE(expression) do { \ + bool tmp = expression; \ + EXPECT_TRUE(tmp) << #expression << " is not true"; \ + if (!tmp) \ + return false; \ +} while (0); + +#define EXTENDED_ASSERT_FALSE(expression) do { \ + bool tmp = expression; \ + EXPECT_FALSE(tmp) << #expression << " is not false"; \ + if (tmp) \ + return false; \ +} while (0); + +#define EXTENDED_ASSERT_EQ(expression, value) do { \ + auto ret = expression; \ + EXPECT_EQ(ret, value) << #expression << " is not equal to " << #value; \ + if (ret != value) \ + return false; \ +} while (0); + namespace bf = boost::filesystem; namespace bs = boost::system; namespace ci = common_installer; @@ -140,18 +162,18 @@ bool ValidateFileContentInPackage(const std::string& pkgid, void AddDataFiles(const std::string& pkgid, uid_t uid); -void ValidateDataFiles(const std::string& pkgid, uid_t uid); +bool ValidateDataFiles(const std::string& pkgid, uid_t uid); -void ValidatePackageRWFS(const std::string& pkgid, uid_t uid); +bool ValidatePackageRWFS(const std::string& pkgid, uid_t uid); -void ValidatePackageFS(const std::string& pkgid, +bool ValidatePackageFS(const std::string& pkgid, const std::vector& appids, uid_t uid, gid_t gid, bool is_readonly); void PackageCheckCleanup(const std::string& pkgid, const std::vector&, bool is_readonly = false); -void ValidatePackage(const std::string& pkgid, +bool ValidatePackage(const std::string& pkgid, const std::vector& appids, bool is_readonly = false); void ValidateExternalPackageFS(const std::string& pkgid, @@ -161,7 +183,7 @@ void ValidateExternalPackageFS(const std::string& pkgid, void ValidateExternalPackage(const std::string& pkgid, const std::vector& appids); -void CheckPackageNonExistance(const std::string& pkgid, +bool CheckPackageNonExistance(const std::string& pkgid, const std::vector& appids); void CheckPackageReadonlyNonExistance(const std::string& pkgid, @@ -172,6 +194,14 @@ std::unique_ptr CreateQueryInterface(); std::unique_ptr CreateInstaller(ci::PkgMgrPtr pkgmgr, PackageType type); +void TestRollbackAfterEachStep(int argc, const char*argv[], + std::function validator, + PackageType type = PackageType::WGT); + +void CrashAfterEachStep(std::vector args, + std::function validator, + PackageType type = PackageType::WGT); + ci::AppInstaller::Result RunInstallerWithPkgrmgr(ci::PkgMgrPtr pkgmgr, PackageType type, RequestResult mode); -- 2.7.4 From 390d91ff1033a94414b93d054cff94393962c30b Mon Sep 17 00:00:00 2001 From: Damian Pietruchowski Date: Thu, 23 Mar 2017 15:11:17 +0100 Subject: [PATCH 03/16] [SmokeTest] Fixes for ParseRequestMode() function - Allow to parse unknown options. - Return global request mode for unknown options. Change-Id: I2f2c71820a6f5e8552842f4c3ee0378617176aa8 Signed-off-by: Damian Pietruchowski --- src/unit_tests/smoke_utils.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/unit_tests/smoke_utils.cc b/src/unit_tests/smoke_utils.cc index fff20f4..c88f3fa 100644 --- a/src/unit_tests/smoke_utils.cc +++ b/src/unit_tests/smoke_utils.cc @@ -84,7 +84,8 @@ ci::RequestMode ParseRequestMode(int argc, char** argv) { ("user-request,u", "set request mode to user"); bo::variables_map vm; - bo::store(bo::parse_command_line(argc, argv, desc), vm); + bo::store(bo::command_line_parser(argc, argv). + options(desc).allow_unregistered().run(), vm); bo::notify(vm); if (vm.count("global-request")) { @@ -106,9 +107,9 @@ ci::RequestMode ParseRequestMode(int argc, char** argv) { } std::cout << "Cannot set request mode to " << vm["request-mode"].as() << std::endl; - std::cout << "Request mode was set to global." << std::endl; - return ci::RequestMode::GLOBAL; } + std::cout << "Request mode was set to global." << std::endl; + return ci::RequestMode::GLOBAL; } bool TouchFile(const bf::path& path) { -- 2.7.4 From 8e4ad744154151aee46f6fdbc39077bf6a483c3a Mon Sep 17 00:00:00 2001 From: Damian Pietruchowski Date: Mon, 27 Mar 2017 14:21:35 +0200 Subject: [PATCH 04/16] [SmokeTest] Fix for recovery smoke tests Change-Id: I464fd123c34ddd4dac14a319e586a6e1c45c4dea Signed-off-by: Damian Pietruchowski --- src/unit_tests/smoke_test_helper.cc | 2 +- src/unit_tests/smoke_utils.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/unit_tests/smoke_test_helper.cc b/src/unit_tests/smoke_test_helper.cc index 4501e89..156b64b 100644 --- a/src/unit_tests/smoke_test_helper.cc +++ b/src/unit_tests/smoke_test_helper.cc @@ -41,7 +41,7 @@ int main(int argc, char** argv) { ci::PkgmgrInstaller pkgmgr_installer; wgt::WgtAppQueryInterface query_interface; - auto pkgmgr = ci::PkgMgrInterface::Create(argc, argv, &pkgmgr_installer, + auto pkgmgr = ci::PkgMgrInterface::Create(backend_argc, argv, &pkgmgr_installer, &query_interface); if (!pkgmgr) { LOG(ERROR) << "Options of pkgmgr installer cannot be parsed"; diff --git a/src/unit_tests/smoke_utils.cc b/src/unit_tests/smoke_utils.cc index c88f3fa..24f92b3 100644 --- a/src/unit_tests/smoke_utils.cc +++ b/src/unit_tests/smoke_utils.cc @@ -515,7 +515,7 @@ void CrashAfterEachStep(std::vector args, args.push_back(std::to_string(stepCount)); int i; for (i = 0; i < stepCount; i++) { - ci::Subprocess backend_crash("/usr/bin/tpk-backend-ut/smoke-test-helper"); + ci::Subprocess backend_crash("/usr/bin/wgt-backend-ut/smoke-test-helper"); args.back() = std::to_string(i); backend_crash.Run(args); ASSERT_NE(backend_crash.Wait(), 0); -- 2.7.4 From 36493ef3231a513608a91d768345f40618301d47 Mon Sep 17 00:00:00 2001 From: Damian Pietruchowski Date: Thu, 6 Apr 2017 16:13:09 +0200 Subject: [PATCH 05/16] [SmokeTest] Add SIGINT and SIGSEGV handling Change-Id: I497435a6d89a7df26bbfe19e4fd308be2dd9b55d Signed-off-by: Damian Pietruchowski --- src/unit_tests/extensive_smoke_test.cc | 4 +++- src/unit_tests/smoke_test.cc | 6 +++--- src/unit_tests/smoke_utils.cc | 6 ++++++ src/unit_tests/smoke_utils.h | 5 +++++ 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/unit_tests/extensive_smoke_test.cc b/src/unit_tests/extensive_smoke_test.cc index 58f11f6..043c293 100644 --- a/src/unit_tests/extensive_smoke_test.cc +++ b/src/unit_tests/extensive_smoke_test.cc @@ -382,7 +382,9 @@ int main(int argc, char** argv) { ::testing::GTEST_FLAG(filter) = "SmokeTest.*"; } testing::InitGoogleTest(&argc, argv); - testing::Environment *env = testing::AddGlobalTestEnvironment( + env = testing::AddGlobalTestEnvironment( new common_installer::SmokeEnvironment(request_mode)); + signal(SIGINT, signalHandler); + signal(SIGSEGV, signalHandler); return RUN_ALL_TESTS(); } diff --git a/src/unit_tests/smoke_test.cc b/src/unit_tests/smoke_test.cc index 38c2b01..9b90c2a 100644 --- a/src/unit_tests/smoke_test.cc +++ b/src/unit_tests/smoke_test.cc @@ -3,10 +3,8 @@ // found in the LICENSE file. #include - #include -#include #include #include "unit_tests/smoke_utils.h" @@ -711,7 +709,9 @@ int main(int argc, char** argv) { ::testing::GTEST_FLAG(filter) = "SmokeTest.*"; } testing::InitGoogleTest(&argc, argv); - testing::Environment *env = testing::AddGlobalTestEnvironment( + env = testing::AddGlobalTestEnvironment( new common_installer::SmokeEnvironment(request_mode)); + signal(SIGINT, signalHandler); + signal(SIGSEGV, signalHandler); return RUN_ALL_TESTS(); } diff --git a/src/unit_tests/smoke_utils.cc b/src/unit_tests/smoke_utils.cc index 24f92b3..2ef8402 100644 --- a/src/unit_tests/smoke_utils.cc +++ b/src/unit_tests/smoke_utils.cc @@ -75,6 +75,11 @@ const char kPreloadApps[] = "/usr/apps"; const char kPreloadManifestDir[] = "/usr/share/packages"; const char kPreloadIcons[] = "/usr/share/icons"; +testing::Environment *env = nullptr; +void signalHandler(int signum) { + env->TearDown(); + exit(signum); +} ci::RequestMode ParseRequestMode(int argc, char** argv) { bo::options_description desc("Available options"); @@ -817,6 +822,7 @@ void UninstallAllAppsInDirectory(bf::path dir, bool is_preload) { } void UninstallAllSmokeApps(ci::RequestMode request_mode) { + std::cout << "Uninstalling all smoke apps" << std::endl; if (getuid() == 0 && request_mode == ci::RequestMode::GLOBAL) { bf::path root_path = kPreloadApps; UninstallAllAppsInDirectory(root_path, true); diff --git a/src/unit_tests/smoke_utils.h b/src/unit_tests/smoke_utils.h index d0a4b47..448b71f 100644 --- a/src/unit_tests/smoke_utils.h +++ b/src/unit_tests/smoke_utils.h @@ -16,6 +16,8 @@ #include #include +#include + #include #include #include @@ -84,6 +86,9 @@ extern const char kPreloadApps[]; extern const char kPreloadManifestDir[]; extern const char kPreloadIcons[]; +extern testing::Environment *env; +void signalHandler(int signum); + enum class RequestResult { NORMAL, FAIL -- 2.7.4 From 1ce595996ed65c28b72fd41d1ed220fd92bd7ad9 Mon Sep 17 00:00:00 2001 From: jongmyeongko Date: Sat, 8 Apr 2017 15:51:26 +0900 Subject: [PATCH 06/16] Fix Mount Installation Failure Requires : https://review.tizen.org/gerrit/#/c/123947/ Change-Id: Icd0342eab4266467288d06cbe88f573e1a16ee63 Signed-off-by: jongmyeongko (cherry picked from commit 77476e84f50dd9b72a7e1cf2341c50dedd4d10cc) --- src/hybrid/hybrid_installer.cc | 4 ++-- src/wgt/wgt_installer.cc | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hybrid/hybrid_installer.cc b/src/hybrid/hybrid_installer.cc index 9c83f0b..ba50202 100644 --- a/src/hybrid/hybrid_installer.cc +++ b/src/hybrid/hybrid_installer.cc @@ -350,7 +350,7 @@ HybridInstaller::HybridInstaller(common_installer::PkgMgrPtr pkgmgr) ci::Plugin::ActionType::Install); AddStep( wgt::filesystem::HybridAdditionalSharedDirs); - AddStep(); + AddStep(true); AddStep(); break; case ci::RequestType::MountUpdate: @@ -399,7 +399,7 @@ HybridInstaller::HybridInstaller(common_installer::PkgMgrPtr pkgmgr) AddStep(); AddStep( ci::Plugin::ActionType::Upgrade); - AddStep(); + AddStep(true); AddStep(); break; case ci::RequestType::ManifestDirectInstall: diff --git a/src/wgt/wgt_installer.cc b/src/wgt/wgt_installer.cc index ee1f9b3..475c05e 100755 --- a/src/wgt/wgt_installer.cc +++ b/src/wgt/wgt_installer.cc @@ -434,7 +434,7 @@ WgtInstaller::WgtInstaller(ci::PkgMgrPtr pkgrmgr) ci::Plugin::ActionType::Install); AddStep( wgt::filesystem::WgtAdditionalSharedDirs); - AddStep(); + AddStep(true); AddStep(); } @@ -475,7 +475,7 @@ WgtInstaller::WgtInstaller(ci::PkgMgrPtr pkgrmgr) AddStep(); AddStep( ci::Plugin::ActionType::Upgrade); - AddStep(); + AddStep(true); AddStep(); } -- 2.7.4 From 330a232445b9db00f63f3975a1338e7116bd570c Mon Sep 17 00:00:00 2001 From: Damian Pietruchowski Date: Fri, 7 Apr 2017 13:02:40 +0200 Subject: [PATCH 07/16] [SmokeTest] Fix restore backup When something goes wrong (for example unmount failed) then backup is not restored. After that fix, directory, which could not be removed, will be renamed to path with "trash" extension. User have to remove this directory manually.. Change-Id: Ie616f27f1bccbe2d5efbc31316f7b99cf6fec87b Signed-off-by: Damian Pietruchowski --- src/unit_tests/smoke_test.cc | 4 ++-- src/unit_tests/smoke_utils.cc | 42 +++++++++++++++++++++++++++++++++++------- src/unit_tests/smoke_utils.h | 4 ++-- 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/src/unit_tests/smoke_test.cc b/src/unit_tests/smoke_test.cc index 9b90c2a..35bdfbc 100644 --- a/src/unit_tests/smoke_test.cc +++ b/src/unit_tests/smoke_test.cc @@ -27,7 +27,7 @@ class SmokeEnvironment : public testing::Environment { } backups_ = SetupBackupDirectories(); for (auto& path : backups_) - BackupPath(path); + ASSERT_TRUE(BackupPath(path)); } void TearDown() override { ASSERT_TRUE(request_mode_ == ci::RequestMode::GLOBAL || @@ -35,7 +35,7 @@ class SmokeEnvironment : public testing::Environment { kGlobalUserUid != kTestUserId)); UninstallAllSmokeApps(request_mode_); for (auto& path : backups_) - RestorePath(path); + ASSERT_TRUE(RestorePath(path)); if (request_mode_ == ci::RequestMode::USER) ASSERT_TRUE(DeleteTestUser(kNormalUserName)); } diff --git a/src/unit_tests/smoke_utils.cc b/src/unit_tests/smoke_utils.cc index 2ef8402..ec50e82 100644 --- a/src/unit_tests/smoke_utils.cc +++ b/src/unit_tests/smoke_utils.cc @@ -729,7 +729,21 @@ ci::AppInstaller::Result Recover(const bf::path& recovery_file, return CallBackend(SIZEOFARRAY(argv), argv, type, mode); } -void BackupPath(const bf::path& path) { +namespace { + +boost::filesystem::path GetTrashPath(const boost::filesystem::path& path) { + return path.string() + ".trash"; +} + +} + +bool BackupPath(const bf::path& path) { + bf::path trash_path = GetTrashPath(path); + if (bf::exists(trash_path)) { + LOG(ERROR) << trash_path << " exists. Please remove " + << trash_path << " manually!"; + return false; + } bf::path backup_path = path.string() + ".bck"; std::cout << "Backup path: " << path << " to " << backup_path << std::endl; bs::error_code error; @@ -739,28 +753,42 @@ void BackupPath(const bf::path& path) { << " (" << error.message() << ")"; if (bf::exists(path)) { bf::rename(path, backup_path, error); - if (error) + if (error) { LOG(ERROR) << "Failed to setup test environment. Does some previous" << " test crashed? Path: " << backup_path << " should not exist."; + return false; + } assert(!error); } + return true; } -void RestorePath(const bf::path& path) { +bool 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 (error) { + bf::path trash_path = GetTrashPath(path); + LOG(ERROR) << "Remove failed: " << path << " (" << error.message() << ")"; + std::cout << "Moving " << path << " to " << trash_path << std::endl; + bf::rename(path, trash_path, error); + if (error) + LOG(ERROR) << "Failed to move " << path << " to " << trash_path + << " (" << error.message() << ")"; + else + LOG(ERROR) << trash_path << " should be removed manually!"; + } if (bf::exists(backup_path)) { bf::rename(backup_path, path, error); - if (error) + if (error) { LOG(ERROR) << "Failed to restore backup path: " << backup_path << " (" << error.message() << ")"; + return false; + } } + return true; } std::vector SetupBackupDirectories() { diff --git a/src/unit_tests/smoke_utils.h b/src/unit_tests/smoke_utils.h index 448b71f..808e19b 100644 --- a/src/unit_tests/smoke_utils.h +++ b/src/unit_tests/smoke_utils.h @@ -263,9 +263,9 @@ ci::AppInstaller::Result Recover(const bf::path& recovery_file, PackageType type, RequestResult mode = RequestResult::NORMAL); -void BackupPath(const bf::path& path); +bool BackupPath(const bf::path& path); -void RestorePath(const bf::path& path); +bool RestorePath(const bf::path& path); std::vector SetupBackupDirectories(); -- 2.7.4 From 88fc2091153fda400934a7056617b8bc16e12383 Mon Sep 17 00:00:00 2001 From: jongmyeongko Date: Wed, 19 Apr 2017 18:15:56 +0900 Subject: [PATCH 08/16] Fix crash issue when getting the locale was failed Change-Id: Id4c860204b942a636bbd6f01b00ae99551cbddc7 Signed-off-by: jongmyeongko --- src/lib/wgt_archive_info.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lib/wgt_archive_info.cc b/src/lib/wgt_archive_info.cc index 5e95b1f..eb508e1 100644 --- a/src/lib/wgt_archive_info.cc +++ b/src/lib/wgt_archive_info.cc @@ -28,7 +28,7 @@ namespace ci = common_installer; namespace { -const char kVconfLanguageKey[] = "db/menu_widget/language"; +const char kVconfLanguageKey[] = VCONFKEY_LANGSET; const char kConfigFileName[] = "config.xml"; const char kHybridConfigFileName[] = "res/wgt/config.xml"; @@ -226,6 +226,8 @@ bool WgtArchiveInfo::GetArchiveInfo(const char* file_path, } char* locale = vconf_get_str(kVconfLanguageKey); + if (!locale) + locale = strdup(""); if (!GetLabelInfo(parser, locale, info)) LOG(WARNING) << "Failed to get label info"; if (!GetDescriptionInfo(parser, locale, info)) -- 2.7.4 From c2fd87783a4f43f8e11f0bfb5f5144b737cb0e55 Mon Sep 17 00:00:00 2001 From: Sangyoon Jang Date: Wed, 24 May 2017 14:38:17 +0900 Subject: [PATCH 09/16] Fix crash when parsing icon info from wgt archive Change-Id: Ifa4866a495af0764be72eb4e5d68d016642b931f Signed-off-by: Sangyoon Jang --- src/lib/wgt_archive_info.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/wgt_archive_info.cc b/src/lib/wgt_archive_info.cc index eb508e1..205ba5f 100644 --- a/src/lib/wgt_archive_info.cc +++ b/src/lib/wgt_archive_info.cc @@ -164,7 +164,7 @@ std::string GetIconInfo(const wgt::parse::WidgetConfigParser& parser) { auto icons_info = std::static_pointer_cast( parser.GetManifestData(wgt::parse::ApplicationIconsInfo::Key())); - if (!icons_info) + if (!icons_info || icons_info->icons().empty()) return {}; return std::string(icons_info->icons().front().path()); -- 2.7.4 From fef5e9e1ee8396fb3413d4cc2523c202dfe61f43 Mon Sep 17 00:00:00 2001 From: Junghyun Yeon Date: Mon, 22 May 2017 10:43:28 +0900 Subject: [PATCH 10/16] Add update step of directories - shared/data directory of package should be created/removed when updating hybrid pkg Change-Id: Ib3f7bd0091f79d42472cc505c5bcf7ad96f69875 Signed-off-by: Junghyun Yeon --- src/hybrid/hybrid_installer.cc | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/hybrid/hybrid_installer.cc b/src/hybrid/hybrid_installer.cc index ba50202..28ef97c 100644 --- a/src/hybrid/hybrid_installer.cc +++ b/src/hybrid/hybrid_installer.cc @@ -42,6 +42,8 @@ #include #include #include +#include +#include #include #include #include @@ -185,6 +187,7 @@ HybridInstaller::HybridInstaller(common_installer::PkgMgrPtr pkgmgr) AddStep(true); AddStep(); AddStep(); + AddStep(); AddStep(); AddStep(); AddStep(); @@ -201,6 +204,7 @@ HybridInstaller::HybridInstaller(common_installer::PkgMgrPtr pkgmgr) AddStep(); AddStep( ci::Plugin::ActionType::Upgrade); + AddStep(); AddStep(); AddStep(); break; @@ -268,6 +272,7 @@ HybridInstaller::HybridInstaller(common_installer::PkgMgrPtr pkgmgr) AddStep(true); AddStep(); AddStep(); + AddStep(); AddStep(); AddStep(); AddStep(); @@ -284,6 +289,7 @@ HybridInstaller::HybridInstaller(common_installer::PkgMgrPtr pkgmgr) AddStep(); AddStep( ci::Plugin::ActionType::Upgrade); + AddStep(); AddStep(); AddStep(); break; @@ -384,6 +390,7 @@ HybridInstaller::HybridInstaller(common_installer::PkgMgrPtr pkgmgr) AddStep(); AddStep(); AddStep(); + AddStep(); AddStep(); AddStep(); AddStep(); @@ -399,6 +406,7 @@ HybridInstaller::HybridInstaller(common_installer::PkgMgrPtr pkgmgr) AddStep(); AddStep( ci::Plugin::ActionType::Upgrade); + AddStep(); AddStep(true); AddStep(); break; @@ -463,6 +471,7 @@ HybridInstaller::HybridInstaller(common_installer::PkgMgrPtr pkgmgr) AddStep(); AddStep( ci::Plugin::ActionType::Upgrade); + AddStep(); AddStep(); AddStep(); break; @@ -507,6 +516,7 @@ HybridInstaller::HybridInstaller(common_installer::PkgMgrPtr pkgmgr) AddStep(); AddStep( ci::Plugin::ActionType::Upgrade); + AddStep(); AddStep(); break; } -- 2.7.4 From 88be41a3b7315837293bbf677f367000bade3cca Mon Sep 17 00:00:00 2001 From: Junghyun Yeon Date: Thu, 1 Jun 2017 09:47:27 +0900 Subject: [PATCH 11/16] Release version 0.4.3 Changes: - Fix crash when parsing icon info from wgt archive - Add update step of directories Change-Id: Id00bf427ae551510d7176b1c75f3ba8cf1f46019 Signed-off-by: Junghyun Yeon --- packaging/wgt-backend.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/wgt-backend.spec b/packaging/wgt-backend.spec index b80b728..c674ac2 100644 --- a/packaging/wgt-backend.spec +++ b/packaging/wgt-backend.spec @@ -1,6 +1,6 @@ Name: wgt-backend Summary: Application installer backend for WGT -Version: 0.4.2 +Version: 0.4.3 Release: 1 Group: Application Framework/Package Management License: Apache-2.0 -- 2.7.4 From 128d8beb7b2ae2b32394d8ec62f7f8115c5bce6f Mon Sep 17 00:00:00 2001 From: Junghyun Yeon Date: Thu, 1 Jun 2017 15:18:01 +0900 Subject: [PATCH 12/16] Supress build warnings - Supress "unused parameter" build warnings Change-Id: Ic27d2298556ccbce75fc6a6fe4f06c1f3a544a8d Signed-off-by: Junghyun Yeon --- src/unit_tests/smoke_utils.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/unit_tests/smoke_utils.cc b/src/unit_tests/smoke_utils.cc index ec50e82..3721b48 100644 --- a/src/unit_tests/smoke_utils.cc +++ b/src/unit_tests/smoke_utils.cc @@ -149,7 +149,7 @@ bool DeleteUser(const char *user_name, bool rem_home_dir) { bool AddTestUser(const char *user_name) { std::cout << "Adding test user: " << user_name << std::endl; - bool ret = AddUser(user_name); + AddUser(user_name); if (boost::optional uid = ci::GetUidByUserName(user_name)) { kTestUserId = *uid; kTestUserIdStr = std::to_string(kTestUserId); @@ -170,7 +170,7 @@ bool DeleteTestUser(const char *user_name) { uid_t test_uid; if (boost::optional uid = ci::GetUidByUserName(user_name)) test_uid = *uid; - bool ret = DeleteUser(user_name, true); + DeleteUser(user_name, true); if (!ci::GetUidByUserName(user_name)) { std::cout << "User deleted properly: user_name=" << user_name << " uid=" << test_uid << std::endl; -- 2.7.4 From 3a9647cc8e8e639dd2dc52ed3e8fd4b1e4979299 Mon Sep 17 00:00:00 2001 From: jongmyeongko Date: Wed, 24 May 2017 21:35:05 +0900 Subject: [PATCH 13/16] Fix logic of 'update' attribute Requires and Refer to: https://review.tizen.org/gerrit/#/c/130948/ Change-Id: I408ec32d9cabd161217e4a462188c27e6366d712 Signed-off-by: jongmyeongko --- src/wgt/step/configuration/step_parse.cc | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/wgt/step/configuration/step_parse.cc b/src/wgt/step/configuration/step_parse.cc index 01ae9bc..6157663 100644 --- a/src/wgt/step/configuration/step_parse.cc +++ b/src/wgt/step/configuration/step_parse.cc @@ -275,12 +275,14 @@ bool StepParse::FillWidgetInfo(manifest_x* manifest) { // set update true if package is updated preload package ci::RequestType req_type = context_->request_type.get(); - if (req_type == ci::RequestType::ReadonlyUpdateInstall) + if (ci::QueryIsUpdatedPackage(context_->pkgid.get(), context_->uid.get())) manifest->update = strdup("true"); - else if (req_type == ci::RequestType::ReadonlyUpdateUninstall) - manifest->update = strdup("false"); - else if (ci::QueryIsUpdatedReadonlyPackage(context_->pkgid.get(), - context_->uid.get())) + else if (ci::QueryIsPreloadPackage(context_->pkgid.get(), + context_->uid.get()) && + (req_type == ci::RequestType::Update || + req_type == ci::RequestType::Delta || + req_type == ci::RequestType::MountUpdate || + req_type == ci::RequestType::ReadonlyUpdateInstall)) manifest->update = strdup("true"); else manifest->update = strdup("false"); -- 2.7.4 From ea510377447fc22afb1a7106ae566907ff7a1112 Mon Sep 17 00:00:00 2001 From: Piotr Ganicz Date: Fri, 2 Jun 2017 17:05:13 +0200 Subject: [PATCH 14/16] Fix for ManifestTests Both properties in config are mandatory, regarding the documentation. So it is intuitive that te parsing process will fail in case of lack of such properies. Change-Id: I2f89a3aaa2098f942fb53002fb64fab54cb8c936 --- src/unit_tests/manifest_test.cc | 25 ++----------------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/src/unit_tests/manifest_test.cc b/src/unit_tests/manifest_test.cc index 52f9a81..009cf44 100644 --- a/src/unit_tests/manifest_test.cc +++ b/src/unit_tests/manifest_test.cc @@ -528,18 +528,7 @@ TEST_F(ManifestTest, MetadataElement_MissingValue) { TEST_F(ManifestTest, MetadataElement_MissingKey) { StepParseRunner runner(GetMyName()); - ASSERT_TRUE(runner.Run()); - manifest_x* m = runner.GetManifest(); - ASSERT_NE(m, nullptr); - auto apps = GListRange(m->application); - application_x* app = *apps.begin(); - - std::map meta_data_map; - for (metadata_x* meta_data : GListRange(app->metadata)) { - if (meta_data->key && meta_data->value) - meta_data_map[meta_data->key] = meta_data->value; - } - ASSERT_EQ(meta_data_map.size(), 0); + ASSERT_FALSE(runner.Run()); } TEST_F(ManifestTest, CategoryElement_Valid) { @@ -561,17 +550,7 @@ TEST_F(ManifestTest, CategoryElement_Valid) { TEST_F(ManifestTest, CategoryElement_MissingName) { StepParseRunner runner(GetMyName()); - ASSERT_TRUE(runner.Run()); - manifest_x* m = runner.GetManifest(); - ASSERT_NE(m, nullptr); - auto apps = GListRange(m->application); - application_x* app = *apps.begin(); - - std::vector categories; - for (const char* category : GListRange(app->category)) { - categories.push_back(category); - } - ASSERT_TRUE(categories.empty()); + ASSERT_FALSE(runner.Run()); } TEST_F(ManifestTest, CategoryElement_MultipleElements) { -- 2.7.4 From decd7bcdce31132fa2cbad71f98e6da6fec876a9 Mon Sep 17 00:00:00 2001 From: Sangyoon Jang Date: Fri, 9 Jun 2017 11:30:29 +0900 Subject: [PATCH 15/16] Release version 0.4.4 Changes: - Supress build warnings - Fix logic of 'update' attribute - Fix for ManifestTests Change-Id: Ief985c4e3f6e3320e88475697d2db506d55ffe86 Signed-off-by: Sangyoon Jang --- packaging/wgt-backend.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/wgt-backend.spec b/packaging/wgt-backend.spec index c674ac2..09189df 100644 --- a/packaging/wgt-backend.spec +++ b/packaging/wgt-backend.spec @@ -1,6 +1,6 @@ Name: wgt-backend Summary: Application installer backend for WGT -Version: 0.4.3 +Version: 0.4.4 Release: 1 Group: Application Framework/Package Management License: Apache-2.0 -- 2.7.4 From e25408785ad84245a2e9d2eea53b445d900a0090 Mon Sep 17 00:00:00 2001 From: Bartlomiej Kunikowski Date: Wed, 24 May 2017 12:13:30 +0200 Subject: [PATCH 16/16] [SmokeTest] Fixes for smoke tests Add "System" exec label to extensive smoke test. Small fixes for RecoveryMode_ForDelta and MigrateLegacyExternalImageMode. Change-Id: I5e342a9e397e5c0ce72680037b1dcb667828c1e3 --- packaging/wgt-backend-tests.manifest | 1 + src/unit_tests/extensive_smoke_test.cc | 5 ++++- src/unit_tests/smoke_test.cc | 11 ++++++++--- src/unit_tests/smoke_utils.cc | 2 +- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/packaging/wgt-backend-tests.manifest b/packaging/wgt-backend-tests.manifest index 17bba51..8ea34c3 100644 --- a/packaging/wgt-backend-tests.manifest +++ b/packaging/wgt-backend-tests.manifest @@ -5,5 +5,6 @@ + diff --git a/src/unit_tests/extensive_smoke_test.cc b/src/unit_tests/extensive_smoke_test.cc index 043c293..34104de 100644 --- a/src/unit_tests/extensive_smoke_test.cc +++ b/src/unit_tests/extensive_smoke_test.cc @@ -107,12 +107,14 @@ TEST_F(SmokeTest, RecoveryMode_ForDelta) { bf::path path_new = kSmokePackagesDirectory / "RecoveryMode_ForDelta.delta"; std::string pkgid = "smokewgt30"; std::string appid = "smokewgt30.RecoveryModeForDelta"; - bf::path recovery_file = FindRecoveryFile(); RemoveAllRecoveryFiles(); + ASSERT_EQ(Install(path_old, PackageType::WGT), ci::AppInstaller::Result::OK); + AddDataFiles(pkgid, kTestUserId); std::vector args = {"", "-i", path_new.string(), "-u", kTestUserIdStr.c_str()}; CrashAfterEachStep(args, [=](int step) -> bool { if (step >= 1) { + bf::path recovery_file = FindRecoveryFile(); EXTENDED_ASSERT_FALSE(recovery_file.empty()); EXTENDED_ASSERT_EQ(Recover(recovery_file, PackageType::WGT), ci::AppInstaller::Result::OK); @@ -120,6 +122,7 @@ TEST_F(SmokeTest, RecoveryMode_ForDelta) { EXTENDED_ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "1\n")); + EXTENDED_ASSERT_TRUE(ValidateDataFiles(pkgid, kTestUserId)); } return true; }); diff --git a/src/unit_tests/smoke_test.cc b/src/unit_tests/smoke_test.cc index 35bdfbc..c3dad25 100644 --- a/src/unit_tests/smoke_test.cc +++ b/src/unit_tests/smoke_test.cc @@ -583,9 +583,14 @@ TEST_F(SmokeTest, MigrateLegacyExternalImageMode) { 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}); + if (kTestUserIdStr == kDefaultUserIdStr || kTestUserId == kGlobalUserUid) { + ASSERT_EQ(MigrateLegacyExternalImage(pkgid, path, legacy_path, + PackageType::WGT), ci::AppInstaller::Result::OK); + ValidateExternalPackage(pkgid, {appid}); + } else { + ASSERT_EQ(MigrateLegacyExternalImage(pkgid, path, legacy_path, + PackageType::WGT), ci::AppInstaller::Result::ERROR); + } } TEST_F(PreloadSmokeTest, InstallationMode_Preload) { diff --git a/src/unit_tests/smoke_utils.cc b/src/unit_tests/smoke_utils.cc index 3721b48..08d617f 100644 --- a/src/unit_tests/smoke_utils.cc +++ b/src/unit_tests/smoke_utils.cc @@ -660,7 +660,7 @@ ci::AppInstaller::Result MigrateLegacyExternalImage(const std::string& pkgid, return ci::AppInstaller::Result::ERROR; } const char* argv[] = {"", "--migrate-extimg", pkgid.c_str(), - "-u", kDefaultUserIdStr.c_str()}; + "-u", kTestUserIdStr.c_str()}; return CallBackend(SIZEOFARRAY(argv), argv, type, mode); } -- 2.7.4