FIND_PACKAGE(GTest REQUIRED)
ADD_SUBDIRECTORY(src)
+ADD_SUBDIRECTORY(test)
This package contains header files of app-installers common library
%package tests
-Summary: Unit tests for app-installers
+Summary: Smoke tests for app-installers
Requires: %{name} = %{version}
%description tests
-Unit tests for al modules of app-installers and common utils for smoke test
+Smoke tests for all modules of app-installers and common utils for smoke test
%prep
%setup -q
%{_datadir}/app-installers-ut/*
%{_libdir}/libtest-assessor-lib.so*
%{_libdir}/libsmoke-utils.so*
-%{_includedir}/app-installers/unit_tests/common/smoke_utils.h
+%{_includedir}/app-installers/smoke_tests/common/smoke_utils.h
%changelog
* Tue Sep 01 2015 Pawel Sikorski <p.sikorski@samsung.com> 1.8-1
ADD_SUBDIRECTORY(pkg_initdb)
ADD_SUBDIRECTORY(pkg_recovery)
ADD_SUBDIRECTORY(pkgdir_tool)
-ADD_SUBDIRECTORY(unit_tests)
+++ /dev/null
-SET(DESTINATION_DIR app-installers-ut)
-
-INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../)
-
-SET(TARGET_ASSESSOR_LIB "test-assessor-lib")
-SET(TARGET_TEST_TAG_PLUGIN "test-tag-plugin")
-SET(TARGET_TEST_CATEGORY_PLUGIN "test-category-plugin")
-SET(TARGET_TEST_METADATA_PLUGIN "test-metadata-plugin")
-SET(TARGET_TEST_TAG_FAIL_PLUGIN "test-tag-fail-plugin")
-SET(TARGET_TEST_CATEGORY_FAIL_PLUGIN "test-category-fail-plugin")
-SET(TARGET_TEST_METADATA_FAIL_PLUGIN "test-metadata-fail-plugin")
-
-SET(TARGET_PLUGINS_TEST "plugins_unittest")
-SET(TARGET_SIGNATURE_TEST "signature_unittest")
-
-# Executables
-ADD_EXECUTABLE(${TARGET_SIGNATURE_TEST}
- signature_unittest.cc
-)
-
-ADD_EXECUTABLE(${TARGET_PLUGINS_TEST}
- plugins_unittest.cc
-)
-
-INSTALL(DIRECTORY test_samples/ DESTINATION ${SHAREDIR}/${DESTINATION_DIR}/test_samples)
-
-APPLY_PKG_CONFIG(${TARGET_SIGNATURE_TEST} PUBLIC
- Boost
- GTEST
-)
-
-APPLY_PKG_CONFIG(plugins_unittest PUBLIC
- Boost
- GTEST
-)
-
-# FindGTest module do not sets all needed libraries in GTEST_LIBRARIES and
-# GTest main libraries is still missing, so additional linking of
-# GTEST_MAIN_LIBRARIES is needed.
-TARGET_LINK_LIBRARIES(${TARGET_SIGNATURE_TEST} PUBLIC
- ${TARGET_LIBNAME_COMMON}
- ${GTEST_MAIN_LIBRARIES}
- pthread
-)
-TARGET_LINK_LIBRARIES(${TARGET_PLUGINS_TEST} PUBLIC
- ${TARGET_LIBNAME_COMMON}
- ${TPK_MANIFEST_HANDLERS_DEPS}
- ${GTEST_MAIN_LIBRARIES}
- ${TARGET_ASSESSOR_LIB}
- pthread
-)
-
-INSTALL(TARGETS ${TARGET_SIGNATURE_TEST} DESTINATION ${BINDIR}/${DESTINATION_DIR})
-INSTALL(TARGETS ${TARGET_PLUGINS_TEST} DESTINATION ${BINDIR}/${DESTINATION_DIR})
-
-ADD_SUBDIRECTORY(libs)
-ADD_SUBDIRECTORY(common)
+++ /dev/null
-ADD_LIBRARY(${TARGET_SMOKE_UTILS} SHARED
- smoke_utils.cc
-)
-
-APPLY_PKG_CONFIG(${TARGET_SMOKE_UTILS} PUBLIC
- Boost
- GTEST
- GUM_DEPS
-)
-
-TARGET_LINK_LIBRARIES(${TARGET_SMOKE_UTILS} PRIVATE
- ${TARGET_LIBNAME_COMMON}
-)
-
-INSTALL(TARGETS ${TARGET_SMOKE_UTILS} DESTINATION ${LIB_INSTALL_DIR})
-INSTALL(FILES smoke_utils.h DESTINATION ${INCLUDEDIR}/app-installers/unit_tests/common/)
+++ /dev/null
-// 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 "unit_tests/common/smoke_utils.h"
-
-#include <gum/gum-user.h>
-#include <gum/gum-user-service.h>
-#include <gum/common/gum-user-types.h>
-#include <manifest_parser/utils/version_number.h>
-#include <sys/smack.h>
-#include <vconf.h>
-#include <vconf-internal-keys.h>
-
-#include <boost/filesystem/path.hpp>
-#include <gtest/gtest.h>
-
-#include <common/installer/app_installer.h>
-#include <common/utils/paths.h>
-#include <common/pkgmgr_interface.h>
-#include <common/utils/pkgmgr_query.h>
-#include <common/tzip_interface.h>
-
-#include <list>
-#include <memory>
-#include <string>
-#include <vector>
-
-namespace bf = boost::filesystem;
-namespace bs = boost::system;
-namespace ci = common_installer;
-namespace bo = boost::program_options;
-
-namespace {
-
-const uid_t kDefaultUserUid = tzplatform_getuid(TZ_SYS_DEFAULT_USER);
-const gid_t kDefaultUserGid = tzplatform_getgid(TZ_SYS_DEFAULT_USER);
-const char kNormalUserName[] = "smokeuser";
-const char kSystemShareGroupName[] = "system_share";
-const char kMigrateTestDBName[] = "app2sd_migrate.db";
-// common entries
-const std::vector<std::string> kDBEntries = {
- {".pkgmgr_parser.db"},
- {".pkgmgr_parser.db-journal"},
- {".pkgmgr_cert.db"},
- {".pkgmgr_cert.db-journal"},
- {".app2sd.db"},
- {".app2sd.db-journal"},
-};
-// globaluser entries
-const char kGlobalManifestDir[] = "/opt/share/packages";
-const char kSkelDir[] = "/etc/skel/apps_rw";
-const char kPreloadApps[] = "/usr/apps";
-const char kPreloadManifestDir[] = "/usr/share/packages";
-const char kPreloadIcons[] = "/usr/share/icons";
-const char kData[] = "data";
-const char kShared[] = ".shared";
-const char kSharedTmp[] = ".shared_tmp";
-
-enum RWDirectory {
- DATA,
- CACHE,
- SHARED_CACHE,
- SHARED_DATA,
- SHARED_TRUSTED
-};
-
-const char* rwDirectories[] = {
- "data",
- "cache",
- "shared/cache",
- "shared/data",
- "shared/trusted",
-};
-
-} // namespace
-
-namespace smoke_test {
-
-const char kLegacyExtImageDir[] = "legacy_extimage_dir";
-const std::string& kDefaultUserIdStr = std::to_string(kDefaultUserUid);
-const uid_t kGlobalUserUid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
-const uid_t kGlobalUserGid = tzplatform_getgid(TZ_SYS_GLOBALAPP_USER);
-extern const bf::path kSdkDirectory = "/home/owner/share/tmp/sdk_tools";
-
-ci::RequestMode ParseRequestMode(int argc, char** argv) {
- bo::options_description desc("Available options");
- desc.add_options()
- ("request-mode", bo::value<std::string>(), "set request mode")
- ("global-request,g", "set request mode to global")
- ("user-request,u", "set request mode to user");
-
- bo::variables_map vm;
- bo::store(bo::command_line_parser(argc, argv).
- options(desc).allow_unregistered().run(), vm);
- bo::notify(vm);
-
- if (vm.count("global-request")) {
- std::cout << "Request mode was set to global." << std::endl;
- return ci::RequestMode::GLOBAL;
- }
- if (vm.count("user-request")) {
- std::cout << "Request mode was set to user." << std::endl;
- return ci::RequestMode::USER;
- }
- if (vm.count("request-mode")) {
- if (vm["request-mode"].as<std::string>() == "global") {
- std::cout << "Request mode was set to global." << std::endl;
- return ci::RequestMode::GLOBAL;
- }
- if (vm["request-mode"].as<std::string>() == "user") {
- std::cout << "Request mode was set to user." << std::endl;
- return ci::RequestMode::USER;
- }
- std::cout << "Cannot set request mode to "
- << vm["request-mode"].as<std::string>() << std::endl;
- }
- std::cout << "Request mode was set to global." << std::endl;
- return ci::RequestMode::GLOBAL;
-}
-
-static 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;
-}
-
-static 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(User* test_user) {
- std::cout << "Adding test user: " << kNormalUserName << std::endl;
- AddUser(kNormalUserName);
- if (boost::optional<uid_t> uid = ci::GetUidByUserName(kNormalUserName)) {
- test_user->uid = *uid;
- std::cout << "User created properly: uid=" << *uid;
- if (boost::optional<gid_t> gid = ci::GetGidByUid(*uid)) {
- test_user->gid = *gid;
- std::cout << " gid=" << *gid;
- }
- std::cout << std::endl;
- return true;
- }
- LOG(ERROR) << "Adding test user failed";
- return false;
-}
-
-bool DeleteTestUser() {
- std::cout << "Deleting test user: " << kNormalUserName << std::endl;
- uid_t test_uid;
- if (boost::optional<uid_t> uid = ci::GetUidByUserName(kNormalUserName))
- test_uid = *uid;
- else
- return false;
- DeleteUser(kNormalUserName, true);
- if (!ci::GetUidByUserName(kNormalUserName)) {
- std::cout << "User deleted properly: user_name=" << kNormalUserName
- << " uid=" << test_uid << std::endl;
- return true;
- }
- LOG(ERROR) << "Deleting test user failed";
- return false;
-}
-
-bool TouchFile(const bf::path& path) {
- FILE* f = fopen(path.c_str(), "w+");
- if (!f)
- return false;
- fclose(f);
- return true;
-}
-
-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 RemoveAllRecoveryFiles(const std::string& prefix, uid_t uid) {
- bf::path root_path = ci::GetRootAppPath(false, uid);
- 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(prefix) != std::string::npos) {
- bs::error_code error;
- bf::remove(dir_entry.path(), error);
- if (error)
- LOG(ERROR) << "Failed to remove " << dir_entry.path()
- << ": " << error.message();
- }
- }
- }
-}
-
-bf::path FindRecoveryFile(const std::string& prefix, uid_t uid) {
- bf::path root_path = ci::GetRootAppPath(false, uid);
- 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(prefix) != std::string::npos) {
- return dir_entry.path();
- }
- }
- }
- return {};
-}
-
-std::unique_ptr<ci::recovery::RecoveryFile> GetRecoverFileInfo(
- const bf::path& recovery_file_path) {
- return ci::recovery::RecoveryFile::OpenRecoveryFile(recovery_file_path);
-}
-
-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,
- const TestParameters& params) {
- bf::path file_path = ci::GetRootAppPath(params.is_readonly,
- params.test_user.uid);
- 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<char, 200> buffer;
- while (fgets(buffer.data(), buffer.size(), handle)) {
- content += buffer.data();
- }
- fclose(handle);
- return content == expected;
-}
-
-static 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];
-
- 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<gid_t> system_share =
- ci::GetGidByGroupName(kSystemShareGroupName);
- 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);
- EXTENDED_ASSERT_EQ(uid, stats.st_uid);
- EXTENDED_ASSERT_EQ(*system_share, stats.st_gid);
- }
-
- stat(cache_path.c_str(), &stats);
- EXTENDED_ASSERT_EQ(uid, stats.st_uid);
- EXTENDED_ASSERT_EQ(*system_share, stats.st_gid);
- return true;
-}
-
-static bool ValidatePackageFS(const std::string& pkgid, const Apps& apps,
- const TestParameters& params) {
- bf::path root_path = ci::GetRootAppPath(params.is_readonly,
- params.test_user.uid);
- bf::path package_path = root_path / pkgid;
- bf::path shared_path = package_path / "shared";
- 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(params.test_user.uid,
- params.is_readonly)) / (pkgid + ".xml");
- EXTENDED_ASSERT_TRUE(bf::exists(manifest_path));
-
- for (auto& app : apps) {
- const std::string &exec = app.second;
- bf::path binary_path = package_path / "bin" / exec;
- EXTENDED_ASSERT_TRUE(bf::exists(binary_path));
- }
-
- if (params.pkg_type == PackageType::WGT ||
- params.pkg_type == PackageType::HYBRID) {
- bf::path widget_root_path = package_path / "res" / "wgt";
- bf::path config_path = widget_root_path / "config.xml";
- EXTENDED_ASSERT_TRUE(bf::exists(widget_root_path));
- EXTENDED_ASSERT_TRUE(bf::exists(config_path));
-
- bf::path private_tmp_path = package_path / "tmp";
- 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);
- 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) {
- 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);
- EXTENDED_ASSERT_EQ(params.test_user.uid, stats.st_uid);
- EXTENDED_ASSERT_EQ(params.test_user.gid, stats.st_gid);
- }
- return true;
-}
-
-bool ValidatePackage(const std::string& pkgid, const Apps& apps,
- const TestParameters& params) {
- ci::PkgQueryInterface pkg_query(pkgid, params.test_user.uid, true);
- EXTENDED_ASSERT_TRUE(pkg_query.IsPackageInstalled(
- ci::GetRequestMode(params.test_user.uid)));
- EXTENDED_ASSERT_TRUE(ValidatePackageFS(pkgid, apps, params));
- if (params.test_user.uid == kGlobalUserUid) {
- ci::UserList list = ci::GetUserList();
- for (auto& l : list)
- EXTENDED_ASSERT_TRUE(ValidatePackageRWFS(pkgid, std::get<0>(l)));
- } else {
- EXTENDED_ASSERT_TRUE(ValidatePackageRWFS(pkgid, params.test_user.uid));
- }
- return true;
-}
-
-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));
- 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);
- EXTENDED_ASSERT_TRUE(bf::exists(pkg_path / "data" / "file1.txt"));
- EXTENDED_ASSERT_TRUE(bf::exists(pkg_path / "data" / "file2.txt"));
- }
- return true;
-}
-
-static bool ValidateExternalPackageFS(const std::string& pkgid,
- const Apps& apps, const TestParameters& params) {
- EXTENDED_ASSERT_EQ(app2ext_usr_enable_external_pkg(pkgid.c_str(),
- params.test_user.uid), 0);
- bf::path root_path = ci::GetRootAppPath(false, params.test_user.uid);
- if (params.pkg_type == PackageType::TPK) {
- EXTENDED_ASSERT_TRUE(bf::exists(root_path / pkgid / ".mmc" / "bin"));
- EXTENDED_ASSERT_TRUE(bf::exists(root_path / pkgid / ".mmc" / "lib"));
- }
- EXTENDED_ASSERT_TRUE(bf::exists(root_path / pkgid / ".mmc" / "res"));
- EXTENDED_ASSERT_TRUE(ValidatePackageFS(pkgid, apps, params));
- EXTENDED_ASSERT_EQ(app2ext_usr_disable_external_pkg(pkgid.c_str(),
- params.test_user.uid), 0);
- return true;
-}
-
-bool ValidateExternalPackage(const std::string& pkgid, const Apps& apps,
- const TestParameters& params) {
- ci::PkgQueryInterface pkg_query(pkgid, params.test_user.uid, true);
- std::string storage = pkg_query.StorageForPkgId();
- bf::path ext_mount_path = ci::GetExternalCardPath();
- if (bf::is_empty(ext_mount_path)) {
- LOG(INFO) << "Sdcard not exists!";
- EXTENDED_ASSERT_EQ(storage, "installed_internal");
- } else {
- EXTENDED_ASSERT_EQ(storage, "installed_external");
- }
- EXTENDED_ASSERT_TRUE(ValidateExternalPackageFS(pkgid, apps, params));
- return true;
-}
-
-bool ValidateExtendedPackage(const std::string& pkgid, const Apps& apps,
- const TestParameters& params) {
- ci::PkgQueryInterface pkg_query(pkgid, params.test_user.uid, true);
- std::string storage = pkg_query.StorageForPkgId();
- bf::path extended_path =
- bf::path(ci::GetExtendedRootAppPath(params.test_user.uid)) / pkgid;
- if (!bf::exists(extended_path)) {
- LOG(INFO) << "Extended storage not exists!";
- EXTENDED_ASSERT_EQ(storage, "installed_internal");
- } else {
- EXTENDED_ASSERT_EQ(storage, "installed_extended");
- }
- EXTENDED_ASSERT_TRUE(ValidatePackage(pkgid, apps, params));
- return true;
-}
-
-static bool PackageCheckCleanup(const std::string& pkgid,
- const TestParameters& params) {
- bf::path root_path = ci::GetRootAppPath(params.is_readonly,
- params.test_user.uid);
- bf::path package_path = root_path / pkgid;
- EXTENDED_ASSERT_FALSE(bf::exists(package_path));
-
- bf::path manifest_path = bf::path(getUserManifestPath(params.test_user.uid,
- params.is_readonly)) / (pkgid + ".xml");
- EXTENDED_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);
- EXTENDED_ASSERT_FALSE(bf::exists(package_backup));
- EXTENDED_ASSERT_FALSE(bf::exists(manifest_backup));
- return true;
-}
-
-bool CheckPackageNonExistance(const std::string& pkgid,
- const TestParameters& params) {
- ci::PkgQueryInterface pkg_query(pkgid, params.test_user.uid, true);
- EXTENDED_ASSERT_FALSE(pkg_query.IsPackageInstalled(
- ci::GetRequestMode(params.test_user.uid)));
- EXTENDED_ASSERT_TRUE(PackageCheckCleanup(pkgid, params));
- if (params.test_user.uid == kGlobalUserUid) {
- bf::path skel_path(kSkelDir);
- EXTENDED_ASSERT_FALSE(bf::exists(skel_path / pkgid));
- EXTENDED_ASSERT_FALSE(bf::exists(skel_path / kShared / pkgid));
- EXTENDED_ASSERT_FALSE(bf::exists(skel_path / kSharedTmp / pkgid));
- ci::UserList list = ci::GetUserList();
- for (auto& l : list) {
- bf::path root_path = ci::GetRootAppPath(false, std::get<0>(l));
- EXTENDED_ASSERT_FALSE(bf::exists(root_path / kShared / pkgid));
- EXTENDED_ASSERT_FALSE(bf::exists(root_path / kSharedTmp / pkgid));
- bf::path package_path = root_path / pkgid;
- EXTENDED_ASSERT_FALSE(bf::exists(package_path));
- }
- }
- return true;
-}
-
-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;
-}
-
-bool CheckAvailableExtendedPath() {
- bf::path extended_path = bf::path(tzplatform_getenv(TZ_SYS_EXTENDEDSD));
- LOG(DEBUG) << "extended_path :" << extended_path;
- // TODO(jeremy.jang): It should be checked by libstorage API.
- if (!bf::exists(extended_path)) {
- LOG(ERROR) << "Extended storage not exists!";
- return false;
- }
- return true;
-}
-
-bool CheckPackageReadonlyNonExistance(const std::string& pkgid,
- const TestParameters& params) {
- ci::PkgQueryInterface pkg_query(pkgid, params.test_user.uid, true);
- EXTENDED_ASSERT_FALSE(pkg_query.IsPackageInstalled(
- ci::GetRequestMode(params.test_user.uid)));
- EXTENDED_ASSERT_TRUE(PackageCheckCleanup(pkgid, params));
- return true;
-}
-
-static bool CheckSharedDataExistanceForPath(const bf::path& apps_rw,
- const std::string& pkgid) {
- bf::path shared_data_path = apps_rw / pkgid / rwDirectories[SHARED_DATA];
- bf::path shared = apps_rw / kShared / pkgid / kData;
- bf::path shared_tmp = apps_rw / kSharedTmp / pkgid;
- EXTENDED_ASSERT_TRUE(bf::exists(shared_data_path));
- EXTENDED_ASSERT_TRUE(bf::exists(shared));
- EXTENDED_ASSERT_TRUE(bf::exists(shared_tmp));
- return true;
-}
-
-static bool CheckSharedDataPermissions(const bf::path& apps_rw,
- const std::string& pkgid, uid_t uid) {
- bf::path shared_data_path = apps_rw / pkgid / rwDirectories[SHARED_DATA];
- bf::path shared = apps_rw / kShared / pkgid / kData;
- bf::path shared_tmp = apps_rw / kSharedTmp / pkgid;
- // gid of RW dirs should be system_share
- boost::optional<gid_t> system_share =
- ci::GetGidByGroupName(kSystemShareGroupName);
- struct stat stats;
- stat(shared_data_path.c_str(), &stats);
- EXTENDED_ASSERT_EQ(uid, stats.st_uid);
- EXTENDED_ASSERT_EQ(*system_share, stats.st_gid);
- stat(shared.c_str(), &stats);
- EXTENDED_ASSERT_EQ(uid, stats.st_uid);
- EXTENDED_ASSERT_EQ(*system_share, stats.st_gid);
- stat(shared_tmp.c_str(), &stats);
- EXTENDED_ASSERT_EQ(uid, stats.st_uid);
- EXTENDED_ASSERT_EQ(kDefaultUserGid, stats.st_gid);
- return true;
-}
-
-bool CheckSharedDataExistance(const std::string& pkgid,
- const TestParameters& params) {
- if (params.test_user.uid == kGlobalUserUid) {
- bf::path skel_path(kSkelDir);
- EXTENDED_ASSERT_TRUE(CheckSharedDataExistanceForPath(kSkelDir, pkgid));
- ci::UserList list = ci::GetUserList();
- for (auto& l : list) {
- uid_t uid = std::get<0>(l);
- bf::path apps_rw = ci::GetRootAppPath(false, uid);
- EXTENDED_ASSERT_TRUE(CheckSharedDataExistanceForPath(apps_rw, pkgid));
- EXTENDED_ASSERT_TRUE(CheckSharedDataPermissions(apps_rw, pkgid, uid));
- }
- } else {
- bf::path apps_rw = ci::GetRootAppPath(false, params.test_user.uid);
- EXTENDED_ASSERT_TRUE(CheckSharedDataExistanceForPath(apps_rw, pkgid));
- EXTENDED_ASSERT_TRUE(
- CheckSharedDataPermissions(apps_rw, pkgid, params.test_user.uid));
- }
- return true;
-}
-
-static bool CheckSharedDataNonExistanceForPath(const bf::path& apps_rw,
- const std::string pkgid) {
- bf::path shared_data_path = apps_rw / pkgid / rwDirectories[SHARED_DATA];
- bf::path shared = apps_rw / kShared / pkgid / kData;
- bf::path shared_tmp = apps_rw / kSharedTmp / pkgid;
- EXTENDED_ASSERT_FALSE(bf::exists(shared_data_path));
- EXTENDED_ASSERT_FALSE(bf::exists(shared));
- EXTENDED_ASSERT_FALSE(bf::exists(shared_tmp));
- return true;
-}
-
-bool CheckSharedDataNonExistance(const std::string& pkgid,
- const TestParameters& params) {
- if (params.test_user.uid == kGlobalUserUid) {
- bf::path skel_path(kSkelDir);
- EXTENDED_ASSERT_TRUE(
- CheckSharedDataNonExistanceForPath(skel_path, pkgid));
-
- ci::UserList list = ci::GetUserList();
- for (auto& l : list) {
- uid_t uid = std::get<0>(l);
- bf::path apps_rw = ci::GetRootAppPath(false, uid);
- EXTENDED_ASSERT_TRUE(CheckSharedDataNonExistanceForPath(apps_rw, pkgid));
- }
- } else {
- bf::path apps_rw = ci::GetRootAppPath(false, params.test_user.uid);
- EXTENDED_ASSERT_TRUE(CheckSharedDataNonExistanceForPath(apps_rw, pkgid));
- }
- return true;
-}
-
-void BackendInterface::TestRollbackAfterEachStep(int argc, const char* argv[],
- std::function<bool()> validator) const {
- TestPkgmgrInstaller pkgmgr_installer;
- std::unique_ptr<ci::AppQueryInterface> query_interface =
- CreateQueryInterface();
- auto pkgmgr =
- ci::PkgMgrInterface::Create(argc, const_cast<char**>(argv),
- &pkgmgr_installer,
- query_interface.get());
- if (!pkgmgr) {
- LOG(ERROR) << "Failed to initialize pkgmgr interface";
- return;
- }
- AppInstallerPtr backend;
- unsigned int insert_idx = 0;
- do {
- backend = CreateFailExpectedInstaller(pkgmgr, insert_idx);
- LOG(DEBUG) << "StepFail is inserted at: " << insert_idx;
- ASSERT_EQ(ci::AppInstaller::Result::ERROR, backend->Run());
- if (!validator())
- break;
- insert_idx++;
- } while (insert_idx < backend->StepCount());
- ASSERT_EQ(insert_idx, backend->StepCount());
-}
-
-void BackendInterface::CrashAfterEachStep(std::vector<std::string>* args,
- std::function<bool(int iter)> validator, PackageType type) const {
- std::unique_ptr<const char*[]> argv(new const char*[args->size()]);
- for (size_t i = 0; i < args->size(); ++i) {
- argv[i] = args->at(i).c_str();
- }
- TestPkgmgrInstaller pkgmgr_installer;
- auto query_interface = CreateQueryInterface();
- auto pkgmgr =
- ci::PkgMgrInterface::Create(args->size(), const_cast<char**>(argv.get()),
- &pkgmgr_installer,
- query_interface.get());
- if (!pkgmgr) {
- LOG(ERROR) << "Failed to initialize pkgmgr interface";
- return;
- }
- auto backend = CreateFailExpectedInstaller(pkgmgr, 0);
- ASSERT_EQ(backend->Run(), ci::AppInstaller::Result::ERROR);
- int stepCount = backend->StepCount();
-
- args->push_back("-idx");
- args->push_back(std::to_string(stepCount));
- int i;
- std::string prefix = (type == PackageType::TPK) ? "tpk" : "wgt";
- for (i = 0; i < stepCount; i++) {
- ci::Subprocess backend_crash(
- "/usr/bin/" + prefix + "-installer-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);
-
- args->push_back("-type_clean");
- for (i = stepCount - 1; i >= 2; i--) {
- ci::Subprocess backend_crash(
- "/usr/bin/" + prefix + "-installer-ut/smoke-test-helper");
- auto it = args->end();
- it -= 2;
- *it = std::to_string(i);
- backend_crash.Run(*args);
- ASSERT_NE(backend_crash.Wait(), 0);
- if (!validator(i))
- break;
- }
- ASSERT_EQ(i , 1);
-}
-
-BackendInterface::CommandResult BackendInterface::RunInstallersWithPkgmgr(
- ci::PkgMgrPtr pkgmgr) const {
- std::list<AppInstallerPtr> installers;
- for (int i = 0; i < pkgmgr->GetRequestInfoCount(); i++) {
- AppInstallerPtr installer;
- if (mode_ == RequestResult::FAIL && i == pkgmgr->GetRequestInfoCount() - 1)
- installer = factory_->CreateFailExpectedInstaller(i, pkgmgr);
- else
- installer = factory_->CreateInstaller(i, pkgmgr);
- if (!installer)
- LOG(ERROR) << "Failed to create installer";
- else
- installers.emplace_back(std::move(installer));
- }
-
- // FIXME: I think we should not implement this logic here...
- CommandResult result = CommandResult::OK;
- std::list<AppInstallerPtr>::iterator it(installers.begin());
- for (; it != installers.end(); ++it) {
- result = (*it)->Process();
- if (result != CommandResult::OK)
- break;
- }
- if (it != installers.end() && result == CommandResult::ERROR) {
- do {
- CommandResult ret = (*it)->Undo();
- if (ret != CommandResult::OK && ret != CommandResult::ERROR)
- result = CommandResult::UNDO_ERROR;
- } while (it-- != installers.begin());
- } else {
- --it;
- do {
- if ((*it)->Clean() != CommandResult::OK)
- result = CommandResult::CLEANUP_ERROR;
- } while (it-- != installers.begin());
- }
- return result;
-}
-
-BackendInterface::CommandResult BackendInterface::CallBackendWithRunner(
- int argc, const char* argv[]) const {
- TestPkgmgrInstaller pkgmgr_installer;
- auto pkgmgr = ci::PkgMgrInterface::Create(argc, const_cast<char**>(argv),
- &pkgmgr_installer);
- if (!pkgmgr) {
- LOG(ERROR) << "Failed to initialize pkgmgr interface";
- return BackendInterface::CommandResult::UNKNOWN;
- }
- return RunInstallersWithPkgmgr(pkgmgr);
-}
-
-BackendInterface::CommandResult BackendInterface::Install(
- const std::vector<bf::path>& paths) const {
- std::vector<const char*> argv;
- argv.emplace_back("");
- argv.emplace_back("-i");
- for (const auto& p : paths)
- argv.emplace_back(p.string().c_str());
- return CallBackendWithRunner(argv.size(), argv.data());
-}
-
-BackendInterface::CommandResult BackendInterface::Uninstall(
- const std::vector<std::string>& pkgids) const {
- std::vector<const char*> argv;
- argv.emplace_back("");
- argv.emplace_back("-d");
- for (const auto& p : pkgids)
- argv.emplace_back(p.c_str());
- return CallBackendWithRunner(argv.size(), argv.data());
-}
-
-BackendInterface::CommandResult BackendInterface::InstallSuccess(
- const std::vector<bf::path>& paths) const {
- RequestResult tmp_mode = mode_;
- RequestResult &original_mode = const_cast<RequestResult&>(mode_);
- original_mode = RequestResult::NORMAL;
- if (Install(paths) != BackendInterface::CommandResult::OK) {
- LOG(ERROR) << "Failed to install application. Cannot update";
- return BackendInterface::CommandResult::UNKNOWN;
- }
- original_mode = tmp_mode;
- return BackendInterface::CommandResult::OK;
-}
-
-BackendInterface::CommandResult BackendInterface::RunInstallerWithPkgrmgr(
- ci::PkgMgrPtr pkgmgr) const {
- std::unique_ptr<ci::AppInstaller> installer;
- switch (mode_) {
- case RequestResult::FAIL:
- installer = CreateFailExpectedInstaller(pkgmgr);
- break;
- default:
- installer = CreateInstaller(pkgmgr);
- break;
- }
- return installer->Run();
-}
-
-BackendInterface::CommandResult BackendInterface::CallBackend(int argc,
- const char* argv[]) const {
- TestPkgmgrInstaller pkgmgr_installer;
- auto query_interface = CreateQueryInterface();
- auto pkgmgr = ci::PkgMgrInterface::Create(argc, const_cast<char**>(argv),
- &pkgmgr_installer, query_interface.get());
- if (!pkgmgr) {
- LOG(ERROR) << "Failed to initialize pkgmgr interface";
- return BackendInterface::CommandResult::UNKNOWN;
- }
- return RunInstallerWithPkgrmgr(pkgmgr);
-}
-
-BackendInterface::CommandResult BackendInterface::Install(
- const bf::path& path) const {
- const char* argv[] = {"", "-i", path.c_str(), "-u", uid_str_.c_str()};
- return CallBackend(SIZEOFARRAY(argv), argv);
-}
-
-BackendInterface::CommandResult BackendInterface::InstallPreload(
- const bf::path& path) const {
- const char* argv[] = {"", "-i", path.c_str(), "--preload"};
- return CallBackend(SIZEOFARRAY(argv), argv);
-}
-
-BackendInterface::CommandResult BackendInterface::InstallWithStorage(
- const bf::path& path, StorageType type) const {
- int default_storage = 0;
- int storage = 0;
- switch (type) {
- case StorageType::EXTERNAL:
- storage = 1;
- break;
- case StorageType::EXTENDED:
- storage = 2;
- break;
- default:
- LOG(ERROR) << "Unknown storage type";
- break;
- }
- vconf_get_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT,
- &default_storage);
- vconf_set_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT, storage);
-
- const char* argv[] = {"", "-i", path.c_str(), "-u", uid_str_.c_str()};
- BackendInterface::CommandResult result = CallBackend(SIZEOFARRAY(argv), argv);
-
- vconf_set_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT,
- default_storage);
- return result;
-}
-
-BackendInterface::CommandResult BackendInterface::MigrateLegacyExternalImage(
- const std::string& pkgid,
- const bf::path& path,
- const bf::path& legacy_path) const {
- if (InstallWithStorage(path, StorageType::EXTERNAL) !=
- BackendInterface::CommandResult::OK) {
- LOG(ERROR) << "Failed to install application. Cannot perform Migrate";
- return BackendInterface::CommandResult::ERROR;
- }
-
- bf::path ext_mount_path = ci::GetExternalCardPath();
- if (bf::is_empty(ext_mount_path)) {
- LOG(ERROR) << "Sdcard not exists!";
- return BackendInterface::CommandResult::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 BackendInterface::CommandResult::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 BackendInterface::CommandResult::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 BackendInterface::CommandResult::ERROR;
- }
- bf::remove(app2sd_db_journal, error);
- if (error) {
- LOG(ERROR) << "Failed to remove app2sd journal db";
- return BackendInterface::CommandResult::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 BackendInterface::CommandResult::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 BackendInterface::CommandResult::ERROR;
- }
- const char* argv[] = {"", "--migrate-extimg", pkgid.c_str(),
- "-u", uid_str_.c_str()};
- return CallBackend(SIZEOFARRAY(argv), argv);
-}
-
-BackendInterface::CommandResult BackendInterface::RDSUpdate(
- const bf::path& path,
- const std::string& pkgid) const {
- RequestResult tmp_mode = mode_;
- RequestResult &original_mode = const_cast<RequestResult&>(mode_);
- original_mode = RequestResult::NORMAL;
- if (Install(path) != BackendInterface::CommandResult::OK) {
- LOG(ERROR) << "Failed to install application. Cannot perform RDS";
- return BackendInterface::CommandResult::UNKNOWN;
- }
- const char* argv[] = {"", "-r", pkgid.c_str(), "-u",
- uid_str_.c_str()};
- original_mode = tmp_mode;
- return CallBackend(SIZEOFARRAY(argv), argv);
-}
-
-BackendInterface::CommandResult BackendInterface::EnablePackage(
- const std::string& pkgid) const {
- const char* argv[] = {"", "-A", pkgid.c_str(), "-u", uid_str_.c_str()};
- return CallBackend(SIZEOFARRAY(argv), argv);
-}
-
-BackendInterface::CommandResult BackendInterface::DisablePackage(
- const std::string& pkgid) const {
- const char* argv[] = {"", "-D", pkgid.c_str(), "-u", uid_str_.c_str()};
- return CallBackend(SIZEOFARRAY(argv), argv);
-}
-
-BackendInterface::CommandResult BackendInterface::Recover(
- const bf::path& recovery_file) const {
- const char* argv[] = {"", "-b", recovery_file.c_str(), "-u",
- uid_str_.c_str()};
- return CallBackend(SIZEOFARRAY(argv), argv);
-}
-
-BackendInterface::CommandResult BackendInterface::ManifestDirectInstall(
- const std::string& pkgid) const {
- const char* argv[] = {"", "-y", pkgid.c_str(), "-u", uid_str_.c_str()};
- return CallBackend(SIZEOFARRAY(argv), argv);
-}
-
-BackendInterface::CommandResult BackendInterface::Uninstall(
- const std::string& pkgid) const {
- const char* argv[] = {"", "-d", pkgid.c_str(), "-u", uid_str_.c_str()};
- return CallBackend(SIZEOFARRAY(argv), argv);
-}
-
-BackendInterface::CommandResult BackendInterface::UninstallPreload(
- const std::string& pkgid) const {
- const char* argv[] = {"", "-d", pkgid.c_str(), "--preload",
- "--force-remove"};
- return CallBackend(SIZEOFARRAY(argv), argv);
-}
-
-BackendInterface::CommandResult BackendInterface::InstallSuccess(
- const bf::path& path) const {
- RequestResult tmp_mode = mode_;
- RequestResult &original_mode = const_cast<RequestResult&>(mode_);
- original_mode = RequestResult::NORMAL;
- if (Install(path) != BackendInterface::CommandResult::OK) {
- LOG(ERROR) << "Failed to install application. Cannot update";
- return BackendInterface::CommandResult::UNKNOWN;
- }
- original_mode = tmp_mode;
- return BackendInterface::CommandResult::OK;
-}
-
-BackendInterface::CommandResult BackendInterface::InstallPreloadSuccess(
- const bf::path& path) const {
- RequestResult tmp_mode = mode_;
- RequestResult &original_mode = const_cast<RequestResult&>(mode_);
- original_mode = RequestResult::NORMAL;
- if (InstallPreload(path) != BackendInterface::CommandResult::OK) {
- LOG(ERROR) << "Failed to install application. Cannot update";
- return BackendInterface::CommandResult::UNKNOWN;
- }
- original_mode = tmp_mode;
- return BackendInterface::CommandResult::OK;
-}
-
-BackendInterface::CommandResult BackendInterface::MountInstall(
- const bf::path& path) const {
- const char* argv[] = {"", "-w", path.c_str(), "-u", uid_str_.c_str()};
- return CallBackend(SIZEOFARRAY(argv), argv);
-}
-
-BackendInterface::CommandResult BackendInterface::MountInstallSuccess(
- const bf::path& path) const {
- RequestResult tmp_mode = mode_;
- RequestResult &original_mode = const_cast<RequestResult&>(mode_);
- original_mode = RequestResult::NORMAL;
- if (MountInstall(path) != BackendInterface::CommandResult::OK) {
- LOG(ERROR) << "Failed to mount-install application. Cannot mount-update";
- return BackendInterface::CommandResult::UNKNOWN;
- }
- original_mode = tmp_mode;
- return BackendInterface::CommandResult::OK;
-}
-
-static boost::filesystem::path GetTrashPath(
- const boost::filesystem::path& path) {
- return path.string() + ".trash";
-}
-
-SmokeTestHelperRunner::Result SmokeTestHelperRunner::RunSubprocess(
- std::vector<std::string> args) const {
- args.push_back("-remove_plugin_steps");
- ci::Subprocess backend = CreateSubprocess();
- backend.RunWithArgs(args);
- int status = backend.Wait();
- if (WIFEXITED(status)) {
- if (WEXITSTATUS(status) == 0)
- return SmokeTestHelperRunner::Result::SUCCESS;
- else
- return SmokeTestHelperRunner::Result::FAIL;
- }
- return SmokeTestHelperRunner::Result::UnKnown;
-}
-
-SmokeTestHelperRunner::Result SmokeTestHelperRunner::RunSubprocessAndKill(
- std::vector<std::string> args, useconds_t delay) const {
- args.push_back("-remove_plugin_steps");
- ci::Subprocess backend = CreateSubprocess();
- backend.RunWithArgs(args);
- usleep(delay);
- backend.Kill();
- int status = backend.Wait();
- if (WIFEXITED(status)) {
- if (WEXITSTATUS(status) == 0)
- return SmokeTestHelperRunner::Result::SUCCESS;
- else
- return SmokeTestHelperRunner::Result::FAIL;
- } else {
- if (WTERMSIG(status) == SIGKILL)
- return SmokeTestHelperRunner::Result::KILLED;
- else
- return SmokeTestHelperRunner::Result::UnKnown;
- }
-}
-
-SmokeTestHelperRunner::Result SmokeTestHelperRunner::InstallWithSubprocess(
- const bf::path& path, uid_t uid) const {
- std::vector<std::string> args =
- { "-i", path.string(), "-u", std::to_string(uid) };
- return RunSubprocess(args);
-}
-
-SmokeTestHelperRunner::Result SmokeTestHelperRunner::MountInstallWithSubprocess(
- const bf::path& path, uid_t uid) const {
- std::vector<std::string> args =
- { "-w", path.string(), "-u", std::to_string(uid) };
- return RunSubprocess(args);
-}
-
-SmokeTestHelperRunner::Result SmokeTestHelperRunner::RecoveryWithSubprocess(
- const bf::path& path, uid_t uid) const {
- std::vector<std::string> args =
- { "-b", path.string(), "-u", std::to_string(uid) };
- return RunSubprocess(args);
-}
-
-SmokeTestHelperRunner::Result SmokeTestHelperRunner::UninstallWithSubprocess(
- const std::string& pkgid, uid_t uid) const {
- std::vector<std::string> args = { "-d", pkgid, "-u", std::to_string(uid) };
- return RunSubprocess(args);
-}
-
-SmokeTestHelperRunner::Result
- SmokeTestHelperRunner::InstallWithSubprocessAndKill(
- const bf::path& path, uid_t uid, useconds_t delay) const {
- std::vector<std::string> args =
- { "-i", path.string(), "-u", std::to_string(uid) };
- return RunSubprocessAndKill(args, delay);
-}
-
-SmokeTestHelperRunner::Result
- SmokeTestHelperRunner::MountInstallWithSubprocessAndKill(
- const bf::path& path, uid_t uid, useconds_t delay) const {
- std::vector<std::string> args =
- { "-w", path.string(), "-u", std::to_string(uid) };
- return RunSubprocessAndKill(args, delay);
-}
-
-SmokeTestHelperRunner::Result
- SmokeTestHelperRunner::UninstallWithSubprocessAndKill(
- const std::string& pkgid, uid_t uid, useconds_t delay) const {
- std::vector<std::string> args =
- { "-d", pkgid, "-u", std::to_string(uid) };
- return RunSubprocessAndKill(args, delay);
-}
-
-SmokeTestHelperRunner::Result SmokeTestHelperRunner::InstallPkgsWithSubprocess(
- const std::vector<bf::path>& paths, uid_t uid) const {
- std::vector<std::string> args;
- args.emplace_back("-i");
- for (const bf::path& p : paths)
- args.emplace_back(p.string());
- args.emplace_back("-u");
- args.emplace_back(std::to_string(uid));
- return RunSubprocess(args);
-}
-
-SmokeTestHelperRunner::Result
- SmokeTestHelperRunner::MountInstallPkgsWithSubprocess(
- const std::vector<bf::path>& paths, uid_t uid) const {
- std::vector<std::string> args;
- args.emplace_back("-w");
- for (const bf::path& p : paths)
- args.emplace_back(p.string());
- args.emplace_back("-u");
- args.emplace_back(std::to_string(uid));
- return RunSubprocess(args);
-}
-
-SmokeTestHelperRunner::Result SmokeTestHelperRunner::RecoveryPkgsWithSubprocess(
- const std::vector<bf::path>& paths, uid_t uid) const {
- std::vector<std::string> args;
- args.emplace_back("-b");
- for (const bf::path& p : paths)
- args.emplace_back(p.string());
- args.emplace_back("-u");
- args.emplace_back(std::to_string(uid));
- return RunSubprocess(args);
-}
-
-SmokeTestHelperRunner::Result
- SmokeTestHelperRunner::UninstallPkgsWithSubprocess(
- const std::vector<std::string>& pkgids, uid_t uid) const {
- std::vector<std::string> args;
- args.emplace_back("-d");
- args.insert(args.end(), pkgids.begin(), pkgids.end());
- args.emplace_back("-u");
- args.emplace_back(std::to_string(uid));
- return RunSubprocess(args);
-}
-
-SmokeTestHelperRunner::Result
- SmokeTestHelperRunner::InstallPkgsWithSubprocessAndKill(
- const std::vector<bf::path>& paths, uid_t uid, useconds_t delay) const {
- std::vector<std::string> args;
- args.emplace_back("-i");
- for (const bf::path& p : paths)
- args.emplace_back(p.string());
- args.emplace_back("-u");
- args.emplace_back(std::to_string(uid));
- return RunSubprocessAndKill(args, delay);
-}
-
-SmokeTestHelperRunner::Result
- SmokeTestHelperRunner::MountInstallPkgsWithSubprocessAndKill(
- const std::vector<bf::path>& paths, uid_t uid, useconds_t delay) const {
- std::vector<std::string> args;
- args.emplace_back("-w");
- for (const bf::path& p : paths)
- args.emplace_back(p.string());
- args.emplace_back("-u");
- args.emplace_back(std::to_string(uid));
- return RunSubprocessAndKill(args, delay);
-}
-
-bool CopySmackAccess(const boost::filesystem::path& src,
- const boost::filesystem::path& dst) {
- if (!bf::exists(src) && !bf::is_symlink(src)) {
- LOG(ERROR) << "Failed to copy smack access label";
- return false;
- }
- int ret;
- char* access_label = nullptr;
- ret = smack_lgetlabel(src.c_str(), &access_label, SMACK_LABEL_ACCESS);
- if (ret < 0) {
- LOG(ERROR) << "get access label from [" << src << "] fail";
- return false;
- }
- if (!access_label)
- return true;
- ret = smack_lsetlabel(dst.c_str(), access_label, SMACK_LABEL_ACCESS);
- free(access_label);
- if (ret < 0) {
- LOG(ERROR) << "set access label to [" << dst << "] fail";
- return false;
- }
- return true;
-}
-
-bool CopySmackExec(const boost::filesystem::path& src,
- const boost::filesystem::path& dst) {
- if (!bf::exists(src) && !bf::is_symlink(src)) {
- LOG(ERROR) << "Failed to copy smack exec label";
- return false;
- }
- int ret;
- char *exec_label = nullptr;
- ret = smack_lgetlabel(src.c_str(), &exec_label, SMACK_LABEL_EXEC);
- if (ret < 0) {
- LOG(ERROR) << "get exec label from [" << src << "] fail";
- return false;
- }
- if (!exec_label)
- return true;
- ret = smack_lsetlabel(dst.c_str(), exec_label, SMACK_LABEL_EXEC);
- free(exec_label);
- if (ret < 0) {
- LOG(ERROR) << "set exec label to [" << dst << "] fail";
- return false;
- }
- return true;
-}
-
-bool CopySmackMmap(const boost::filesystem::path& src,
- const boost::filesystem::path& dst) {
- if (!bf::exists(src) && !bf::is_symlink(src)) {
- LOG(ERROR) << "Failed to copy smack mmap label";
- return false;
- }
- int ret;
- char *mmap_label = nullptr;
- ret = smack_lgetlabel(src.c_str(), &mmap_label, SMACK_LABEL_MMAP);
- if (ret < 0) {
- LOG(ERROR) << "get mmap label from [" << src << "] fail";
- return false;
- }
- if (!mmap_label)
- return true;
- ret = smack_lsetlabel(dst.c_str(), mmap_label, SMACK_LABEL_MMAP);
- free(mmap_label);
- if (ret < 0) {
- LOG(ERROR) << "set mmap label to [" << dst << "] fail";
- return false;
- }
- return true;
-}
-
-bool CopySmackTransmute(const boost::filesystem::path& src,
- const boost::filesystem::path& dst) {
- if (!bf::exists(src)) {
- LOG(ERROR) << "Failed to copy smack tranmute label";
- return false;
- }
- int ret;
- char *transmute_label = nullptr;
- ret = smack_lgetlabel(src.c_str(), &transmute_label, SMACK_LABEL_TRANSMUTE);
- if (ret < 0) {
- LOG(ERROR) << "get access label from [" << src << "] fail";
- return false;
- }
- if (!transmute_label) {
- ret = smack_lsetlabel(dst.c_str(), "0", SMACK_LABEL_TRANSMUTE);
- } else {
- if (strcmp(transmute_label, "TRUE") == 0)
- ret = smack_lsetlabel(dst.c_str(), "1", SMACK_LABEL_TRANSMUTE);
- else
- ret = smack_lsetlabel(dst.c_str(), "0", SMACK_LABEL_TRANSMUTE);
- free(transmute_label);
- if (ret < 0) {
- LOG(ERROR) << "set access label to [" << dst << "] fail";
- return false;
- }
- }
-
- return true;
-}
-
-bool CopySmackLabels(const boost::filesystem::path& src,
- const boost::filesystem::path& dst) {
- if (!CopySmackAccess(src, dst))
- return false;
- if (!CopySmackExec(src, dst))
- return false;
- if (!CopySmackMmap(src, dst))
- return false;
- if (!bf::is_symlink(src) && bf::is_directory(src)) {
- if (!CopySmackTransmute(src, dst))
- return false;
- }
- return true;
-}
-
-bool CopyAndRemoveWithSmack(const bf::path& src, const bf::path& dst) {
- bs::error_code error;
- if (bf::exists(dst)) {
- try {
- bf::remove_all(dst, error);
- } catch (...) {
- std::cout << "Exception occurred during remove [" << dst.string()
- << "], and skip this file"<< std::endl;
- }
- if (error) {
- if (!bf::is_directory(dst)) {
- LOG(ERROR) << "remove_all fail";
- return false;
- }
- }
- }
- try {
- if (bf::is_symlink(src)) {
- bf::copy_symlink(src, dst, error);
- if (error) {
- LOG(ERROR) << "Failed to copy symlink: " << src << ", "
- << error.message();
- return false;
- }
- if (!CopySmackLabels(src, dst)) {
- LOG(ERROR) << "copy smack label from [" << src.string()
- << "] to [" << dst.string() << "] fail";
- return false;
- }
- } else if (bf::is_directory(src)) {
- if (!bf::exists(dst)) {
- bf::create_directories(dst, error);
- if (error) {
- LOG(ERROR) << "create directories fail";
- return false;
- }
- ci::CopyOwnershipAndPermissions(src, dst);
- if (!CopySmackLabels(src, dst)) {
- LOG(ERROR) << "copy smack label from [" << src.string()
- << "] to [" << dst.string() << "] fail";
- return false;
- }
- }
- bool success = true;
- for (bf::directory_iterator file(src);
- file != bf::directory_iterator();
- ++file) {
- bf::path current(file->path());
- bf::path target = dst / current.filename();
- success &= CopyAndRemoveWithSmack(current, target);
- }
- bf::remove_all(src);
- if (!success)
- return false;
- } else {
- bf::copy_file(src, dst);
- ci::CopyOwnershipAndPermissions(src, dst);
- if (!CopySmackLabels(src, dst)) {
- LOG(ERROR) << "copy smack label from [" << src.string()
- << "] to [" << dst.string() << "] fail";
- return false;
- }
- bf::remove_all(src);
- }
- } catch (...) {
- std::cout << "Exception occurred during copy [" << src.string()
- << "], and skip this file"<< std::endl;
- return true;
- }
-
- return true;
-}
-
-bool BackupPathCopyAndRemove(const bf::path& path) {
- if (!bf::exists(path))
- return true;
-
- bf::path backup_path = path.string() + ".bck";
- std::cout << "Backup path: " << path << " to " << backup_path << std::endl;
- if (!CopyAndRemoveWithSmack(path, backup_path)) {
- LOG(ERROR) << "Failed to setup test environment. Does some previous"
- << " test crashed? Path: "
- << backup_path << " should not exist.";
- return false;
- }
- return true;
-}
-
-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;
- 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.";
- return false;
- }
- assert(!error);
- if (bf::is_directory(backup_path))
- bf::create_directory(path);
- }
- return true;
-}
-
-bool RestorePathCopyAndRemove(const bf::path& path) {
- bf::path backup_path = path.string() + ".bck";
- if (!bf::exists(backup_path))
- return true;
-
- std::cout << "Restore path: " << path << " from " << backup_path << std::endl;
- if (!CopyAndRemoveWithSmack(backup_path, path)) {
- LOG(ERROR) << "Failed to restore backup path: " << backup_path;
- return false;
- }
- return true;
-}
-
-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) {
- 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) {
- LOG(ERROR) << "Failed to restore backup path: " << backup_path
- << " (" << error.message() << ")";
- return false;
- }
- }
- return true;
-}
-
-std::vector<bf::path> SetupBackupDirectories(uid_t test_uid) {
- std::vector<bf::path> entries;
- bf::path db_dir = bf::path(tzplatform_getenv(TZ_SYS_DB));
- if (test_uid != kGlobalUserUid)
- db_dir = db_dir / "user" / std::to_string(test_uid);
- for (auto e : kDBEntries) {
- bf::path path = db_dir / e;
- entries.emplace_back(path);
- }
-
- if (getuid() == 0) {
- entries.emplace_back(kPreloadApps);
- entries.emplace_back(kPreloadManifestDir);
- entries.emplace_back(kPreloadIcons);
- }
-
- if (test_uid == kGlobalUserUid) {
- entries.emplace_back(kSkelDir);
- entries.emplace_back(kGlobalManifestDir);
- ci::UserList list = ci::GetUserList();
- for (auto l : list) {
- bf::path apps = std::get<2>(l) / "apps_rw";
- entries.emplace_back(apps);
- }
- } else {
- tzplatform_set_user(test_uid);
- bf::path approot = tzplatform_getenv(TZ_USER_APPROOT);
- tzplatform_reset_user();
- entries.emplace_back(approot);
- }
-
- bf::path apps_rw = ci::GetRootAppPath(false, test_uid);
- entries.emplace_back(apps_rw);
- entries.emplace_back(kSdkDirectory);
-
- return entries;
-}
-
-void UninstallAllAppsInDirectory(bf::path dir, bool is_preload,
- BackendInterface* backend) {
- 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-Z0-9]{5,}");
- if (std::regex_match(package, pkg_regex)) {
- BackendInterface::CommandResult result =
- BackendInterface::CommandResult::OK;
- if (is_preload)
- result = backend->UninstallPreload(
- dir_entry.path().filename().string());
- else
- result = backend->Uninstall(
- dir_entry.path().filename().string());
- if (result != BackendInterface::CommandResult::OK) {
- LOG(ERROR) << "Cannot uninstall smoke test app: "
- << dir_entry.path().filename().string();
- }
- }
- }
- }
- }
-}
-
-void UninstallAllSmokeApps(ci::RequestMode request_mode, uid_t test_uid,
- BackendInterface *backend) {
- std::cout << "Uninstalling all smoke apps" << std::endl;
- bf::path apps_rw = ci::GetRootAppPath(false, test_uid);
- UninstallAllAppsInDirectory(apps_rw, false, backend);
- if (getuid() == 0 && request_mode == ci::RequestMode::GLOBAL) {
- bf::path root_path = kPreloadApps;
- UninstallAllAppsInDirectory(root_path, true, backend);
- }
-}
-
-int GetAppInstalledTime(const char* appid, uid_t uid) {
- int ret = 0;
- int installed_time = 0;
- pkgmgrinfo_appinfo_h handle = NULL;
- ret = pkgmgrinfo_appinfo_get_usr_appinfo(appid, uid, &handle);
- if (ret != PMINFO_R_OK)
- return -1;
- ret = pkgmgrinfo_appinfo_get_installed_time(handle, &installed_time);
- if (ret != PMINFO_R_OK) {
- pkgmgrinfo_appinfo_destroy_appinfo(handle);
- return -1;
- }
- pkgmgrinfo_appinfo_destroy_appinfo(handle);
- return installed_time;
-}
-
-} // namespace smoke_test
+++ /dev/null
-// 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_COMMON_SMOKE_UTILS_H_
-#define UNIT_TESTS_COMMON_SMOKE_UTILS_H_
-
-#include <pkgmgr-info.h>
-#include <signal.h>
-#include <unistd.h>
-#include <tzplatform_config.h>
-
-#include <boost/filesystem/operations.hpp>
-#include <boost/range/iterator_range.hpp>
-#include <boost/format.hpp>
-#include <boost/program_options.hpp>
-#include <boost/system/error_code.hpp>
-
-#include <gtest/gtest.h>
-#include <gtest/gtest-death-test.h>
-
-#include <manifest_parser/utils/version_number.h>
-
-#include <common/utils/subprocess.h>
-#include <common/utils/user_util.h>
-#include <common/utils/file_util.h>
-#include <common/utils/request.h>
-#include <common/tzip_interface.h>
-#include <common/installer/app_installer.h>
-#include <common/utils/paths.h>
-#include <common/utils/pkgmgr_query.h>
-#include <common/recovery_file.h>
-
-#include <array>
-#include <cstdio>
-#include <cstdlib>
-#include <memory>
-#include <regex>
-#include <string>
-#include <vector>
-#include <utility>
-
-#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 smoke_test {
-
-extern const bf::path kSmokePackagesDirectory;
-extern const bf::path kSdkDirectory;
-extern const uid_t kGlobalUserUid;
-extern const uid_t kGlobalUserGid;
-extern const char kLegacyExtImageDir[];
-extern const std::string& kDefaultUserIdStr;
-
-using App = std::pair<std::string, std::string>;
-using Apps = std::vector<App>;
-
-enum class RequestResult {
- NORMAL,
- FAIL
-};
-
-enum class StorageType {
- INTERNAL,
- EXTERNAL,
- EXTENDED
-};
-
-class ScopedTzipInterface {
- public:
- explicit ScopedTzipInterface(const std::string& pkgid, uid_t test_user)
- : pkg_path_(boost::filesystem::path(
- common_installer::GetRootAppPath(false, test_user)) / pkgid),
- interface_(common_installer::GetMountLocation(pkg_path_)),
- mounted_(true) {
- interface_.MountZip(common_installer::GetZipPackageLocation(pkg_path_,
- pkgid));
- }
-
- void Release() {
- if (mounted_) {
- interface_.UnmountZip();
- mounted_ = false;
- }
- }
-
- ~ScopedTzipInterface() {
- Release();
- }
-
- private:
- boost::filesystem::path pkg_path_;
- common_installer::TzipInterface interface_;
- bool mounted_;
-};
-
-class TestPkgmgrInstaller : public common_installer::PkgmgrInstallerInterface {
- public:
- bool CreatePkgMgrInstaller(pkgmgr_installer** installer,
- common_installer::InstallationMode* mode) {
- *installer = pkgmgr_installer_offline_new();
- if (!*installer)
- return false;
- *mode = common_installer::InstallationMode::ONLINE;
- return true;
- }
-
- bool ShouldCreateSignal() const {
- return false;
- }
-};
-
-enum class PackageType {
- TPK,
- WGT,
- HYBRID
-};
-
-struct User {
- uid_t uid = kGlobalUserUid;
- gid_t gid = kGlobalUserGid;
-};
-
-struct TestParameters {
- TestParameters(PackageType type, bool readonly) :
- pkg_type(type), is_readonly(readonly) {}
- TestParameters(const TestParameters& other) : pkg_type(other.pkg_type),
- is_readonly(other.is_readonly), test_user{other.test_user} {}
- PackageType pkg_type;
- bool is_readonly;
- User test_user;
-};
-
-struct PackageAttributes {
- explicit PackageAttributes(common_installer::PkgQueryInterface pi)
- : is_global(pi.IsGlobalPackage()), is_readonly(pi.IsReadonlyPackage()),
- is_update(pi.IsUpdatedPackage()), is_preload(pi.IsPreloadPackage()),
- is_system(pi.IsSystemPackage()), is_removable(pi.IsRemovablePackage()) {
- }
-
- bool operator==(const PackageAttributes& other) const {
- return (is_global == other.is_global) &&
- (is_readonly == other.is_readonly) &&
- (is_update == other.is_update) &&
- (is_preload == other.is_preload) &&
- (is_system == other.is_system) &&
- (is_removable == other.is_removable);
- }
-
- bool is_global;
- bool is_readonly;
- bool is_update;
- bool is_preload;
- bool is_system;
- bool is_removable;
-};
-
-common_installer::RequestMode ParseRequestMode(int argc, char** argv);
-
-bool TouchFile(const boost::filesystem::path& path);
-
-void AddDataFiles(const std::string& pkgid, uid_t uid);
-
-bool AddTestUser(User* test_user);
-
-bool DeleteTestUser();
-
-void RemoveAllRecoveryFiles(const std::string& prefix, uid_t uid);
-
-boost::filesystem::path FindRecoveryFile(const std::string& prefix, uid_t uid);
-
-boost::filesystem::path GetPackageRoot(const std::string& pkgid, uid_t uid);
-
-std::unique_ptr<common_installer::recovery::RecoveryFile> GetRecoverFileInfo(
- const bf::path& recovery_file_path);
-
-bool ValidateFileContentInPackage(const std::string& pkgid,
- const std::string& relative,
- const std::string& expected,
- const TestParameters& params);
-
-bool ValidatePackage(const std::string& pkgid, const Apps& apps,
- const TestParameters& params);
-
-bool ValidateDataFiles(const std::string& pkgid, uid_t uid);
-
-bool ValidateExternalPackage(const std::string& pkgid, const Apps& apps,
- const TestParameters& params);
-bool ValidateExtendedPackage(const std::string& pkgid, const Apps& apps,
- const TestParameters& params);
-
-bool CheckPackageNonExistance(const std::string& pkgid,
- const TestParameters& params);
-
-bool CheckPackageReadonlyNonExistance(const std::string& pkgid,
- const TestParameters& params);
-
-bool CheckSharedDataExistance(const std::string& pkgid,
- const TestParameters& params);
-
-bool CheckSharedDataNonExistance(const std::string& pkgid,
- const TestParameters& params);
-
-bool TouchFile(const boost::filesystem::path& path);
-
-class SmokeInstallerFactory {
- public:
- using AppInstallerPtr = std::unique_ptr<common_installer::AppInstaller>;
- virtual AppInstallerPtr CreateInstaller(
- int idx, common_installer::PkgMgrPtr pkgmgr) const = 0;
- virtual AppInstallerPtr CreateFailExpectedInstaller(
- int idx, common_installer::PkgMgrPtr pkgmgr, int fail_at = -1) const = 0;
-};
-
-class BackendInterface {
- public:
- using CommandResult = common_installer::AppInstaller::Result;
- using SmokeInstallerFactoryPtr = std::unique_ptr<SmokeInstallerFactory>;
- explicit BackendInterface(std::string uid,
- RequestResult mode = RequestResult::NORMAL)
- : uid_str_(uid), mode_(mode) {}
- explicit BackendInterface(SmokeInstallerFactoryPtr factory,
- std::string uid,
- RequestResult mode = RequestResult::NORMAL)
- : factory_(std::move(factory)), uid_str_(uid), mode_(mode) {}
- virtual ~BackendInterface() {}
-
- void TestRollbackAfterEachStep(int argc, const char* argv[],
- std::function<bool()> validator) const;
- void CrashAfterEachStep(std::vector<std::string>* args,
- std::function<bool(int iter)> validator,
- PackageType type) const;
- CommandResult Install(const std::vector<bf::path>& paths) const;
- CommandResult InstallSuccess(const std::vector<bf::path>& paths) const;
- CommandResult Install(const boost::filesystem::path& path) const;
- CommandResult InstallPreload(const boost::filesystem::path& path) const;
- CommandResult InstallWithStorage(const boost::filesystem::path& path,
- StorageType type = StorageType::INTERNAL) const;
- CommandResult InstallSuccess(const bf::path& path) const;
- CommandResult InstallPreloadSuccess(
- const boost::filesystem::path& path) const;
-
- CommandResult Uninstall(const std::vector<std::string>& pkgids) const;
- CommandResult Uninstall(const std::string& pkgid) const;
- CommandResult UninstallPreload(const std::string& pkgid) const;
-
- CommandResult EnablePackage(const std::string& pkgid) const;
- CommandResult DisablePackage(const std::string& pkgid) const;
-
- CommandResult MountInstall(const boost::filesystem::path& path) const;
- CommandResult MountInstallSuccess(const bf::path& path) const;
- CommandResult ManifestDirectInstall(const std::string& pkgid) const;
-
- CommandResult MigrateLegacyExternalImage(const std::string& pkgid,
- const boost::filesystem::path& path,
- const boost::filesystem::path& legacy_path) const;
-
- CommandResult RDSUpdate(const boost::filesystem::path& path,
- const std::string& pkgid) const;
-
- CommandResult Recover(const boost::filesystem::path& recovery_file) const;
-
- protected:
- CommandResult CallBackend(int argc, const char* argv[]) const;
- CommandResult CallBackendWithRunner(int argc, const char* argv[]) const;
- using AppQueryInterfacePtr =
- std::unique_ptr<common_installer::AppQueryInterface>;
- using AppInstallerPtr = std::unique_ptr<common_installer::AppInstaller>;
- SmokeInstallerFactoryPtr factory_;
- std::string uid_str_;
- RequestResult mode_;
-
- private:
- CommandResult RunInstallerWithPkgrmgr(
- common_installer::PkgMgrPtr pkgmgr) const;
- virtual AppQueryInterfacePtr CreateQueryInterface() const = 0;
- virtual AppInstallerPtr CreateInstaller(
- common_installer::PkgMgrPtr pkgmgr) const = 0;
- virtual AppInstallerPtr CreateFailExpectedInstaller(
- common_installer::PkgMgrPtr pkgmgr, int fail_at = -1) const = 0;
- CommandResult RunInstallersWithPkgmgr(
- common_installer::PkgMgrPtr pkgmgr) const;
-};
-
-class SmokeTestHelperRunner {
- public:
- enum class Result {
- SUCCESS,
- FAIL,
- KILLED,
- UnKnown
- };
-
- Result InstallWithSubprocess(const bf::path& path, uid_t uid) const;
- Result MountInstallWithSubprocess(const bf::path& path, uid_t uid) const;
- Result RecoveryWithSubprocess(const bf::path& path, uid_t uid) const;
- Result UninstallWithSubprocess(const std::string& pkgid, uid_t uid) const;
- Result InstallWithSubprocessAndKill(
- const bf::path& path, uid_t uid, useconds_t delay) const;
- Result MountInstallWithSubprocessAndKill(
- const bf::path& path, uid_t uid, useconds_t delay) const;
- Result UninstallWithSubprocessAndKill(
- const std::string& pkgid, uid_t uid, useconds_t delay) const;
- Result InstallPkgsWithSubprocess(
- const std::vector<bf::path>& paths, uid_t uid) const;
- Result MountInstallPkgsWithSubprocess(
- const std::vector<bf::path>& paths, uid_t uid) const;
- Result RecoveryPkgsWithSubprocess(
- const std::vector<bf::path>& paths, uid_t uid) const;
- Result UninstallPkgsWithSubprocess(
- const std::vector<std::string>& pkgids, uid_t uid) const;
- Result InstallPkgsWithSubprocessAndKill(
- const std::vector<bf::path>& paths, uid_t uid, useconds_t delay) const;
- Result MountInstallPkgsWithSubprocessAndKill(
- const std::vector<bf::path>& paths, uid_t uid, useconds_t delay) const;
-
- private:
- Result RunSubprocess(std::vector<std::string> args) const;
- Result RunSubprocessAndKill(std::vector<std::string> args,
- useconds_t delay) const;
- virtual common_installer::Subprocess CreateSubprocess() const = 0;
-};
-
-bool CheckAvailableExternalPath();
-
-bool CheckAvailableExtendedPath();
-
-bool BackupPathCopyAndRemove(const boost::filesystem::path& path);
-
-bool BackupPath(const boost::filesystem::path& path);
-
-bool RestorePathCopyAndRemove(const boost::filesystem::path& path);
-
-bool RestorePath(const boost::filesystem::path& path);
-
-std::vector<boost::filesystem::path> SetupBackupDirectories(uid_t test_uid);
-
-void UninstallAllAppsInDirectory(boost::filesystem::path dir, bool is_preload,
- BackendInterface* backend);
-
-void UninstallAllSmokeApps(common_installer::RequestMode request_mode,
- uid_t test_uid, BackendInterface* backend);
-
-int GetAppInstalledTime(const char* appid, uid_t uid);
-
-enum class CrashStepType {
- PROCESS,
- CLEAN
-};
-
-class StepCrash : public common_installer::Step {
- public:
- using Step::Step;
-
- explicit StepCrash(common_installer::InstallerContext* context,
- CrashStepType type)
- : common_installer::Step::Step(context), type_(type) {}
-
- common_installer::Step::Status process() override {
- if (type_ == CrashStepType::PROCESS)
- raise(SIGSEGV);
- return Status::OK;
- }
- common_installer::Step::Status clean() override {
- if (type_ == CrashStepType::CLEAN)
- raise(SIGSEGV);
- return Status::OK;
- }
- common_installer::Step::Status undo() override {
- return common_installer::Step::Status::OK;
- }
- common_installer::Step::Status precheck() override {
- return common_installer::Step::Status::OK;
- }
-
- STEP_NAME(Crash)
-
- private:
- CrashStepType type_;
-};
-
-} // namespace smoke_test
-
-#endif // UNIT_TESTS_COMMON_SMOKE_UTILS_H_
+++ /dev/null
-SET(PLUGIN_DIR ${SHAREDIR}/${DESTINATION_DIR}/test_samples/plugins/)
-
-INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../../..)
-
-ADD_LIBRARY(${TARGET_ASSESSOR_LIB} SHARED
- test_assessor.cc
-)
-ADD_LIBRARY(${TARGET_TEST_TAG_PLUGIN} SHARED
- test_tag_plugin.cc
-)
-ADD_LIBRARY(${TARGET_TEST_CATEGORY_PLUGIN} SHARED
- test_category_plugin.cc
-)
-ADD_LIBRARY(${TARGET_TEST_METADATA_PLUGIN} SHARED
- test_metadata_plugin.cc
-)
-ADD_LIBRARY(${TARGET_TEST_TAG_FAIL_PLUGIN} SHARED
- test_tag_fail_plugin.cc
-)
-ADD_LIBRARY(${TARGET_TEST_CATEGORY_FAIL_PLUGIN} SHARED
- test_category_fail_plugin.cc
-)
-ADD_LIBRARY(${TARGET_TEST_METADATA_FAIL_PLUGIN} SHARED
- test_metadata_fail_plugin.cc
-)
-
-TARGET_LINK_LIBRARIES(${TARGET_ASSESSOR_LIB} PUBLIC ${TARGET_LIBNAME_COMMON})
-TARGET_LINK_LIBRARIES(${TARGET_TEST_TAG_PLUGIN} PUBLIC ${TARGET_LIBNAME_COMMON} ${TARGET_ASSESSOR_LIB})
-TARGET_LINK_LIBRARIES(${TARGET_TEST_CATEGORY_PLUGIN} PUBLIC ${TARGET_LIBNAME_COMMON} ${TARGET_ASSESSOR_LIB})
-TARGET_LINK_LIBRARIES(${TARGET_TEST_METADATA_PLUGIN} PUBLIC ${TARGET_LIBNAME_COMMON} ${TARGET_ASSESSOR_LIB})
-TARGET_LINK_LIBRARIES(${TARGET_TEST_TAG_FAIL_PLUGIN} PUBLIC ${TARGET_LIBNAME_COMMON} ${TARGET_ASSESSOR_LIB})
-TARGET_LINK_LIBRARIES(${TARGET_TEST_CATEGORY_FAIL_PLUGIN} PUBLIC ${TARGET_LIBNAME_COMMON} ${TARGET_ASSESSOR_LIB})
-TARGET_LINK_LIBRARIES(${TARGET_TEST_METADATA_FAIL_PLUGIN} PUBLIC ${TARGET_LIBNAME_COMMON} ${TARGET_ASSESSOR_LIB})
-
-INSTALL(TARGETS ${TARGET_ASSESSOR_LIB} DESTINATION ${LIBDIR})
-INSTALL(TARGETS ${TARGET_TEST_TAG_PLUGIN} DESTINATION ${PLUGIN_DIR})
-INSTALL(TARGETS ${TARGET_TEST_CATEGORY_PLUGIN} DESTINATION ${PLUGIN_DIR})
-INSTALL(TARGETS ${TARGET_TEST_METADATA_PLUGIN} DESTINATION ${PLUGIN_DIR})
-INSTALL(TARGETS ${TARGET_TEST_TAG_FAIL_PLUGIN} DESTINATION ${PLUGIN_DIR})
-INSTALL(TARGETS ${TARGET_TEST_CATEGORY_FAIL_PLUGIN} DESTINATION ${PLUGIN_DIR})
-INSTALL(TARGETS ${TARGET_TEST_METADATA_FAIL_PLUGIN} DESTINATION ${PLUGIN_DIR})
+++ /dev/null
-// Copyright (c) 2016 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 "unit_tests/libs/test_assessor.h"
-
-namespace common_installer {
-
-const char kTagPluginName[] = "tag";
-const char kCategoryPluginName[] = "category";
-const char kMetadataPluginName[] = "metadata";
-const char kTestPackageId[] = "org.tizen.testapp";
-const char kTestApplicationId[] = "org.tizen.testapp.main";
-
-void TestAssessor::ClearResults() {
- results.clear();
-}
-
-void TestAssessor::AddResult(const ResultLine& result,
- const boost::optional<std::string>& error) {
- results.insert(std::make_pair(result, error));
-}
-
-const TestAssessor::ResultStore& TestAssessor::GetResults() const {
- return results;
-}
-
-} // namespace common_installer
+++ /dev/null
-// Copyright (c) 2016 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_LIBS_TEST_ASSESSOR_H_
-#define UNIT_TESTS_LIBS_TEST_ASSESSOR_H_
-
-#include <boost/optional/optional.hpp>
-
-#include <map>
-#include <string>
-#include <tuple>
-#include <utility>
-
-#include "common/plugins/plugin.h"
-#include "common/utils/singleton.h"
-
-namespace common_installer {
-
-extern const char kTagPluginName[];
-extern const char kCategoryPluginName[];
-extern const char kMetadataPluginName[];
-extern const char kTestPackageId[];
-extern const char kTestApplicationId[];
-
-class TestAssessor : public common_installer::Singleton<TestAssessor> {
- CRTP_DECLARE_DEFAULT_CONSTRUCTOR_CLASS(TestAssessor)
- public:
- using ResultLine = std::tuple<std::string, Plugin::ActionType,
- Plugin::ProcessType>;
- using ResultStore = std::map<ResultLine, boost::optional<std::string>>;
-
- void ClearResults();
- void AddResult(const ResultLine& result,
- const boost::optional<std::string> &error);
- const ResultStore& GetResults() const;
-
- private:
- ResultStore results;
-};
-
-} // namespace common_installer
-
-#endif // UNIT_TESTS_LIBS_TEST_ASSESSOR_H_
+++ /dev/null
-// Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
-// Use of this source code is governed by an apache 2.0 license that can be
-// found in the LICENSE file.
-
-#include <boost/optional/optional.hpp>
-
-#include <pkgmgr_parser.h>
-
-#include <glib/glist.h>
-
-#include <cstring>
-#include <string>
-#include <tuple>
-
-#include "common/plugins/plugin.h"
-#include "common/utils/glist_range.h"
-
-extern "C" int PKGMGR_CATEGORY_PARSER_PLUGIN_INSTALL(
- const char*, const char*, GList*) {
- return -1;
-}
-
-extern "C" int PKGMGR_CATEGORY_PARSER_PLUGIN_UPGRADE(
- const char*, const char*, GList*) {
- return -1;
-}
-
-extern "C" int PKGMGR_CATEGORY_PARSER_PLUGIN_UNINSTALL(
- const char*, const char*, GList*) {
- return -1;
-}
+++ /dev/null
-// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
-// Use of this source code is governed by an apache 2.0 license that can be
-// found in the LICENSE file.
-
-#include <boost/optional/optional.hpp>
-
-#include <pkgmgr_parser.h>
-
-#include <glib/glist.h>
-
-#include <cstring>
-#include <string>
-#include <tuple>
-
-#include "common/plugins/plugin.h"
-#include "common/utils/glist_range.h"
-#include "unit_tests/libs/test_assessor.h"
-
-namespace ci = common_installer;
-
-namespace {
-
-boost::optional<std::string> CheckArgs(
- const char* pkgid,
- const char* appid,
- GList* categories) {
- if (!pkgid)
- return std::string("Package id is null for category plugin");
- if (!appid)
- return std::string("Application id is null for category plugin");
- if (strcmp(pkgid, ci::kTestPackageId) != 0)
- return std::string("Package id doesn't match for category plugin");
- if (strcmp(appid, ci::kTestApplicationId) != 0)
- return std::string("Application id doesn't match for category plugin");
- auto range = GListRange<__category_t*>(categories);
- if (range.Size() != 3)
- return std::string("Metadata Glist is wrong size for category plugin");
- bool found = false;
- for (__category_t* category : range) {
- if (strcmp(category->name, "http://tizen.org/category/test_category") == 0)
- found = true;
- }
- if (!found)
- return std::string("Category value not found");
- return {};
-}
-
-} // namespace
-
-extern "C" int PKGMGR_CATEGORY_PARSER_PLUGIN_INSTALL(
- const char* pkgid,
- const char* appid,
- GList* categories) {
- ci::TestAssessor::Instance().AddResult(std::make_tuple(
- ci::kCategoryPluginName,
- ci::Plugin::ActionType::Install,
- ci::Plugin::ProcessType::Main),
- CheckArgs(pkgid, appid, categories));
- return 0;
-}
-
-extern "C" int PKGMGR_CATEGORY_PARSER_PLUGIN_UPGRADE(
- const char* pkgid,
- const char* appid,
- GList* categories) {
- ci::TestAssessor::Instance().AddResult(std::make_tuple(
- ci::kCategoryPluginName,
- ci::Plugin::ActionType::Upgrade,
- ci::Plugin::ProcessType::Main),
- CheckArgs(pkgid, appid, categories));
- return 0;
-}
-
-extern "C" int PKGMGR_CATEGORY_PARSER_PLUGIN_UNINSTALL(
- const char* pkgid,
- const char* appid,
- GList* categories) {
- ci::TestAssessor::Instance().AddResult(std::make_tuple(
- ci::kCategoryPluginName,
- ci::Plugin::ActionType::Uninstall,
- ci::Plugin::ProcessType::Main),
- CheckArgs(pkgid, appid, categories));
- return 0;
-}
+++ /dev/null
-// Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
-// Use of this source code is governed by an apache 2.0 license that can be
-// found in the LICENSE file.
-
-#include <boost/optional/optional.hpp>
-
-#include <pkgmgr_parser.h>
-
-#include <glib/glist.h>
-
-#include <cstring>
-#include <string>
-#include <tuple>
-
-#include "common/plugins/plugin.h"
-#include "common/utils/glist_range.h"
-
-extern "C" int PKGMGR_MDPARSER_PLUGIN_INSTALL(
- const char*, const char*, GList*) {
- return -1;
-}
-
-extern "C" int PKGMGR_MDPARSER_PLUGIN_UPGRADE(
- const char*, const char*, GList*) {
- return -1;
-}
-
-extern "C" int PKGMGR_MDPARSER_PLUGIN_UNINSTALL(
- const char*, const char*, GList*) {
- return -1;
-}
+++ /dev/null
-// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
-// Use of this source code is governed by an apache 2.0 license that can be
-// found in the LICENSE file.
-
-#include <boost/optional/optional.hpp>
-
-#include <pkgmgr_parser.h>
-
-#include <glib/glist.h>
-
-#include <cstring>
-#include <string>
-#include <tuple>
-
-#include "common/plugins/plugin.h"
-#include "common/utils/glist_range.h"
-#include "unit_tests/libs/test_assessor.h"
-
-namespace ci = common_installer;
-
-namespace {
-
-boost::optional<std::string> CheckArgs(
- const char* pkgid,
- const char* appid,
- GList* metadata) {
- if (!pkgid)
- return std::string("Package id is null for metadata plugin");
- if (!appid)
- return std::string("Application id is null for metadata plugin");
- if (strcmp(pkgid, ci::kTestPackageId) != 0)
- return std::string("Package id doesn't match for metadata plugin");
- if (strcmp(appid, ci::kTestApplicationId) != 0)
- return std::string("Application id doesn't match for metadata plugin");
- auto range = GListRange<__metadata_t*>(metadata);
- if (range.Size() != 3)
- return std::string("Metadata Glist is wrong size for metadata plugin");
- bool found_a = false;
- bool found_b = false;
- bool found_c = false;
- for (__metadata_t* meta : range) {
- if (strcmp(meta->key,
- "http://developer.samsung.com/tizen/metadata/test_metadata/key_a")
- == 0 && strcmp(meta->value, "value_a") == 0) {
- found_a = true;
- }
- if (strcmp(meta->key,
- "http://developer.samsung.com/tizen/metadata/test_metadata/key_b")
- == 0 && strcmp(meta->value, "value_b") == 0) {
- found_b = true;
- }
- if (strcmp(meta->key,
- "http://developer.samsung.com/tizen/metadata/test_metadata/key_c")
- == 0 && strcmp(meta->value, "value_c") == 0) {
- found_c = true;
- }
- }
- if (!found_a)
- return std::string("Metadata key_a incorrect or not found");
- if (!found_b)
- return std::string("Metadata key_b incorrect or not found");
- if (!found_c)
- return std::string("Metadata key_c incorrect or not found");
- return {};
-}
-
-} // namespace
-
-extern "C" int PKGMGR_MDPARSER_PLUGIN_INSTALL(
- const char* pkgid,
- const char* appid,
- GList* metadata) {
- ci::TestAssessor::Instance().AddResult(std::make_tuple(
- ci::kMetadataPluginName,
- ci::Plugin::ActionType::Install,
- ci::Plugin::ProcessType::Main),
- CheckArgs(pkgid, appid, metadata));
- return 0;
-}
-
-extern "C" int PKGMGR_MDPARSER_PLUGIN_UPGRADE(
- const char* pkgid,
- const char* appid,
- GList* metadata) {
- ci::TestAssessor::Instance().AddResult(std::make_tuple(
- ci::kMetadataPluginName,
- ci::Plugin::ActionType::Upgrade,
- ci::Plugin::ProcessType::Main),
- CheckArgs(pkgid, appid, metadata));
- return 0;
-}
-
-extern "C" int PKGMGR_MDPARSER_PLUGIN_UNINSTALL(
- const char* pkgid,
- const char* appid,
- GList* metadata) {
- ci::TestAssessor::Instance().AddResult(std::make_tuple(
- ci::kMetadataPluginName,
- ci::Plugin::ActionType::Uninstall,
- ci::Plugin::ProcessType::Main),
- CheckArgs(pkgid, appid, metadata));
- return 0;
-}
+++ /dev/null
-// Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
-// Use of this source code is governed by an apache 2.0 license that can be
-// found in the LICENSE file.
-
-#include <boost/optional/optional.hpp>
-
-#include <cstring>
-#include <string>
-#include <tuple>
-
-#include "common/plugins/plugin.h"
-
-extern "C" int PKGMGR_PARSER_PLUGIN_PRE_INSTALL(const char*) {
- return 0;
-}
-
-extern "C" int PKGMGR_PARSER_PLUGIN_PRE_UPGRADE(const char*) {
- return 0;
-}
-extern "C" int PKGMGR_PARSER_PLUGIN_PRE_UNINSTALL(const char*) {
- return 0;
-}
-
-extern "C" int PKGMGR_PARSER_PLUGIN_INSTALL(xmlDocPtr, const char*) {
- return 0;
-}
-
-extern "C" int PKGMGR_PARSER_PLUGIN_UPGRADE(xmlDocPtr, const char*) {
- return 0;
-}
-
-extern "C" int PKGMGR_PARSER_PLUGIN_UNINSTALL(xmlDocPtr, const char*) {
- return 0;
-}
-
-extern "C" int PKGMGR_PARSER_PLUGIN_POST_INSTALL(const char*) {
- return -1;
-}
-
-extern "C" int PKGMGR_PARSER_PLUGIN_POST_UPGRADE(const char*) {
- return -1;
-}
-
-extern "C" int PKGMGR_PARSER_PLUGIN_POST_UNINSTALL(const char*) {
- return -1;
-}
+++ /dev/null
-// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
-// Use of this source code is governed by an apache 2.0 license that can be
-// found in the LICENSE file.
-
-#include <boost/optional/optional.hpp>
-
-#include <cstring>
-#include <string>
-#include <tuple>
-
-#include "common/plugins/plugin.h"
-#include "unit_tests/libs/test_assessor.h"
-
-namespace ci = common_installer;
-
-namespace {
-
-boost::optional<std::string> CheckArgs(const char* pkgid) {
- if (!pkgid)
- return std::string("Package id is null for tag plugin");
- if (strcmp(pkgid, ci::kTestPackageId) != 0)
- return std::string("Package id doesn't match for tag plugin") +
- "Expected: " + ci::kTestPackageId + " actual: " + pkgid;
- return {};
-}
-
-boost::optional<std::string> CheckArgs(xmlDocPtr doc, const char* pkgid) {
- if (!doc)
- return std::string("XML doc pointer is null for tag plugin");
- return CheckArgs(pkgid);
-}
-
-} // namespace
-
-extern "C" int PKGMGR_PARSER_PLUGIN_PRE_INSTALL(const char* package) {
- ci::TestAssessor::Instance().AddResult(std::make_tuple(
- ci::kTagPluginName,
- ci::Plugin::ActionType::Install,
- ci::Plugin::ProcessType::Pre),
- CheckArgs(package));
- return 0;
-}
-
-extern "C" int PKGMGR_PARSER_PLUGIN_PRE_UPGRADE(const char* package) {
- ci::TestAssessor::Instance().AddResult(std::make_tuple(
- ci::kTagPluginName,
- ci::Plugin::ActionType::Upgrade,
- ci::Plugin::ProcessType::Pre),
- CheckArgs(package));
- return 0;
-}
-extern "C" int PKGMGR_PARSER_PLUGIN_PRE_UNINSTALL(const char* package) {
- ci::TestAssessor::Instance().AddResult(std::make_tuple(
- ci::kTagPluginName,
- ci::Plugin::ActionType::Uninstall,
- ci::Plugin::ProcessType::Pre),
- CheckArgs(package));
- return 0;
-}
-
-extern "C" int PKGMGR_PARSER_PLUGIN_INSTALL(xmlDocPtr doc,
- const char* package) {
- ci::TestAssessor::Instance().AddResult(std::make_tuple(
- ci::kTagPluginName,
- ci::Plugin::ActionType::Install,
- ci::Plugin::ProcessType::Main),
- CheckArgs(doc, package));
- return 0;
-}
-
-extern "C" int PKGMGR_PARSER_PLUGIN_UPGRADE(xmlDocPtr doc,
- const char* package) {
- ci::TestAssessor::Instance().AddResult(std::make_tuple(
- ci::kTagPluginName,
- ci::Plugin::ActionType::Upgrade,
- ci::Plugin::ProcessType::Main),
- CheckArgs(doc, package));
- return 0;
-}
-
-extern "C" int PKGMGR_PARSER_PLUGIN_UNINSTALL(xmlDocPtr doc,
- const char* package) {
- ci::TestAssessor::Instance().AddResult(std::make_tuple(
- ci::kTagPluginName,
- ci::Plugin::ActionType::Uninstall,
- ci::Plugin::ProcessType::Main),
- CheckArgs(doc, package));
- return 0;
-}
-
-extern "C" int PKGMGR_PARSER_PLUGIN_POST_INSTALL(const char* package) {
- ci::TestAssessor::Instance().AddResult(std::make_tuple(
- ci::kTagPluginName,
- ci::Plugin::ActionType::Install,
- ci::Plugin::ProcessType::Post),
- CheckArgs(package));
- return 0;
-}
-
-extern "C" int PKGMGR_PARSER_PLUGIN_POST_UPGRADE(const char* package) {
- ci::TestAssessor::Instance().AddResult(std::make_tuple(
- ci::kTagPluginName,
- ci::Plugin::ActionType::Upgrade,
- ci::Plugin::ProcessType::Post),
- CheckArgs(package));
- return 0;
-}
-
-extern "C" int PKGMGR_PARSER_PLUGIN_POST_UNINSTALL(const char* package) {
- ci::TestAssessor::Instance().AddResult(std::make_tuple(
- ci::kTagPluginName,
- ci::Plugin::ActionType::Uninstall,
- ci::Plugin::ProcessType::Post),
- CheckArgs(package));
- return 0;
-}
+++ /dev/null
-// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
-// Use of this source code is governed by an apache 2.0 license that can be
-// found in the LICENSE file.
-
-#include <boost/filesystem/path.hpp>
-#include <gtest/gtest.h>
-
-#include <memory>
-#include <iterator>
-#include <tuple>
-
-#include "common/installer_context.h"
-#include "common/step/configuration/step_parse_manifest.h"
-#include "common/plugins/plugin_factory.h"
-#include "common/plugins/plugin_list_parser.h"
-#include "common/plugins/plugin_manager.h"
-#include "common/plugins/plugin_xml_parser.h"
-#include "unit_tests/libs/test_assessor.h"
-
-namespace bf = boost::filesystem;
-namespace ci = common_installer;
-
-namespace {
-
-const char kPluginsTestFiles[] =
- "/usr/share/app-installers-ut/test_samples/plugins";
-
-const bf::path kTestTagPlugin =
- bf::path(kPluginsTestFiles) / "libtest-tag-plugin.so";
-const bf::path kTestCategoryPlugin =
- bf::path(kPluginsTestFiles) / "libtest-category-plugin.so";
-const bf::path kTestMetadataPlugin =
- bf::path(kPluginsTestFiles) / "libtest-metadata-plugin.so";
-const bf::path kTestValidPluginsListDir =
- bf::path(kPluginsTestFiles) / "valid-parser-plugins";
-const bf::path kTestValidFailPluginsListDir =
- bf::path(kPluginsTestFiles) / "valid-fail-parser-plugins";
-const bf::path kTestInvalidPluginsListDir =
- bf::path(kPluginsTestFiles) / "invalid-parser-plugins";
-
-void CheckCall(
- const ci::TestAssessor::ResultStore& store,
- const std::string& name,
- ci::Plugin::ActionType action) {
- auto iter_pre = store.find(
- std::make_tuple(name, action, ci::Plugin::ProcessType::Pre));
- auto iter_main = store.find(
- std::make_tuple(name, action, ci::Plugin::ProcessType::Main));
- auto iter_post = store.find(
- std::make_tuple(name, action, ci::Plugin::ProcessType::Post));
- ASSERT_NE(iter_pre, store.end());
- ASSERT_NE(iter_main, store.end());
- ASSERT_NE(iter_post, store.end());
-
- // Error is not set
- ASSERT_TRUE(!iter_pre->second) << *iter_pre->second;
- ASSERT_TRUE(!iter_main->second) << *iter_main->second;
- ASSERT_TRUE(!iter_post->second) << *iter_post->second;
-
- // Check order of calling
- auto ts_pre = std::distance(store.begin(), iter_pre);
- auto ts_main = std::distance(store.begin(), iter_main);
- auto ts_post = std::distance(store.begin(), iter_post);
- ASSERT_GT(ts_main, ts_pre);
- ASSERT_GT(ts_post, ts_main);
-}
-
-void CheckCallMain(
- const ci::TestAssessor::ResultStore& store,
- const std::string& name,
- ci::Plugin::ActionType action) {
- auto iter_main = store.find(
- std::make_tuple(name, action, ci::Plugin::ProcessType::Main));
- ASSERT_NE(iter_main, store.end());
-
- // Error is not set
- ASSERT_TRUE(!iter_main->second) << *iter_main->second;
-}
-
-} // namespace
-
-namespace common_installer {
-
-class PluginTest : public testing::Test {
-};
-
-TEST_F(PluginTest, PluginsXmlParser_Valid) {
- bf::path manifest = bf::path(kPluginsTestFiles) / "tizen-manifest.xml";
- PluginsXmlParser parser(manifest);
- ASSERT_TRUE(parser.Parse());
- ASSERT_NE(parser.doc_ptr(), nullptr);
- auto tags = parser.tags_list();
- ASSERT_NE(std::find(tags.begin(), tags.end(), "author"), tags.end());
- ASSERT_NE(std::find(tags.begin(), tags.end(), "description"), tags.end());
- ASSERT_NE(std::find(tags.begin(), tags.end(), "ui-application"), tags.end());
- ASSERT_NE(std::find(tags.begin(), tags.end(), "test"), tags.end());
-
- ASSERT_EQ(std::find(tags.begin(), tags.end(), "label"), tags.end());
- ASSERT_EQ(std::find(tags.begin(), tags.end(), "app-control"), tags.end());
- ASSERT_EQ(std::find(tags.begin(), tags.end(), "datacontrol"), tags.end());
- ASSERT_EQ(std::find(tags.begin(), tags.end(), "mime"), tags.end());
- ASSERT_EQ(std::find(tags.begin(), tags.end(), "operation"), tags.end());
- ASSERT_EQ(std::find(tags.begin(), tags.end(), "uri"), tags.end());
- ASSERT_EQ(std::find(tags.begin(), tags.end(), "key"), tags.end());
- ASSERT_EQ(std::find(tags.begin(), tags.end(), "name"), tags.end());
- ASSERT_EQ(std::find(tags.begin(), tags.end(), ""), tags.end());
-}
-
-TEST_F(PluginTest, PluginsXmlParser_Invalid) {
- bf::path manifest = bf::path(kPluginsTestFiles) / "invalid_manifest.xml";
- PluginsXmlParser parser(manifest);
- ASSERT_FALSE(parser.Parse());
-}
-
-TEST_F(PluginTest, PluginsListParser_Valid) {
- PluginsListParser parser(kTestValidPluginsListDir);
- ASSERT_TRUE(parser.Parse());
- auto list = parser.PluginInfoList();
- ASSERT_EQ(list.size(), 3);
- for (auto list_item : list) {
- if (list_item->type() == "tag") {
- ASSERT_EQ(list_item->name(), "test");
- ASSERT_EQ(list_item->path(), kTestTagPlugin.string());
- } else if (list_item->type() == "category") {
- ASSERT_EQ(list_item->name(), "http://tizen.org/category/test_category");
- ASSERT_EQ(list_item->path(), kTestCategoryPlugin.string());
- } else if (list_item->type() == "metadata") {
- ASSERT_EQ(list_item->name(),
- "http://developer.samsung.com/tizen/metadata/test_metadata");
- ASSERT_EQ(list_item->path(), kTestMetadataPlugin.string());
- }
- }
-}
-
-TEST_F(PluginTest, PluginsListParser_Invalid) {
- PluginsListParser parser(kTestInvalidPluginsListDir);
- ASSERT_FALSE(parser.Parse());
-}
-
-TEST_F(PluginTest, PluginFactory_CreatingPlugins) {
- PluginFactory factory;
- PluginInfo tag_info("tag", "test", kTestTagPlugin.string(), false);
- ASSERT_TRUE(!!factory.CreatePluginByPluginInfo(tag_info));
- PluginInfo category_info("category", "category",
- kTestCategoryPlugin.string(), false);
- ASSERT_TRUE(!!factory.CreatePluginByPluginInfo(category_info));
- PluginInfo metadata_info("metadata", "metadata",
- kTestMetadataPlugin.string(), false);
- ASSERT_TRUE(!!factory.CreatePluginByPluginInfo(metadata_info));
- PluginInfo tag_info2("tag", "test", kTestTagPlugin.string(), true);
- ASSERT_TRUE(!!factory.CreatePluginByPluginInfo(tag_info2));
- PluginInfo category_info2("category", "category",
- kTestCategoryPlugin.string(), true);
- ASSERT_TRUE(!!factory.CreatePluginByPluginInfo(category_info2));
- PluginInfo metadata_info2("metadata", "metadata",
- kTestMetadataPlugin.string(), true);
- ASSERT_TRUE(!!factory.CreatePluginByPluginInfo(metadata_info2));
- PluginInfo missing_info("tag", "test",
- "/usr/lib/libmynonexistingplugin.so", false);
- ASSERT_FALSE(!!factory.CreatePluginByPluginInfo(missing_info));
- PluginInfo new_info("newtype", "test", kTestTagPlugin.string(), false);
- ASSERT_FALSE(!!factory.CreatePluginByPluginInfo(new_info));
-}
-
-#define CALLING_PLUGIN_FOR_ACTION_TEST(NAME, ACTION) \
- TEST_F(PluginTest, PluginManager_CallingPlugins ## NAME) { \
- TestAssessor::Instance().ClearResults(); \
- \
- bf::path manifest = bf::path(kPluginsTestFiles) / "tizen-manifest.xml"; \
- bf::path list = kTestValidPluginsListDir; \
- \
- InstallerContext context; \
- context.unpacked_dir_path.set(manifest.parent_path()); \
- configuration::StepParseManifest step(&context, \
- configuration::StepParseManifest::ManifestLocation::PACKAGE, \
- configuration::StepParseManifest::StoreLocation::NORMAL); \
- ASSERT_EQ(step.process(), Step::Status::OK); \
- PluginManager manager(manifest, list, context.pkgid.get(), \
- context.manifest_data.get(), getuid()); \
- ASSERT_TRUE(manager.LoadPlugins(ACTION)); \
- manager.RunPlugins(ACTION); \
- auto result = TestAssessor::Instance().GetResults(); \
- ASSERT_EQ(result.size(), 5); \
- CheckCall(result, kTagPluginName, ACTION); \
- CheckCallMain(result, kMetadataPluginName, ACTION); \
- CheckCallMain(result, kCategoryPluginName, ACTION); \
- }
-
-CALLING_PLUGIN_FOR_ACTION_TEST(Install, Plugin::ActionType::Install)
-CALLING_PLUGIN_FOR_ACTION_TEST(Upgrade, Plugin::ActionType::Upgrade)
-CALLING_PLUGIN_FOR_ACTION_TEST(Uninstall, Plugin::ActionType::Uninstall)
-
-#define CALLING_PLUGIN_FOR_FAIL_ACTION_TEST(NAME, ACTION) \
- TEST_F(PluginTest, PluginManager_CallingFailPlugins ## NAME) { \
- std::string kind_of_plugins[3] = {"category", "metadata", "tag"}; \
- for (auto name : kind_of_plugins) { \
- std::string manifest_dir = name + "-manifest"; \
- bf::path manifest = \
- bf::path(kPluginsTestFiles) / manifest_dir / "tizen-manifest.xml"; \
- bf::path list = kTestValidFailPluginsListDir; \
- \
- InstallerContext context; \
- context.unpacked_dir_path.set(manifest.parent_path()); \
- configuration::StepParseManifest step(&context, \
- configuration::StepParseManifest::ManifestLocation::PACKAGE, \
- configuration::StepParseManifest::StoreLocation::NORMAL); \
- ASSERT_EQ(step.process(), Step::Status::OK); \
- PluginManager manager(manifest, list, context.pkgid.get(), \
- context.manifest_data.get(), getuid()); \
- ASSERT_TRUE(manager.LoadPlugins(ACTION)); \
- ASSERT_FALSE(manager.RunPlugins(ACTION)); \
- } \
- }
-
-CALLING_PLUGIN_FOR_FAIL_ACTION_TEST(Install, Plugin::ActionType::Install)
-CALLING_PLUGIN_FOR_FAIL_ACTION_TEST(Upgrade, Plugin::ActionType::Upgrade)
-CALLING_PLUGIN_FOR_FAIL_ACTION_TEST(Uninstall, Plugin::ActionType::Uninstall)
-
-} // namespace common_installer
+++ /dev/null
-// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
-// Use of this source code is governed by an apache 2.0 license that can be
-// found in the LICENSE file.
-
-#include <boost/filesystem/path.hpp>
-#include <gtest/gtest.h>
-
-#include <memory>
-
-#include "common/certificate_validation.h"
-
-namespace bf = boost::filesystem;
-
-namespace common_installer {
-namespace security {
-
-class SignatureValidatorTest : public testing::Test {
- protected:
- std::unique_ptr<bf::path> signature_file;
-};
-
-// Tests signature verifier with proper signatures
-TEST_F(SignatureValidatorTest, HandlesInitializedSignatureDir) {
- signature_file.reset(new bf::path(
- "/usr/share/app-installers-ut/test_samples/good_signatures"));
- PrivilegeLevel level = PrivilegeLevel::UNTRUSTED;
- common_installer::CertificateInfo cert_info;
- std::string error;
- EXPECT_TRUE(ValidateSignatures(*signature_file, &level, &cert_info, true,
- &error));
-}
-
-// Tests signature verifier with signature directory containing bad signatures
-TEST_F(SignatureValidatorTest, HandlesBadSignatureDir) {
- signature_file.reset(new bf::path(
- "/usr/share/app-installers-ut/test_samples/bad_signatures"));
- PrivilegeLevel level = PrivilegeLevel::UNTRUSTED;
- common_installer::CertificateInfo cert_info;
- std::string error;
- EXPECT_FALSE(ValidateSignatures(*signature_file, &level, &cert_info, true,
- &error));
-}
-
-} // namespace security
-} // namespace common_installer
+++ /dev/null
-<Signature xmlns="http://www.w3.org/2000/09/xmldsig#" Id="AuthorSignature">
-<SignedInfo>
-<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></CanonicalizationMethod>
-<SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"></SignatureMethod>
-<Reference URI="config.xml">
-<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
-<DigestValue>iEX0LuZs81Q6Du/SkXgbMd+Qa6puMxgyRUCLqhrfpJ8=</DigestValue>
-</Reference>
-<Reference URI="icon.png">
-<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
-<DigestValue>1d0oEZHqPn+QzNzGIHwj9ODby6x9ggFs9uOsav6jPNs=</DigestValue>
-</Reference>
-<Reference URI="index.html">
-<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
-<DigestValue>rJOIi81O4OG/Gar/hwrjvD623MpScv6TMdurRZgzDf0=</DigestValue>
-</Reference>
-<Reference URI="version.txt">
-<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
-<DigestValue>MjYb9c/C/J56bHY6rlIjfDqkpjFtsUBjLLkco/rcfFY=</DigestValue>
-</Reference>
-<Reference URI="#prop">
-<Transforms>
-<Transform Algorithm="http://www.w3.org/2006/12/xml-c14n11"></Transform>
-</Transforms>
-<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
-<DigestValue>lpo8tUDs054eLlBQXiDPVDVKfw30ZZdtkRs1jd7H5K8=</DigestValue>
-</Reference>
-</SignedInfo>
-<SignatureValue>
-c7Jd7btw6Bi9MxzKVv6JY9xcegxv42DhOzZhyrjz3EMN/60dhcGJClfKBY39FwH6exMajoThyFIW
-djtnp7pqIiQJCJkGRs0vAQThcm8JniVSbUwHMcMw7WjAW5VPsLQZKmEe16YW00YkoT6KfZLC1ySw
-48WNrHrCrTcj6LZRrld=
-</SignatureValue>
-<KeyInfo>
-<X509Data>
-<X509Certificate>
-MIIC2zCCAcOgAwIBAgIGAUudC0tkMA0GCSqGSIb3DQEBBQUAMFYxGjAYBgNVBAoMEVRpemVuIEFz
-c29jaWF0aW9uMRowGAYDVQQLDBFUaXplbiBBc3NvY2lhdGlvbjEcMBoGA1UEAwwTVGl6ZW4gRGV2
-ZWxvcGVycyBDQTAeFw0xMjExMDEwMDAwMDBaFw0xOTAxMDEwMDAwMDBaMFcxCzAJBgNVBAYTAlBM
-MQ8wDQYDVQQHDAZXYXJzYXcxEDAOBgNVBAoMB1NhbXN1bmcxFDASBgNVBAsMC1dlYlBsYXRmb3Jt
-MQ8wDQYDVQQDDAZhdXRob3IwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM0kQ8aPoKnJaBjk
-3ET7XdOS5C3ueSemfA8tYNihWQ3VX95CKX38ARLpaAGRSfOdo2L1vTIBtaO/UWEEl/XKQzqwem22
-A9UuLwl0rJNDeoq5Xz5oJD1z9eA+uuNde6cAcPmxRQDsilnVZNHlpATdDOeKUSs8+Y5UxPDz1c6j
-kUTpAgMBAAGjMjAwMAwGA1UdEwEB/wQCMAAwCwYDVR0PBAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUF
-BwMDMA0GCSqGSIb3DQEBBQUAA4IBAQC2kGzwMPMgxRrAi3ZaRu+i8x2ApZEWW4Y5uaZ9s7p4483A
-l+RBZ1/zHhkmZaekhCm2YwOpWIkXLiQc2wm9YRq+W1OorrArl/wgxtpO7hajlCxDS3X8GgJqCy7v
-8vQYTBvNXayQaRB496mC9lLZDjRL9ycYnPk55eimL3HEYclbibDjOvks4bdN/fedA8jovir+wA+b
-tIC+GGkiwGco6URdxigydxdpNEwRECCl78YVybf9agKeowXL08kwDZN9DAHCixu76kw1qtpfwm3T
-t/lz7VB1pDFhjzfuG6runH4H257bBYLkJnSBchiNItMuK2zvTVP8HsQmBeOLAFGtsoas
-</X509Certificate>
-<X509Certificate>
-MIIDOTCCAiGgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMRowGAYDVQQKDBFUaXplbiBBc3NvY2lh
-dGlvbjEaMBgGA1UECwwRVGl6ZW4gQXNzb2NpYXRpb24xHjAcBgNVBAMMFVRpemVuIERldmVsb3Bl
-cnMgUm9vdDAeFw0xMjAxMDEwMDAwMDBaFw0yNzAxMDEwMDAwMDBaMFYxGjAYBgNVBAoMEVRpemVu
-IEFzc29jaWF0aW9uMRowGAYDVQQLDBFUaXplbiBBc3NvY2lhdGlvbjEcMBoGA1UEAwwTVGl6ZW4g
-RGV2ZWxvcGVycyBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANVGhRGmMIUyBA7o
-PCz8Sxut6z6HNkF4oDIuzuKaMzRYPeWodwe9O0gmqAkToQHfwg2giRhE5GoPld0fq+OYMMwSasCu
-g8dwODx1eDeSYVuOLWRxpAmbTXOsSFi6VoWeyaPEm18JBHvZBsU5YQtgZ6Kp7MqzvQg3pXOxtajj
-vyHxiatJl+xXrHgcXC1wgyG3buty7u/Fi2mvKXJ0PRJcCjjK81dqe/Vr20sRUCrbk02zbm5ggFt/
-jIEhV8wbFRQpliobc7J4dSTKhFfrqGM8rdd54LYhD7gSI1CFSe16pUXfcVR7FhJztRaiGLnCrwBE
-dyTZ248+D4L/qR/D0axb3jcCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOC
-AQEAnOXXQ/1O/QTDHyrmQDtFziqPY3xWlJBqJtEqXiT7Y+Ljpe66e+Ee/OjQMlZe8gu21/8cKklH
-95RxjopMWCVedXDUbWdvS2+CdyvVW/quT2E0tjqIzXDekUTYwwhlPWlGxvfj3VsxqSFq3p8Brl04
-1Gx5RKAGyKVsMfTLhbbwSWwApuBUxYfcNpKwLWGPXkysu+HctY03OKv4/xKBnVWiN8ex/Sgesi0M
-+OBAOMdZMPK32uJBTeKFx1xZgTLIhk45V0hPOomPjZloiv0LSS11eyd451ufjW0iHRE7WlpR6EvI
-W6TFyZgMpQq+kg4hWl2SBTf3s2VI8Ygz7gj8TMlClg==
-</X509Certificate>
-</X509Data>
-</KeyInfo>
-<Object Id="prop"><SignatureProperties xmlns:dsp="http://www.w3.org/2009/xmldsig-properties"><SignatureProperty Id="profile" Target="#AuthorSignature"><dsp:Profile URI="http://www.w3.org/ns/widgets-digsig#profile"></dsp:Profile></SignatureProperty><SignatureProperty Id="role" Target="#AuthorSignature"><dsp:Role URI="http://www.w3.org/ns/widgets-digsig#role-author"></dsp:Role></SignatureProperty><SignatureProperty Id="identifier" Target="#AuthorSignature"><dsp:Identifier></dsp:Identifier></SignatureProperty></SignatureProperties></Object>
-</Signature>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<widget xmlns="http://www.w3.org/ns/widgets" xmlns:tizen="http://tizen.org/ns/widgets" id="http://yourdomain/AppInstallersTest" version="1.0.0" viewmodes="maximized">
- <tizen:application id="ZK6wgb4nwt.AppInstallersTest" package="ZK6wgb4nwt" required_version="2.3"/>
- <content src="index.html"/>
- <feature name="http://tizen.org/feature/screen.size.all"/>
- <icon src="icon.png"/>
- <name>AppInstallersTest</name>
- <tizen:profile name="mobile"/>
-</widget>
+++ /dev/null
-<!DOCTYPE html>
-<html>
-<head>
- <meta charset="utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
- <meta name="description" content="Tizen basic template generated by Tizen Web IDE"/>
-
- <title>Tizen Web IDE - Tizen - Tizen basic Application</title>
-</head>
-
-<body>
- <header>
- <hgroup>
- <h1>Tizen app</h1>
- <h2>An empty template of tizen</h2>
- </hgroup>
- </header>
-
- <nav>
- <ul>
- <li><a href="#">Home</a></li>
- <li><a href="#">About Us</a></li>
- <li><a href="#">Contact Us</a></li>
- </ul>
- </nav>
-
- <article>
- <p>This is an empty template of Tizen Web Application. Tizen will support multiple device categories:</p>
- <ul>
- <li>smartphones, tablets and smart TVs
- <li>netbooks, in-vehicle infotainment devices
- </ul>
- <section>
- <p>This is a basic section of a document.</p>
- <p>The following button displays a time using JavaScript.</p>
- <div id="divbutton1">
- <button>Clock</button>
- </div>
- </section>
- </article>
-
- <footer>
- <p>© 2012 Company Name. All rights reserved.</p>
- </footer>
-</body>
-</html>
+++ /dev/null
-<Signature xmlns="http://www.w3.org/2000/09/xmldsig#" Id="DistributorSignature">
-<SignedInfo>
-<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></CanonicalizationMethod>
-<SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"></SignatureMethod>
-<Reference URI="author-signature.xml">
-<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
-<DigestValue>opfWp60FUsKzpdQBgTp3x31PB1GzC9mS6M7B6n2m63c=</DigestValue>
-</Reference>
-<Reference URI="config.xml">
-<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
-<DigestValue>iEX0LuZs81Q6Du/SkXgbMd+Qa6puMxgyRUCLqhrfpJ8=</DigestValue>
-</Reference>
-<Reference URI="icon.png">
-<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
-<DigestValue>1d0oEZHqPn+QzNzGIHwj9ODby6x9ggFs9uOsav6jPNs=</DigestValue>
-</Reference>
-<Reference URI="index.html">
-<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
-<DigestValue>rJOIi81O4OG/Gar/hwrjvD623MpScv6TMdurRZgzDf0=</DigestValue>
-</Reference>
-<Reference URI="version.txt">
-<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
-<DigestValue>MjYb9c/C/J56bHY6rlIjfDqkpjFtsUBjLLkco/rcfFY=</DigestValue>
-</Reference>
-<Reference URI="#prop">
-<Transforms>
-<Transform Algorithm="http://www.w3.org/2006/12/xml-c14n11"></Transform>
-</Transforms>
-<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
-<DigestValue>u/jU3U4Zm5ihTMSjKGlGYbWzDfRkGphPPHx3gJIYEJ4=</DigestValue>
-</Reference>
-</SignedInfo>
-<SignatureValue>
-O6yHkXzPKe+8nGxjh06ivDImxKSKygVOgvZzmKKHVWn879K2K8vY08/f7FXKG+zRXEouXbZd7aip
-IGyOCpulXUzESCQMIiffzMVgTV0Ho+kXx44xbME/XKy7DJYpZOvZFXX1S9ZXvU2BmmgHtWWLS/gc
-sFiYVHpRxLnify3npXF=
-</SignatureValue>
-<KeyInfo>
-<X509Data>
-<X509Certificate>
-MIICmzCCAgQCCQDXI7WLdVZwiTANBgkqhkiG9w0BAQUFADCBjzELMAkGA1UEBhMCS1IxDjAMBgNV
-BAgMBVN1d29uMQ4wDAYDVQQHDAVTdXdvbjEWMBQGA1UECgwNVGl6ZW4gVGVzdCBDQTEiMCAGA1UE
-CwwZVGl6ZW4gRGlzdHJpYnV0b3IgVGVzdCBDQTEkMCIGA1UEAwwbVGl6ZW4gUHVibGljIERpc3Ry
-aWJ1dG9yIENBMB4XDTEyMTAyOTEzMDMwNFoXDTIyMTAyNzEzMDMwNFowgZMxCzAJBgNVBAYTAktS
-MQ4wDAYDVQQIDAVTdXdvbjEOMAwGA1UEBwwFU3V3b24xFjAUBgNVBAoMDVRpemVuIFRlc3QgQ0Ex
-IjAgBgNVBAsMGVRpemVuIERpc3RyaWJ1dG9yIFRlc3QgQ0ExKDAmBgNVBAMMH1RpemVuIFB1Ymxp
-YyBEaXN0cmlidXRvciBTaWduZXIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALtMvlc5hENK
-90ZdA+y66+Sy0enD1gpZDBh5T9RP0oRsptJv5jjNTseQbQi0SZOdOXb6J7iQdlBCtR343RpIEz8H
-mrBy7mSY7mgwoU4EPpp4CTSUeAuKcmvrNOngTp5Hv7Ngf02TTHOLK3hZLpGayaDviyNZB5PdqQdB
-hokKjzAzAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAvGp1gxxAIlFfhJH1efjb9BJK/rtRkbYn9+Ez
-GEbEULg1svsgnyWisFimI3uFvgI/swzr1eKVY3Sc8MQ3+Fdy3EkbDZ2+WAubhcEkorTWjzWz2fL1
-vKaYjeIsuEX6TVRUugHWudPzcEuQRLQf8ibZWjbQdBmpeQYBMg5x+xKLCJc=
-</X509Certificate>
-<X509Certificate>
-MIICtDCCAh2gAwIBAgIJAMDbehElPNKvMA0GCSqGSIb3DQEBBQUAMIGVMQswCQYDVQQGEwJLUjEO
-MAwGA1UECAwFU3V3b24xDjAMBgNVBAcMBVN1d29uMRYwFAYDVQQKDA1UaXplbiBUZXN0IENBMSMw
-IQYDVQQLDBpUVGl6ZW4gRGlzdHJpYnV0b3IgVGVzdCBDQTEpMCcGA1UEAwwgVGl6ZW4gUHVibGlj
-IERpc3RyaWJ1dG9yIFJvb3QgQ0EwHhcNMTIxMDI5MTMwMjUwWhcNMjIxMDI3MTMwMjUwWjCBjzEL
-MAkGA1UEBhMCS1IxDjAMBgNVBAgMBVN1d29uMQ4wDAYDVQQHDAVTdXdvbjEWMBQGA1UECgwNVGl6
-ZW4gVGVzdCBDQTEiMCAGA1UECwwZVGl6ZW4gRGlzdHJpYnV0b3IgVGVzdCBDQTEkMCIGA1UEAwwb
-VGl6ZW4gUHVibGljIERpc3RyaWJ1dG9yIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDe
-OTS/3nXvkDEmsFCJIvRlQ3RKDcxdWJJp625pFqHdmoJBdV+x6jl1raGK2Y1sp2Gdvpjc/z92yzAp
-bE/UVLPh/tRNZPeGhzU4ejDDm7kzdr2f7Ia0U98K+OoY12ucwg7TYNItj9is7Cj4blGfuMDzd2ah
-2AgnCGlwNwV/pv+uVQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBACqJ
-KO33YdoGudwanZIxMdXuxnnD9R6u72ltKk1S4zPfMJJv482CRGCI4FK6djhlsI4i0Lt1SVIJEed+
-yc3qckGm19dW+4xdlkekon7pViEBWuyHw8OWv3RXtTum1+PGHjBJ2eYY4ZKIpz73U/1NC16sTB/0
-VhfnkHwPltmrpYVe
-</X509Certificate>
-</X509Data>
-</KeyInfo>
-<Object Id="prop"><SignatureProperties xmlns:dsp="http://www.w3.org/2009/xmldsig-properties"><SignatureProperty Id="profile" Target="#DistributorSignature"><dsp:Profile URI="http://www.w3.org/ns/widgets-digsig#profile"></dsp:Profile></SignatureProperty><SignatureProperty Id="role" Target="#DistributorSignature"><dsp:Role URI="http://www.w3.org/ns/widgets-digsig#role-distributor"></dsp:Role></SignatureProperty><SignatureProperty Id="identifier" Target="#DistributorSignature"><dsp:Identifier></dsp:Identifier></SignatureProperty></SignatureProperties></Object>
-</Signature>
+++ /dev/null
-<Signature xmlns="http://www.w3.org/2000/09/xmldsig#" Id="AuthorSignature">
-<SignedInfo>
-<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></CanonicalizationMethod>
-<SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"></SignatureMethod>
-<Reference URI="config.xml">
-<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
-<DigestValue>iEX0LuZs81Q6Du/SkXgbMd+Qa6puMxgyRUCLqhrfpJ8=</DigestValue>
-</Reference>
-<Reference URI="icon.png">
-<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
-<DigestValue>1d0oEZHqPn+QzNzGIHwj9ODby6x9ggFs9uOsav6jPNs=</DigestValue>
-</Reference>
-<Reference URI="index.html">
-<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
-<DigestValue>rJOIi81O4OG/Gar/hwrjvD623MpScv6TMdurRZgzDf0=</DigestValue>
-</Reference>
-<Reference URI="version.txt">
-<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
-<DigestValue>MjYb9c/C/J56bHY6rlIjfDqkpjFtsUBjLLkco/rcfFY=</DigestValue>
-</Reference>
-<Reference URI="#prop">
-<Transforms>
-<Transform Algorithm="http://www.w3.org/2006/12/xml-c14n11"></Transform>
-</Transforms>
-<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
-<DigestValue>lpo8tUDs054eLlBQXiDPVDVKfw30ZZdtkRs1jd7H5K8=</DigestValue>
-</Reference>
-</SignedInfo>
-<SignatureValue>
-c7Jd7btw6Bi9MxzKVv6JY9xcegxv42DhOzZhyrjz3EMN/60dhcGJClfKBY39FwH6exMajoThyFIW
-djtnp7pqIiQJCJkGRs0vAQThcm8JniVSbUwHMcMw7WjAW5VPsLQZKmEe16YW00YkoT6KfZLC1ySw
-48WNrHrCrTcj6LZRrlc=
-</SignatureValue>
-<KeyInfo>
-<X509Data>
-<X509Certificate>
-MIIC2zCCAcOgAwIBAgIGAUudC0tkMA0GCSqGSIb3DQEBBQUAMFYxGjAYBgNVBAoMEVRpemVuIEFz
-c29jaWF0aW9uMRowGAYDVQQLDBFUaXplbiBBc3NvY2lhdGlvbjEcMBoGA1UEAwwTVGl6ZW4gRGV2
-ZWxvcGVycyBDQTAeFw0xMjExMDEwMDAwMDBaFw0xOTAxMDEwMDAwMDBaMFcxCzAJBgNVBAYTAlBM
-MQ8wDQYDVQQHDAZXYXJzYXcxEDAOBgNVBAoMB1NhbXN1bmcxFDASBgNVBAsMC1dlYlBsYXRmb3Jt
-MQ8wDQYDVQQDDAZhdXRob3IwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM0kQ8aPoKnJaBjk
-3ET7XdOS5C3ueSemfA8tYNihWQ3VX95CKX38ARLpaAGRSfOdo2L1vTIBtaO/UWEEl/XKQzqwem22
-A9UuLwl0rJNDeoq5Xz5oJD1z9eA+uuNde6cAcPmxRQDsilnVZNHlpATdDOeKUSs8+Y5UxPDz1c6j
-kUTpAgMBAAGjMjAwMAwGA1UdEwEB/wQCMAAwCwYDVR0PBAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUF
-BwMDMA0GCSqGSIb3DQEBBQUAA4IBAQC2kGzwMPMgxRrAi3ZaRu+i8x2ApZEWW4Y5uaZ9s7p4483A
-l+RBZ1/zHhkmZaekhCm2YwOpWIkXLiQc2wm9YRq+W1OorrArl/wgxtpO7hajlCxDS3X8GgJqCy7v
-8vQYTBvNXayQaRB496mC9lLZDjRL9ycYnPk55eimL3HEYclbibDjOvks4bdN/fedA8jovir+wA+b
-tIC+GGkiwGco6URdxigydxdpNEwRECCl78YVybf9agKeowXL08kwDZN9DAHCixu76kw1qtpfwm3T
-t/lz7VB1pDFhjzfuG6runH4H257bBYLkJnSBchiNItMuK2zvTVP8HsQmBeOLAFGtsoas
-</X509Certificate>
-<X509Certificate>
-MIIDOTCCAiGgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMRowGAYDVQQKDBFUaXplbiBBc3NvY2lh
-dGlvbjEaMBgGA1UECwwRVGl6ZW4gQXNzb2NpYXRpb24xHjAcBgNVBAMMFVRpemVuIERldmVsb3Bl
-cnMgUm9vdDAeFw0xMjAxMDEwMDAwMDBaFw0yNzAxMDEwMDAwMDBaMFYxGjAYBgNVBAoMEVRpemVu
-IEFzc29jaWF0aW9uMRowGAYDVQQLDBFUaXplbiBBc3NvY2lhdGlvbjEcMBoGA1UEAwwTVGl6ZW4g
-RGV2ZWxvcGVycyBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANVGhRGmMIUyBA7o
-PCz8Sxut6z6HNkF4oDIuzuKaMzRYPeWodwe9O0gmqAkToQHfwg2giRhE5GoPld0fq+OYMMwSasCu
-g8dwODx1eDeSYVuOLWRxpAmbTXOsSFi6VoWeyaPEm18JBHvZBsU5YQtgZ6Kp7MqzvQg3pXOxtajj
-vyHxiatJl+xXrHgcXC1wgyG3buty7u/Fi2mvKXJ0PRJcCjjK81dqe/Vr20sRUCrbk02zbm5ggFt/
-jIEhV8wbFRQpliobc7J4dSTKhFfrqGM8rdd54LYhD7gSI1CFSe16pUXfcVR7FhJztRaiGLnCrwBE
-dyTZ248+D4L/qR/D0axb3jcCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOC
-AQEAnOXXQ/1O/QTDHyrmQDtFziqPY3xWlJBqJtEqXiT7Y+Ljpe66e+Ee/OjQMlZe8gu21/8cKklH
-95RxjopMWCVedXDUbWdvS2+CdyvVW/quT2E0tjqIzXDekUTYwwhlPWlGxvfj3VsxqSFq3p8Brl04
-1Gx5RKAGyKVsMfTLhbbwSWwApuBUxYfcNpKwLWGPXkysu+HctY03OKv4/xKBnVWiN8ex/Sgesi0M
-+OBAOMdZMPK32uJBTeKFx1xZgTLIhk45V0hPOomPjZloiv0LSS11eyd451ufjW0iHRE7WlpR6EvI
-W6TFyZgMpQq+kg4hWl2SBTf3s2VI8Ygz7gj8TMlClg==
-</X509Certificate>
-</X509Data>
-</KeyInfo>
-<Object Id="prop"><SignatureProperties xmlns:dsp="http://www.w3.org/2009/xmldsig-properties"><SignatureProperty Id="profile" Target="#AuthorSignature"><dsp:Profile URI="http://www.w3.org/ns/widgets-digsig#profile"></dsp:Profile></SignatureProperty><SignatureProperty Id="role" Target="#AuthorSignature"><dsp:Role URI="http://www.w3.org/ns/widgets-digsig#role-author"></dsp:Role></SignatureProperty><SignatureProperty Id="identifier" Target="#AuthorSignature"><dsp:Identifier></dsp:Identifier></SignatureProperty></SignatureProperties></Object>
-</Signature>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<widget xmlns="http://www.w3.org/ns/widgets" xmlns:tizen="http://tizen.org/ns/widgets" id="http://yourdomain/AppInstallersTest" version="1.0.0" viewmodes="maximized">
- <tizen:application id="ZK6wgb4nwt.AppInstallersTest" package="ZK6wgb4nwt" required_version="2.3"/>
- <content src="index.html"/>
- <feature name="http://tizen.org/feature/screen.size.all"/>
- <icon src="icon.png"/>
- <name>AppInstallersTest</name>
- <tizen:profile name="mobile"/>
-</widget>
+++ /dev/null
-<!DOCTYPE html>
-<html>
-<head>
- <meta charset="utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
- <meta name="description" content="Tizen basic template generated by Tizen Web IDE"/>
-
- <title>Tizen Web IDE - Tizen - Tizen basic Application</title>
-</head>
-
-<body>
- <header>
- <hgroup>
- <h1>Tizen app</h1>
- <h2>An empty template of tizen</h2>
- </hgroup>
- </header>
-
- <nav>
- <ul>
- <li><a href="#">Home</a></li>
- <li><a href="#">About Us</a></li>
- <li><a href="#">Contact Us</a></li>
- </ul>
- </nav>
-
- <article>
- <p>This is an empty template of Tizen Web Application. Tizen will support multiple device categories:</p>
- <ul>
- <li>smartphones, tablets and smart TVs
- <li>netbooks, in-vehicle infotainment devices
- </ul>
- <section>
- <p>This is a basic section of a document.</p>
- <p>The following button displays a time using JavaScript.</p>
- <div id="divbutton1">
- <button>Clock</button>
- </div>
- </section>
- </article>
-
- <footer>
- <p>© 2012 Company Name. All rights reserved.</p>
- </footer>
-</body>
-</html>
+++ /dev/null
-<Signature xmlns="http://www.w3.org/2000/09/xmldsig#" Id="DistributorSignature">
-<SignedInfo>
-<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></CanonicalizationMethod>
-<SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"></SignatureMethod>
-<Reference URI="author-signature.xml">
-<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
-<DigestValue>opfWp60FUsKzpdQBgTp3x31PB1GzC9mS6M7B6n2m63c=</DigestValue>
-</Reference>
-<Reference URI="config.xml">
-<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
-<DigestValue>iEX0LuZs81Q6Du/SkXgbMd+Qa6puMxgyRUCLqhrfpJ8=</DigestValue>
-</Reference>
-<Reference URI="icon.png">
-<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
-<DigestValue>1d0oEZHqPn+QzNzGIHwj9ODby6x9ggFs9uOsav6jPNs=</DigestValue>
-</Reference>
-<Reference URI="index.html">
-<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
-<DigestValue>rJOIi81O4OG/Gar/hwrjvD623MpScv6TMdurRZgzDf0=</DigestValue>
-</Reference>
-<Reference URI="version.txt">
-<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
-<DigestValue>MjYb9c/C/J56bHY6rlIjfDqkpjFtsUBjLLkco/rcfFY=</DigestValue>
-</Reference>
-<Reference URI="#prop">
-<Transforms>
-<Transform Algorithm="http://www.w3.org/2006/12/xml-c14n11"></Transform>
-</Transforms>
-<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
-<DigestValue>u/jU3U4Zm5ihTMSjKGlGYbWzDfRkGphPPHx3gJIYEJ4=</DigestValue>
-</Reference>
-</SignedInfo>
-<SignatureValue>
-O6yHkXzPKe+8nGxjh06ivDImxKSKygVOgvZzmKKHVWn879K2K8vY08/f7FXKG+zRXEouXbZd7aip
-IGyOCpulXUzESCQMIiffzMVgTV0Ho+kXx44xbME/XKy7DJYpZOvZFXX1S9ZXvU2BmmgHtWWLS/gc
-sFiYVHpRxLnify3npXE=
-</SignatureValue>
-<KeyInfo>
-<X509Data>
-<X509Certificate>
-MIICmzCCAgQCCQDXI7WLdVZwiTANBgkqhkiG9w0BAQUFADCBjzELMAkGA1UEBhMCS1IxDjAMBgNV
-BAgMBVN1d29uMQ4wDAYDVQQHDAVTdXdvbjEWMBQGA1UECgwNVGl6ZW4gVGVzdCBDQTEiMCAGA1UE
-CwwZVGl6ZW4gRGlzdHJpYnV0b3IgVGVzdCBDQTEkMCIGA1UEAwwbVGl6ZW4gUHVibGljIERpc3Ry
-aWJ1dG9yIENBMB4XDTEyMTAyOTEzMDMwNFoXDTIyMTAyNzEzMDMwNFowgZMxCzAJBgNVBAYTAktS
-MQ4wDAYDVQQIDAVTdXdvbjEOMAwGA1UEBwwFU3V3b24xFjAUBgNVBAoMDVRpemVuIFRlc3QgQ0Ex
-IjAgBgNVBAsMGVRpemVuIERpc3RyaWJ1dG9yIFRlc3QgQ0ExKDAmBgNVBAMMH1RpemVuIFB1Ymxp
-YyBEaXN0cmlidXRvciBTaWduZXIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALtMvlc5hENK
-90ZdA+y66+Sy0enD1gpZDBh5T9RP0oRsptJv5jjNTseQbQi0SZOdOXb6J7iQdlBCtR343RpIEz8H
-mrBy7mSY7mgwoU4EPpp4CTSUeAuKcmvrNOngTp5Hv7Ngf02TTHOLK3hZLpGayaDviyNZB5PdqQdB
-hokKjzAzAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAvGp1gxxAIlFfhJH1efjb9BJK/rtRkbYn9+Ez
-GEbEULg1svsgnyWisFimI3uFvgI/swzr1eKVY3Sc8MQ3+Fdy3EkbDZ2+WAubhcEkorTWjzWz2fL1
-vKaYjeIsuEX6TVRUugHWudPzcEuQRLQf8ibZWjbQdBmpeQYBMg5x+xKLCJc=
-</X509Certificate>
-<X509Certificate>
-MIICtDCCAh2gAwIBAgIJAMDbehElPNKvMA0GCSqGSIb3DQEBBQUAMIGVMQswCQYDVQQGEwJLUjEO
-MAwGA1UECAwFU3V3b24xDjAMBgNVBAcMBVN1d29uMRYwFAYDVQQKDA1UaXplbiBUZXN0IENBMSMw
-IQYDVQQLDBpUVGl6ZW4gRGlzdHJpYnV0b3IgVGVzdCBDQTEpMCcGA1UEAwwgVGl6ZW4gUHVibGlj
-IERpc3RyaWJ1dG9yIFJvb3QgQ0EwHhcNMTIxMDI5MTMwMjUwWhcNMjIxMDI3MTMwMjUwWjCBjzEL
-MAkGA1UEBhMCS1IxDjAMBgNVBAgMBVN1d29uMQ4wDAYDVQQHDAVTdXdvbjEWMBQGA1UECgwNVGl6
-ZW4gVGVzdCBDQTEiMCAGA1UECwwZVGl6ZW4gRGlzdHJpYnV0b3IgVGVzdCBDQTEkMCIGA1UEAwwb
-VGl6ZW4gUHVibGljIERpc3RyaWJ1dG9yIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDe
-OTS/3nXvkDEmsFCJIvRlQ3RKDcxdWJJp625pFqHdmoJBdV+x6jl1raGK2Y1sp2Gdvpjc/z92yzAp
-bE/UVLPh/tRNZPeGhzU4ejDDm7kzdr2f7Ia0U98K+OoY12ucwg7TYNItj9is7Cj4blGfuMDzd2ah
-2AgnCGlwNwV/pv+uVQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBACqJ
-KO33YdoGudwanZIxMdXuxnnD9R6u72ltKk1S4zPfMJJv482CRGCI4FK6djhlsI4i0Lt1SVIJEed+
-yc3qckGm19dW+4xdlkekon7pViEBWuyHw8OWv3RXtTum1+PGHjBJ2eYY4ZKIpz73U/1NC16sTB/0
-VhfnkHwPltmrpYVe
-</X509Certificate>
-</X509Data>
-</KeyInfo>
-<Object Id="prop"><SignatureProperties xmlns:dsp="http://www.w3.org/2009/xmldsig-properties"><SignatureProperty Id="profile" Target="#DistributorSignature"><dsp:Profile URI="http://www.w3.org/ns/widgets-digsig#profile"></dsp:Profile></SignatureProperty><SignatureProperty Id="role" Target="#DistributorSignature"><dsp:Role URI="http://www.w3.org/ns/widgets-digsig#role-distributor"></dsp:Role></SignatureProperty><SignatureProperty Id="identifier" Target="#DistributorSignature"><dsp:Identifier></dsp:Identifier></SignatureProperty></SignatureProperties></Object>
-</Signature>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<manifest xmlns="http://tizen.org/ns/packages" api-version="2.3" package="org.tizen.testapp" version="1.0.0">
- <author email="tester@samsung.com" href="www.tizen.org">tester</author>
- <description>This is default description</description>
- <description xml:lang="en-us">This is test description</description>
- <ui-application appid="org.tizen.testapp.main" exec="testapp" multiple="false" nodisplay="false" taskmanage="true" type="capp">
- <label>testapp</label>
- <label xml:lang="en-us">Test</label>
- <icon>testapp.png</icon>
- <app-control>
- <mime name="EditMime"/>
- <operation name="http://tizen.org/appcontrol/operation/edit"/>
- <uri name="EditUri"/>
- </app-control>
- <app-control>
- <operation name="http://tizen.org/appcontrol/operation/view"/>
- <uri name="ViewUri"/>
- <mime name="ViewMime"/>
- </app-control>
- <datacontrol access="ReadOnly" providerid="http://testapp.com/datacontrol/provider/testapp" type="Sql"/>
- <datacontrol access="ReadOnly" providerid="http://testapp.com/datacontrol/provider/testapp" type="Map"/>
- <category name="http://tizen.org/category/test_category" />
- <category name="http://tizen.org/category/test_category/value_a" />
- <category name="http://tizen.org/category/test_category/value_b" />
- </ui-application>
-</manifest>
+++ /dev/null
-type="tag";name="test";path="/usr/share/app-installers-ut/test_samples/plugins/libtest-tag-plugin.so"
-type="category";;;;;;name="http://tizen.org/category/test_category";path="/usr/share/app-installers-ut/test_samples/plugins/libtest-category-plugin.so"
-type="metadata";name="http://developer.samsung.com/tizen/metadata/test_metadata";path="/usr/share/app-installers-ut/test_samples/plugins/libtest-metadata-plugin.so"
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<manifest xmlns="http://tizen.org/ns/packages" api-version="2.3" package="org.tizen.testapp" version="1.0.0">
- <broken_xml
-</manifest>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<manifest xmlns="http://tizen.org/ns/packages" api-version="2.3" package="org.tizen.testapp" version="1.0.0">
- <author email="tester@samsung.com" href="www.tizen.org">tester</author>
- <description>This is default description</description>
- <description xml:lang="en-us">This is test description</description>
- <ui-application appid="org.tizen.testapp.main" exec="testapp" multiple="false" nodisplay="false" taskmanage="true" type="capp">
- <label>testapp</label>
- <label xml:lang="en-us">Test</label>
- <icon>testapp.png</icon>
- <app-control>
- <mime name="EditMime"/>
- <operation name="http://tizen.org/appcontrol/operation/edit"/>
- <uri name="EditUri"/>
- </app-control>
- <app-control>
- <operation name="http://tizen.org/appcontrol/operation/view"/>
- <uri name="ViewUri"/>
- <mime name="ViewMime"/>
- </app-control>
- <metadata key="metakey1" value="metaval1"/>
- <metadata key="metakey2" value="metaval2"/>
- <metadata key="http://developer.samsung.com/tizen/metadata/test_metadata/key_a" value="value_a"/>
- <metadata key="http://developer.samsung.com/tizen/metadata/test_metadata/key_b" value="value_b"/>
- <metadata key="http://developer.samsung.com/tizen/metadata/test_metadata/key_c" value="value_c"/>
- <datacontrol access="ReadOnly" providerid="http://testapp.com/datacontrol/provider/testapp" type="Sql"/>
- <datacontrol access="ReadOnly" providerid="http://testapp.com/datacontrol/provider/testapp" type="Map"/>
- </ui-application>
-</manifest>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<manifest xmlns="http://tizen.org/ns/packages" api-version="2.3" package="org.tizen.testapp" version="1.0.0">
- <author email="tester@samsung.com" href="www.tizen.org">tester</author>
- <description>This is default description</description>
- <description xml:lang="en-us">This is test description</description>
- <ui-application appid="org.tizen.testapp.main" exec="testapp" multiple="false" nodisplay="false" taskmanage="true" type="capp">
- <label>testapp</label>
- <label xml:lang="en-us">Test</label>
- <icon>testapp.png</icon>
- <app-control>
- <mime name="EditMime"/>
- <operation name="http://tizen.org/appcontrol/operation/edit"/>
- <uri name="EditUri"/>
- </app-control>
- <app-control>
- <operation name="http://tizen.org/appcontrol/operation/view"/>
- <uri name="ViewUri"/>
- <mime name="ViewMime"/>
- </app-control>
- <datacontrol access="ReadOnly" providerid="http://testapp.com/datacontrol/provider/testapp" type="Sql"/>
- <datacontrol access="ReadOnly" providerid="http://testapp.com/datacontrol/provider/testapp" type="Map"/>
- </ui-application>
- <test>
- </test>
-</manifest>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<manifest xmlns="http://tizen.org/ns/packages" api-version="2.3" package="org.tizen.testapp" version="1.0.0">
- <author email="tester@samsung.com" href="www.tizen.org">tester</author>
- <description>This is default description</description>
- <description xml:lang="en-us">This is test description</description>
- <ui-application appid="org.tizen.testapp.main" exec="testapp" multiple="false" nodisplay="false" taskmanage="true" type="capp">
- <label>testapp</label>
- <label xml:lang="en-us">Test</label>
- <icon>testapp.png</icon>
- <app-control>
- <mime name="EditMime"/>
- <operation name="http://tizen.org/appcontrol/operation/edit"/>
- <uri name="EditUri"/>
- </app-control>
- <app-control>
- <operation name="http://tizen.org/appcontrol/operation/view"/>
- <uri name="ViewUri"/>
- <mime name="ViewMime"/>
- </app-control>
- <metadata key="metakey1" value="metaval1"/>
- <metadata key="metakey2" value="metaval2"/>
- <metadata key="http://developer.samsung.com/tizen/metadata/test_metadata/key_a" value="value_a"/>
- <metadata key="http://developer.samsung.com/tizen/metadata/test_metadata/key_b" value="value_b"/>
- <metadata key="http://developer.samsung.com/tizen/metadata/test_metadata/key_c" value="value_c"/>
- <datacontrol access="ReadOnly" providerid="http://testapp.com/datacontrol/provider/testapp" type="Sql"/>
- <datacontrol access="ReadOnly" providerid="http://testapp.com/datacontrol/provider/testapp" type="Map"/>
- <category name="http://tizen.org/category/test_category" />
- <category name="http://tizen.org/category/test_category/value_a" />
- <category name="http://tizen.org/category/test_category/value_b" />
- </ui-application>
- <test>
- </test>
-</manifest>
+++ /dev/null
-type="metadata";name="http://developer.samsung.com/tizen/metadata/test_metadata";path="/usr/share/app-installers-ut/test_samples/plugins/libtest-metadata-fail-plugin.so";vitalness="true"\r
+++ /dev/null
-type="tag";name="test";path="/usr/share/app-installers-ut/test_samples/plugins/libtest-tag-fail-plugin.so";vitalness="true"
-type="category";name="http://tizen.org/category/test_category";path="/usr/share/app-installers-ut/test_samples/plugins/libtest-category-fail-plugin.so";vitalness="true"
+++ /dev/null
-type="metadata";name="http://developer.samsung.com/tizen/metadata/test_metadata";path="/usr/share/app-installers-ut/test_samples/plugins/libtest-metadata-plugin.so"
+++ /dev/null
-type="tag";name="test";path="/usr/share/app-installers-ut/test_samples/plugins/libtest-tag-plugin.so"
-type="category";name="http://tizen.org/category/test_category";path="/usr/share/app-installers-ut/test_samples/plugins/libtest-category-plugin.so"
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<manifest xmlns="http://tizen.org/ns/packages" api-version="2.3" package="org.tizen.testapp" version="1.0.0">
- <author email="tester@samsung.com" href="www.tizen.org">tester</author>
- <description>This is default description</description>
- <description xml:lang="en-us">This is test description</description>
- <ui-application appid="org.tizen.testapp" exec="testapp" multiple="false" nodisplay="false" taskmanage="true" type="capp">
- <label>testapp</label>
- <label xml:lang="en-us">Test</label>
- <icon>testapp.png</icon>
- <app-control>
- <mime name="EditMime"/>
- <operation name="http://tizen.org/appcontrol/operation/edit"/>
- <uri name="EditUri"/>
- </app-control>
- <app-control>
- <operation name="http://tizen.org/appcontrol/operation/view"/>
- <uri name="ViewUri"/>
- <mime name="ViewMime"/>
- </app-control>
- <metadata key="metakey1" value="metaval1"/>
- <metadata key="metakey2" value="metaval2"/>
- <datacontrol access="ReadOnly" providerid="http://testapp.com/datacontrol/provider/testapp" type="Sql"/>
- <datacontrol access="ReadOnly" providerid="http://testapp.com/datacontrol/provider/testapp" type="Map"/>
- </ui-application>
- <account>
- <account-provider appid="org.tizen.testapp" multiple-accounts-support="false" providerid="com.samsung">
- <icon section="account">testapp.png</icon>
- <icon section="account-small">testapp.png</icon>
- <label xml:lang="en-gb">account icon</label>
- <label>Samsung</label>
- <capability>http://tizen.org/account/capability/calendar</capability>
- <capability>http://tizen.org/account/capability/photo</capability>
- </account-provider>
- </account>
- <privileges>
- <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
- <privilege>http://tizen.org/privilege/packagemanager.info</privilege>
- </privileges>
- <feature name="http://tizen.org/feature/camera.front.flash">true</feature>
- <feature name="http://tizen.org/feature/camera">true</feature>
- <feature name="http://tizen.org/feature/camera.back.flash">true</feature>
- <feature name="http://tizen.org/feature/camera.front">true</feature>
-</manifest>
--- /dev/null
+ADD_SUBDIRECTORY(smoke_tests)
--- /dev/null
+SET(DESTINATION_DIR app-installers-ut)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../)
+
+SET(TARGET_ASSESSOR_LIB "test-assessor-lib")
+SET(TARGET_TEST_TAG_PLUGIN "test-tag-plugin")
+SET(TARGET_TEST_CATEGORY_PLUGIN "test-category-plugin")
+SET(TARGET_TEST_METADATA_PLUGIN "test-metadata-plugin")
+SET(TARGET_TEST_TAG_FAIL_PLUGIN "test-tag-fail-plugin")
+SET(TARGET_TEST_CATEGORY_FAIL_PLUGIN "test-category-fail-plugin")
+SET(TARGET_TEST_METADATA_FAIL_PLUGIN "test-metadata-fail-plugin")
+
+SET(TARGET_PLUGINS_TEST "plugins_smoketest")
+SET(TARGET_SIGNATURE_TEST "signature_smoketest")
+
+# Executables
+ADD_EXECUTABLE(${TARGET_SIGNATURE_TEST}
+ signature_smoketest.cc
+)
+
+ADD_EXECUTABLE(${TARGET_PLUGINS_TEST}
+ plugins_smoketest.cc
+)
+
+INSTALL(DIRECTORY test_samples/ DESTINATION ${SHAREDIR}/${DESTINATION_DIR}/test_samples)
+
+APPLY_PKG_CONFIG(${TARGET_SIGNATURE_TEST} PUBLIC
+ Boost
+ GTEST
+)
+
+APPLY_PKG_CONFIG(${TARGET_PLUGINS_TEST} PUBLIC
+ Boost
+ GTEST
+)
+
+# FindGTest module do not sets all needed libraries in GTEST_LIBRARIES and
+# GTest main libraries is still missing, so additional linking of
+# GTEST_MAIN_LIBRARIES is needed.
+TARGET_LINK_LIBRARIES(${TARGET_SIGNATURE_TEST} PUBLIC
+ ${TARGET_LIBNAME_COMMON}
+ ${GTEST_MAIN_LIBRARIES}
+ pthread
+)
+TARGET_LINK_LIBRARIES(${TARGET_PLUGINS_TEST} PUBLIC
+ ${TARGET_LIBNAME_COMMON}
+ ${TPK_MANIFEST_HANDLERS_DEPS}
+ ${GTEST_MAIN_LIBRARIES}
+ ${TARGET_ASSESSOR_LIB}
+ pthread
+)
+
+INSTALL(TARGETS ${TARGET_SIGNATURE_TEST} DESTINATION ${BINDIR}/${DESTINATION_DIR})
+INSTALL(TARGETS ${TARGET_PLUGINS_TEST} DESTINATION ${BINDIR}/${DESTINATION_DIR})
+
+ADD_SUBDIRECTORY(libs)
+ADD_SUBDIRECTORY(common)
--- /dev/null
+ADD_LIBRARY(${TARGET_SMOKE_UTILS} SHARED
+ smoke_utils.cc
+)
+
+APPLY_PKG_CONFIG(${TARGET_SMOKE_UTILS} PUBLIC
+ Boost
+ GTEST
+ GUM_DEPS
+)
+
+TARGET_LINK_LIBRARIES(${TARGET_SMOKE_UTILS} PRIVATE
+ ${TARGET_LIBNAME_COMMON}
+)
+
+INSTALL(TARGETS ${TARGET_SMOKE_UTILS} DESTINATION ${LIB_INSTALL_DIR})
+INSTALL(FILES smoke_utils.h DESTINATION ${INCLUDEDIR}/app-installers/smoke_tests/common/)
--- /dev/null
+// 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 "smoke_tests/common/smoke_utils.h"
+
+#include <gum/gum-user.h>
+#include <gum/gum-user-service.h>
+#include <gum/common/gum-user-types.h>
+#include <manifest_parser/utils/version_number.h>
+#include <sys/smack.h>
+#include <vconf.h>
+#include <vconf-internal-keys.h>
+
+#include <boost/filesystem/path.hpp>
+#include <gtest/gtest.h>
+
+#include <common/installer/app_installer.h>
+#include <common/utils/paths.h>
+#include <common/pkgmgr_interface.h>
+#include <common/utils/pkgmgr_query.h>
+#include <common/tzip_interface.h>
+
+#include <list>
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace bf = boost::filesystem;
+namespace bs = boost::system;
+namespace ci = common_installer;
+namespace bo = boost::program_options;
+
+namespace {
+
+const uid_t kDefaultUserUid = tzplatform_getuid(TZ_SYS_DEFAULT_USER);
+const gid_t kDefaultUserGid = tzplatform_getgid(TZ_SYS_DEFAULT_USER);
+const char kNormalUserName[] = "smokeuser";
+const char kSystemShareGroupName[] = "system_share";
+const char kMigrateTestDBName[] = "app2sd_migrate.db";
+// common entries
+const std::vector<std::string> kDBEntries = {
+ {".pkgmgr_parser.db"},
+ {".pkgmgr_parser.db-journal"},
+ {".pkgmgr_cert.db"},
+ {".pkgmgr_cert.db-journal"},
+ {".app2sd.db"},
+ {".app2sd.db-journal"},
+};
+// globaluser entries
+const char kGlobalManifestDir[] = "/opt/share/packages";
+const char kSkelDir[] = "/etc/skel/apps_rw";
+const char kPreloadApps[] = "/usr/apps";
+const char kPreloadManifestDir[] = "/usr/share/packages";
+const char kPreloadIcons[] = "/usr/share/icons";
+const char kData[] = "data";
+const char kShared[] = ".shared";
+const char kSharedTmp[] = ".shared_tmp";
+
+enum RWDirectory {
+ DATA,
+ CACHE,
+ SHARED_CACHE,
+ SHARED_DATA,
+ SHARED_TRUSTED
+};
+
+const char* rwDirectories[] = {
+ "data",
+ "cache",
+ "shared/cache",
+ "shared/data",
+ "shared/trusted",
+};
+
+} // namespace
+
+namespace smoke_test {
+
+const char kLegacyExtImageDir[] = "legacy_extimage_dir";
+const std::string& kDefaultUserIdStr = std::to_string(kDefaultUserUid);
+const uid_t kGlobalUserUid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
+const uid_t kGlobalUserGid = tzplatform_getgid(TZ_SYS_GLOBALAPP_USER);
+extern const bf::path kSdkDirectory = "/home/owner/share/tmp/sdk_tools";
+
+ci::RequestMode ParseRequestMode(int argc, char** argv) {
+ bo::options_description desc("Available options");
+ desc.add_options()
+ ("request-mode", bo::value<std::string>(), "set request mode")
+ ("global-request,g", "set request mode to global")
+ ("user-request,u", "set request mode to user");
+
+ bo::variables_map vm;
+ bo::store(bo::command_line_parser(argc, argv).
+ options(desc).allow_unregistered().run(), vm);
+ bo::notify(vm);
+
+ if (vm.count("global-request")) {
+ std::cout << "Request mode was set to global." << std::endl;
+ return ci::RequestMode::GLOBAL;
+ }
+ if (vm.count("user-request")) {
+ std::cout << "Request mode was set to user." << std::endl;
+ return ci::RequestMode::USER;
+ }
+ if (vm.count("request-mode")) {
+ if (vm["request-mode"].as<std::string>() == "global") {
+ std::cout << "Request mode was set to global." << std::endl;
+ return ci::RequestMode::GLOBAL;
+ }
+ if (vm["request-mode"].as<std::string>() == "user") {
+ std::cout << "Request mode was set to user." << std::endl;
+ return ci::RequestMode::USER;
+ }
+ std::cout << "Cannot set request mode to "
+ << vm["request-mode"].as<std::string>() << std::endl;
+ }
+ std::cout << "Request mode was set to global." << std::endl;
+ return ci::RequestMode::GLOBAL;
+}
+
+static 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;
+}
+
+static 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(User* test_user) {
+ std::cout << "Adding test user: " << kNormalUserName << std::endl;
+ AddUser(kNormalUserName);
+ if (boost::optional<uid_t> uid = ci::GetUidByUserName(kNormalUserName)) {
+ test_user->uid = *uid;
+ std::cout << "User created properly: uid=" << *uid;
+ if (boost::optional<gid_t> gid = ci::GetGidByUid(*uid)) {
+ test_user->gid = *gid;
+ std::cout << " gid=" << *gid;
+ }
+ std::cout << std::endl;
+ return true;
+ }
+ LOG(ERROR) << "Adding test user failed";
+ return false;
+}
+
+bool DeleteTestUser() {
+ std::cout << "Deleting test user: " << kNormalUserName << std::endl;
+ uid_t test_uid;
+ if (boost::optional<uid_t> uid = ci::GetUidByUserName(kNormalUserName))
+ test_uid = *uid;
+ else
+ return false;
+ DeleteUser(kNormalUserName, true);
+ if (!ci::GetUidByUserName(kNormalUserName)) {
+ std::cout << "User deleted properly: user_name=" << kNormalUserName
+ << " uid=" << test_uid << std::endl;
+ return true;
+ }
+ LOG(ERROR) << "Deleting test user failed";
+ return false;
+}
+
+bool TouchFile(const bf::path& path) {
+ FILE* f = fopen(path.c_str(), "w+");
+ if (!f)
+ return false;
+ fclose(f);
+ return true;
+}
+
+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 RemoveAllRecoveryFiles(const std::string& prefix, uid_t uid) {
+ bf::path root_path = ci::GetRootAppPath(false, uid);
+ 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(prefix) != std::string::npos) {
+ bs::error_code error;
+ bf::remove(dir_entry.path(), error);
+ if (error)
+ LOG(ERROR) << "Failed to remove " << dir_entry.path()
+ << ": " << error.message();
+ }
+ }
+ }
+}
+
+bf::path FindRecoveryFile(const std::string& prefix, uid_t uid) {
+ bf::path root_path = ci::GetRootAppPath(false, uid);
+ 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(prefix) != std::string::npos) {
+ return dir_entry.path();
+ }
+ }
+ }
+ return {};
+}
+
+std::unique_ptr<ci::recovery::RecoveryFile> GetRecoverFileInfo(
+ const bf::path& recovery_file_path) {
+ return ci::recovery::RecoveryFile::OpenRecoveryFile(recovery_file_path);
+}
+
+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,
+ const TestParameters& params) {
+ bf::path file_path = ci::GetRootAppPath(params.is_readonly,
+ params.test_user.uid);
+ 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<char, 200> buffer;
+ while (fgets(buffer.data(), buffer.size(), handle)) {
+ content += buffer.data();
+ }
+ fclose(handle);
+ return content == expected;
+}
+
+static 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];
+
+ 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<gid_t> system_share =
+ ci::GetGidByGroupName(kSystemShareGroupName);
+ 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);
+ EXTENDED_ASSERT_EQ(uid, stats.st_uid);
+ EXTENDED_ASSERT_EQ(*system_share, stats.st_gid);
+ }
+
+ stat(cache_path.c_str(), &stats);
+ EXTENDED_ASSERT_EQ(uid, stats.st_uid);
+ EXTENDED_ASSERT_EQ(*system_share, stats.st_gid);
+ return true;
+}
+
+static bool ValidatePackageFS(const std::string& pkgid, const Apps& apps,
+ const TestParameters& params) {
+ bf::path root_path = ci::GetRootAppPath(params.is_readonly,
+ params.test_user.uid);
+ bf::path package_path = root_path / pkgid;
+ bf::path shared_path = package_path / "shared";
+ 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(params.test_user.uid,
+ params.is_readonly)) / (pkgid + ".xml");
+ EXTENDED_ASSERT_TRUE(bf::exists(manifest_path));
+
+ for (auto& app : apps) {
+ const std::string &exec = app.second;
+ bf::path binary_path = package_path / "bin" / exec;
+ EXTENDED_ASSERT_TRUE(bf::exists(binary_path));
+ }
+
+ if (params.pkg_type == PackageType::WGT ||
+ params.pkg_type == PackageType::HYBRID) {
+ bf::path widget_root_path = package_path / "res" / "wgt";
+ bf::path config_path = widget_root_path / "config.xml";
+ EXTENDED_ASSERT_TRUE(bf::exists(widget_root_path));
+ EXTENDED_ASSERT_TRUE(bf::exists(config_path));
+
+ bf::path private_tmp_path = package_path / "tmp";
+ 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);
+ 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) {
+ 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);
+ EXTENDED_ASSERT_EQ(params.test_user.uid, stats.st_uid);
+ EXTENDED_ASSERT_EQ(params.test_user.gid, stats.st_gid);
+ }
+ return true;
+}
+
+bool ValidatePackage(const std::string& pkgid, const Apps& apps,
+ const TestParameters& params) {
+ ci::PkgQueryInterface pkg_query(pkgid, params.test_user.uid, true);
+ EXTENDED_ASSERT_TRUE(pkg_query.IsPackageInstalled(
+ ci::GetRequestMode(params.test_user.uid)));
+ EXTENDED_ASSERT_TRUE(ValidatePackageFS(pkgid, apps, params));
+ if (params.test_user.uid == kGlobalUserUid) {
+ ci::UserList list = ci::GetUserList();
+ for (auto& l : list)
+ EXTENDED_ASSERT_TRUE(ValidatePackageRWFS(pkgid, std::get<0>(l)));
+ } else {
+ EXTENDED_ASSERT_TRUE(ValidatePackageRWFS(pkgid, params.test_user.uid));
+ }
+ return true;
+}
+
+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));
+ 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);
+ EXTENDED_ASSERT_TRUE(bf::exists(pkg_path / "data" / "file1.txt"));
+ EXTENDED_ASSERT_TRUE(bf::exists(pkg_path / "data" / "file2.txt"));
+ }
+ return true;
+}
+
+static bool ValidateExternalPackageFS(const std::string& pkgid,
+ const Apps& apps, const TestParameters& params) {
+ EXTENDED_ASSERT_EQ(app2ext_usr_enable_external_pkg(pkgid.c_str(),
+ params.test_user.uid), 0);
+ bf::path root_path = ci::GetRootAppPath(false, params.test_user.uid);
+ if (params.pkg_type == PackageType::TPK) {
+ EXTENDED_ASSERT_TRUE(bf::exists(root_path / pkgid / ".mmc" / "bin"));
+ EXTENDED_ASSERT_TRUE(bf::exists(root_path / pkgid / ".mmc" / "lib"));
+ }
+ EXTENDED_ASSERT_TRUE(bf::exists(root_path / pkgid / ".mmc" / "res"));
+ EXTENDED_ASSERT_TRUE(ValidatePackageFS(pkgid, apps, params));
+ EXTENDED_ASSERT_EQ(app2ext_usr_disable_external_pkg(pkgid.c_str(),
+ params.test_user.uid), 0);
+ return true;
+}
+
+bool ValidateExternalPackage(const std::string& pkgid, const Apps& apps,
+ const TestParameters& params) {
+ ci::PkgQueryInterface pkg_query(pkgid, params.test_user.uid, true);
+ std::string storage = pkg_query.StorageForPkgId();
+ bf::path ext_mount_path = ci::GetExternalCardPath();
+ if (bf::is_empty(ext_mount_path)) {
+ LOG(INFO) << "Sdcard not exists!";
+ EXTENDED_ASSERT_EQ(storage, "installed_internal");
+ } else {
+ EXTENDED_ASSERT_EQ(storage, "installed_external");
+ }
+ EXTENDED_ASSERT_TRUE(ValidateExternalPackageFS(pkgid, apps, params));
+ return true;
+}
+
+bool ValidateExtendedPackage(const std::string& pkgid, const Apps& apps,
+ const TestParameters& params) {
+ ci::PkgQueryInterface pkg_query(pkgid, params.test_user.uid, true);
+ std::string storage = pkg_query.StorageForPkgId();
+ bf::path extended_path =
+ bf::path(ci::GetExtendedRootAppPath(params.test_user.uid)) / pkgid;
+ if (!bf::exists(extended_path)) {
+ LOG(INFO) << "Extended storage not exists!";
+ EXTENDED_ASSERT_EQ(storage, "installed_internal");
+ } else {
+ EXTENDED_ASSERT_EQ(storage, "installed_extended");
+ }
+ EXTENDED_ASSERT_TRUE(ValidatePackage(pkgid, apps, params));
+ return true;
+}
+
+static bool PackageCheckCleanup(const std::string& pkgid,
+ const TestParameters& params) {
+ bf::path root_path = ci::GetRootAppPath(params.is_readonly,
+ params.test_user.uid);
+ bf::path package_path = root_path / pkgid;
+ EXTENDED_ASSERT_FALSE(bf::exists(package_path));
+
+ bf::path manifest_path = bf::path(getUserManifestPath(params.test_user.uid,
+ params.is_readonly)) / (pkgid + ".xml");
+ EXTENDED_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);
+ EXTENDED_ASSERT_FALSE(bf::exists(package_backup));
+ EXTENDED_ASSERT_FALSE(bf::exists(manifest_backup));
+ return true;
+}
+
+bool CheckPackageNonExistance(const std::string& pkgid,
+ const TestParameters& params) {
+ ci::PkgQueryInterface pkg_query(pkgid, params.test_user.uid, true);
+ EXTENDED_ASSERT_FALSE(pkg_query.IsPackageInstalled(
+ ci::GetRequestMode(params.test_user.uid)));
+ EXTENDED_ASSERT_TRUE(PackageCheckCleanup(pkgid, params));
+ if (params.test_user.uid == kGlobalUserUid) {
+ bf::path skel_path(kSkelDir);
+ EXTENDED_ASSERT_FALSE(bf::exists(skel_path / pkgid));
+ EXTENDED_ASSERT_FALSE(bf::exists(skel_path / kShared / pkgid));
+ EXTENDED_ASSERT_FALSE(bf::exists(skel_path / kSharedTmp / pkgid));
+ ci::UserList list = ci::GetUserList();
+ for (auto& l : list) {
+ bf::path root_path = ci::GetRootAppPath(false, std::get<0>(l));
+ EXTENDED_ASSERT_FALSE(bf::exists(root_path / kShared / pkgid));
+ EXTENDED_ASSERT_FALSE(bf::exists(root_path / kSharedTmp / pkgid));
+ bf::path package_path = root_path / pkgid;
+ EXTENDED_ASSERT_FALSE(bf::exists(package_path));
+ }
+ }
+ return true;
+}
+
+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;
+}
+
+bool CheckAvailableExtendedPath() {
+ bf::path extended_path = bf::path(tzplatform_getenv(TZ_SYS_EXTENDEDSD));
+ LOG(DEBUG) << "extended_path :" << extended_path;
+ // TODO(jeremy.jang): It should be checked by libstorage API.
+ if (!bf::exists(extended_path)) {
+ LOG(ERROR) << "Extended storage not exists!";
+ return false;
+ }
+ return true;
+}
+
+bool CheckPackageReadonlyNonExistance(const std::string& pkgid,
+ const TestParameters& params) {
+ ci::PkgQueryInterface pkg_query(pkgid, params.test_user.uid, true);
+ EXTENDED_ASSERT_FALSE(pkg_query.IsPackageInstalled(
+ ci::GetRequestMode(params.test_user.uid)));
+ EXTENDED_ASSERT_TRUE(PackageCheckCleanup(pkgid, params));
+ return true;
+}
+
+static bool CheckSharedDataExistanceForPath(const bf::path& apps_rw,
+ const std::string& pkgid) {
+ bf::path shared_data_path = apps_rw / pkgid / rwDirectories[SHARED_DATA];
+ bf::path shared = apps_rw / kShared / pkgid / kData;
+ bf::path shared_tmp = apps_rw / kSharedTmp / pkgid;
+ EXTENDED_ASSERT_TRUE(bf::exists(shared_data_path));
+ EXTENDED_ASSERT_TRUE(bf::exists(shared));
+ EXTENDED_ASSERT_TRUE(bf::exists(shared_tmp));
+ return true;
+}
+
+static bool CheckSharedDataPermissions(const bf::path& apps_rw,
+ const std::string& pkgid, uid_t uid) {
+ bf::path shared_data_path = apps_rw / pkgid / rwDirectories[SHARED_DATA];
+ bf::path shared = apps_rw / kShared / pkgid / kData;
+ bf::path shared_tmp = apps_rw / kSharedTmp / pkgid;
+ // gid of RW dirs should be system_share
+ boost::optional<gid_t> system_share =
+ ci::GetGidByGroupName(kSystemShareGroupName);
+ struct stat stats;
+ stat(shared_data_path.c_str(), &stats);
+ EXTENDED_ASSERT_EQ(uid, stats.st_uid);
+ EXTENDED_ASSERT_EQ(*system_share, stats.st_gid);
+ stat(shared.c_str(), &stats);
+ EXTENDED_ASSERT_EQ(uid, stats.st_uid);
+ EXTENDED_ASSERT_EQ(*system_share, stats.st_gid);
+ stat(shared_tmp.c_str(), &stats);
+ EXTENDED_ASSERT_EQ(uid, stats.st_uid);
+ EXTENDED_ASSERT_EQ(kDefaultUserGid, stats.st_gid);
+ return true;
+}
+
+bool CheckSharedDataExistance(const std::string& pkgid,
+ const TestParameters& params) {
+ if (params.test_user.uid == kGlobalUserUid) {
+ bf::path skel_path(kSkelDir);
+ EXTENDED_ASSERT_TRUE(CheckSharedDataExistanceForPath(kSkelDir, pkgid));
+ ci::UserList list = ci::GetUserList();
+ for (auto& l : list) {
+ uid_t uid = std::get<0>(l);
+ bf::path apps_rw = ci::GetRootAppPath(false, uid);
+ EXTENDED_ASSERT_TRUE(CheckSharedDataExistanceForPath(apps_rw, pkgid));
+ EXTENDED_ASSERT_TRUE(CheckSharedDataPermissions(apps_rw, pkgid, uid));
+ }
+ } else {
+ bf::path apps_rw = ci::GetRootAppPath(false, params.test_user.uid);
+ EXTENDED_ASSERT_TRUE(CheckSharedDataExistanceForPath(apps_rw, pkgid));
+ EXTENDED_ASSERT_TRUE(
+ CheckSharedDataPermissions(apps_rw, pkgid, params.test_user.uid));
+ }
+ return true;
+}
+
+static bool CheckSharedDataNonExistanceForPath(const bf::path& apps_rw,
+ const std::string pkgid) {
+ bf::path shared_data_path = apps_rw / pkgid / rwDirectories[SHARED_DATA];
+ bf::path shared = apps_rw / kShared / pkgid / kData;
+ bf::path shared_tmp = apps_rw / kSharedTmp / pkgid;
+ EXTENDED_ASSERT_FALSE(bf::exists(shared_data_path));
+ EXTENDED_ASSERT_FALSE(bf::exists(shared));
+ EXTENDED_ASSERT_FALSE(bf::exists(shared_tmp));
+ return true;
+}
+
+bool CheckSharedDataNonExistance(const std::string& pkgid,
+ const TestParameters& params) {
+ if (params.test_user.uid == kGlobalUserUid) {
+ bf::path skel_path(kSkelDir);
+ EXTENDED_ASSERT_TRUE(
+ CheckSharedDataNonExistanceForPath(skel_path, pkgid));
+
+ ci::UserList list = ci::GetUserList();
+ for (auto& l : list) {
+ uid_t uid = std::get<0>(l);
+ bf::path apps_rw = ci::GetRootAppPath(false, uid);
+ EXTENDED_ASSERT_TRUE(CheckSharedDataNonExistanceForPath(apps_rw, pkgid));
+ }
+ } else {
+ bf::path apps_rw = ci::GetRootAppPath(false, params.test_user.uid);
+ EXTENDED_ASSERT_TRUE(CheckSharedDataNonExistanceForPath(apps_rw, pkgid));
+ }
+ return true;
+}
+
+void BackendInterface::TestRollbackAfterEachStep(int argc, const char* argv[],
+ std::function<bool()> validator) const {
+ TestPkgmgrInstaller pkgmgr_installer;
+ std::unique_ptr<ci::AppQueryInterface> query_interface =
+ CreateQueryInterface();
+ auto pkgmgr =
+ ci::PkgMgrInterface::Create(argc, const_cast<char**>(argv),
+ &pkgmgr_installer,
+ query_interface.get());
+ if (!pkgmgr) {
+ LOG(ERROR) << "Failed to initialize pkgmgr interface";
+ return;
+ }
+ AppInstallerPtr backend;
+ unsigned int insert_idx = 0;
+ do {
+ backend = CreateFailExpectedInstaller(pkgmgr, insert_idx);
+ LOG(DEBUG) << "StepFail is inserted at: " << insert_idx;
+ ASSERT_EQ(ci::AppInstaller::Result::ERROR, backend->Run());
+ if (!validator())
+ break;
+ insert_idx++;
+ } while (insert_idx < backend->StepCount());
+ ASSERT_EQ(insert_idx, backend->StepCount());
+}
+
+void BackendInterface::CrashAfterEachStep(std::vector<std::string>* args,
+ std::function<bool(int iter)> validator, PackageType type) const {
+ std::unique_ptr<const char*[]> argv(new const char*[args->size()]);
+ for (size_t i = 0; i < args->size(); ++i) {
+ argv[i] = args->at(i).c_str();
+ }
+ TestPkgmgrInstaller pkgmgr_installer;
+ auto query_interface = CreateQueryInterface();
+ auto pkgmgr =
+ ci::PkgMgrInterface::Create(args->size(), const_cast<char**>(argv.get()),
+ &pkgmgr_installer,
+ query_interface.get());
+ if (!pkgmgr) {
+ LOG(ERROR) << "Failed to initialize pkgmgr interface";
+ return;
+ }
+ auto backend = CreateFailExpectedInstaller(pkgmgr, 0);
+ ASSERT_EQ(backend->Run(), ci::AppInstaller::Result::ERROR);
+ int stepCount = backend->StepCount();
+
+ args->push_back("-idx");
+ args->push_back(std::to_string(stepCount));
+ int i;
+ std::string prefix = (type == PackageType::TPK) ? "tpk" : "wgt";
+ for (i = 0; i < stepCount; i++) {
+ ci::Subprocess backend_crash(
+ "/usr/bin/" + prefix + "-installer-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);
+
+ args->push_back("-type_clean");
+ for (i = stepCount - 1; i >= 2; i--) {
+ ci::Subprocess backend_crash(
+ "/usr/bin/" + prefix + "-installer-ut/smoke-test-helper");
+ auto it = args->end();
+ it -= 2;
+ *it = std::to_string(i);
+ backend_crash.Run(*args);
+ ASSERT_NE(backend_crash.Wait(), 0);
+ if (!validator(i))
+ break;
+ }
+ ASSERT_EQ(i , 1);
+}
+
+BackendInterface::CommandResult BackendInterface::RunInstallersWithPkgmgr(
+ ci::PkgMgrPtr pkgmgr) const {
+ std::list<AppInstallerPtr> installers;
+ for (int i = 0; i < pkgmgr->GetRequestInfoCount(); i++) {
+ AppInstallerPtr installer;
+ if (mode_ == RequestResult::FAIL && i == pkgmgr->GetRequestInfoCount() - 1)
+ installer = factory_->CreateFailExpectedInstaller(i, pkgmgr);
+ else
+ installer = factory_->CreateInstaller(i, pkgmgr);
+ if (!installer)
+ LOG(ERROR) << "Failed to create installer";
+ else
+ installers.emplace_back(std::move(installer));
+ }
+
+ // FIXME: I think we should not implement this logic here...
+ CommandResult result = CommandResult::OK;
+ std::list<AppInstallerPtr>::iterator it(installers.begin());
+ for (; it != installers.end(); ++it) {
+ result = (*it)->Process();
+ if (result != CommandResult::OK)
+ break;
+ }
+ if (it != installers.end() && result == CommandResult::ERROR) {
+ do {
+ CommandResult ret = (*it)->Undo();
+ if (ret != CommandResult::OK && ret != CommandResult::ERROR)
+ result = CommandResult::UNDO_ERROR;
+ } while (it-- != installers.begin());
+ } else {
+ --it;
+ do {
+ if ((*it)->Clean() != CommandResult::OK)
+ result = CommandResult::CLEANUP_ERROR;
+ } while (it-- != installers.begin());
+ }
+ return result;
+}
+
+BackendInterface::CommandResult BackendInterface::CallBackendWithRunner(
+ int argc, const char* argv[]) const {
+ TestPkgmgrInstaller pkgmgr_installer;
+ auto pkgmgr = ci::PkgMgrInterface::Create(argc, const_cast<char**>(argv),
+ &pkgmgr_installer);
+ if (!pkgmgr) {
+ LOG(ERROR) << "Failed to initialize pkgmgr interface";
+ return BackendInterface::CommandResult::UNKNOWN;
+ }
+ return RunInstallersWithPkgmgr(pkgmgr);
+}
+
+BackendInterface::CommandResult BackendInterface::Install(
+ const std::vector<bf::path>& paths) const {
+ std::vector<const char*> argv;
+ argv.emplace_back("");
+ argv.emplace_back("-i");
+ for (const auto& p : paths)
+ argv.emplace_back(p.string().c_str());
+ return CallBackendWithRunner(argv.size(), argv.data());
+}
+
+BackendInterface::CommandResult BackendInterface::Uninstall(
+ const std::vector<std::string>& pkgids) const {
+ std::vector<const char*> argv;
+ argv.emplace_back("");
+ argv.emplace_back("-d");
+ for (const auto& p : pkgids)
+ argv.emplace_back(p.c_str());
+ return CallBackendWithRunner(argv.size(), argv.data());
+}
+
+BackendInterface::CommandResult BackendInterface::InstallSuccess(
+ const std::vector<bf::path>& paths) const {
+ RequestResult tmp_mode = mode_;
+ RequestResult &original_mode = const_cast<RequestResult&>(mode_);
+ original_mode = RequestResult::NORMAL;
+ if (Install(paths) != BackendInterface::CommandResult::OK) {
+ LOG(ERROR) << "Failed to install application. Cannot update";
+ return BackendInterface::CommandResult::UNKNOWN;
+ }
+ original_mode = tmp_mode;
+ return BackendInterface::CommandResult::OK;
+}
+
+BackendInterface::CommandResult BackendInterface::RunInstallerWithPkgrmgr(
+ ci::PkgMgrPtr pkgmgr) const {
+ std::unique_ptr<ci::AppInstaller> installer;
+ switch (mode_) {
+ case RequestResult::FAIL:
+ installer = CreateFailExpectedInstaller(pkgmgr);
+ break;
+ default:
+ installer = CreateInstaller(pkgmgr);
+ break;
+ }
+ return installer->Run();
+}
+
+BackendInterface::CommandResult BackendInterface::CallBackend(int argc,
+ const char* argv[]) const {
+ TestPkgmgrInstaller pkgmgr_installer;
+ auto query_interface = CreateQueryInterface();
+ auto pkgmgr = ci::PkgMgrInterface::Create(argc, const_cast<char**>(argv),
+ &pkgmgr_installer, query_interface.get());
+ if (!pkgmgr) {
+ LOG(ERROR) << "Failed to initialize pkgmgr interface";
+ return BackendInterface::CommandResult::UNKNOWN;
+ }
+ return RunInstallerWithPkgrmgr(pkgmgr);
+}
+
+BackendInterface::CommandResult BackendInterface::Install(
+ const bf::path& path) const {
+ const char* argv[] = {"", "-i", path.c_str(), "-u", uid_str_.c_str()};
+ return CallBackend(SIZEOFARRAY(argv), argv);
+}
+
+BackendInterface::CommandResult BackendInterface::InstallPreload(
+ const bf::path& path) const {
+ const char* argv[] = {"", "-i", path.c_str(), "--preload"};
+ return CallBackend(SIZEOFARRAY(argv), argv);
+}
+
+BackendInterface::CommandResult BackendInterface::InstallWithStorage(
+ const bf::path& path, StorageType type) const {
+ int default_storage = 0;
+ int storage = 0;
+ switch (type) {
+ case StorageType::EXTERNAL:
+ storage = 1;
+ break;
+ case StorageType::EXTENDED:
+ storage = 2;
+ break;
+ default:
+ LOG(ERROR) << "Unknown storage type";
+ break;
+ }
+ vconf_get_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT,
+ &default_storage);
+ vconf_set_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT, storage);
+
+ const char* argv[] = {"", "-i", path.c_str(), "-u", uid_str_.c_str()};
+ BackendInterface::CommandResult result = CallBackend(SIZEOFARRAY(argv), argv);
+
+ vconf_set_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT,
+ default_storage);
+ return result;
+}
+
+BackendInterface::CommandResult BackendInterface::MigrateLegacyExternalImage(
+ const std::string& pkgid,
+ const bf::path& path,
+ const bf::path& legacy_path) const {
+ if (InstallWithStorage(path, StorageType::EXTERNAL) !=
+ BackendInterface::CommandResult::OK) {
+ LOG(ERROR) << "Failed to install application. Cannot perform Migrate";
+ return BackendInterface::CommandResult::ERROR;
+ }
+
+ bf::path ext_mount_path = ci::GetExternalCardPath();
+ if (bf::is_empty(ext_mount_path)) {
+ LOG(ERROR) << "Sdcard not exists!";
+ return BackendInterface::CommandResult::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 BackendInterface::CommandResult::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 BackendInterface::CommandResult::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 BackendInterface::CommandResult::ERROR;
+ }
+ bf::remove(app2sd_db_journal, error);
+ if (error) {
+ LOG(ERROR) << "Failed to remove app2sd journal db";
+ return BackendInterface::CommandResult::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 BackendInterface::CommandResult::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 BackendInterface::CommandResult::ERROR;
+ }
+ const char* argv[] = {"", "--migrate-extimg", pkgid.c_str(),
+ "-u", uid_str_.c_str()};
+ return CallBackend(SIZEOFARRAY(argv), argv);
+}
+
+BackendInterface::CommandResult BackendInterface::RDSUpdate(
+ const bf::path& path,
+ const std::string& pkgid) const {
+ RequestResult tmp_mode = mode_;
+ RequestResult &original_mode = const_cast<RequestResult&>(mode_);
+ original_mode = RequestResult::NORMAL;
+ if (Install(path) != BackendInterface::CommandResult::OK) {
+ LOG(ERROR) << "Failed to install application. Cannot perform RDS";
+ return BackendInterface::CommandResult::UNKNOWN;
+ }
+ const char* argv[] = {"", "-r", pkgid.c_str(), "-u",
+ uid_str_.c_str()};
+ original_mode = tmp_mode;
+ return CallBackend(SIZEOFARRAY(argv), argv);
+}
+
+BackendInterface::CommandResult BackendInterface::EnablePackage(
+ const std::string& pkgid) const {
+ const char* argv[] = {"", "-A", pkgid.c_str(), "-u", uid_str_.c_str()};
+ return CallBackend(SIZEOFARRAY(argv), argv);
+}
+
+BackendInterface::CommandResult BackendInterface::DisablePackage(
+ const std::string& pkgid) const {
+ const char* argv[] = {"", "-D", pkgid.c_str(), "-u", uid_str_.c_str()};
+ return CallBackend(SIZEOFARRAY(argv), argv);
+}
+
+BackendInterface::CommandResult BackendInterface::Recover(
+ const bf::path& recovery_file) const {
+ const char* argv[] = {"", "-b", recovery_file.c_str(), "-u",
+ uid_str_.c_str()};
+ return CallBackend(SIZEOFARRAY(argv), argv);
+}
+
+BackendInterface::CommandResult BackendInterface::ManifestDirectInstall(
+ const std::string& pkgid) const {
+ const char* argv[] = {"", "-y", pkgid.c_str(), "-u", uid_str_.c_str()};
+ return CallBackend(SIZEOFARRAY(argv), argv);
+}
+
+BackendInterface::CommandResult BackendInterface::Uninstall(
+ const std::string& pkgid) const {
+ const char* argv[] = {"", "-d", pkgid.c_str(), "-u", uid_str_.c_str()};
+ return CallBackend(SIZEOFARRAY(argv), argv);
+}
+
+BackendInterface::CommandResult BackendInterface::UninstallPreload(
+ const std::string& pkgid) const {
+ const char* argv[] = {"", "-d", pkgid.c_str(), "--preload",
+ "--force-remove"};
+ return CallBackend(SIZEOFARRAY(argv), argv);
+}
+
+BackendInterface::CommandResult BackendInterface::InstallSuccess(
+ const bf::path& path) const {
+ RequestResult tmp_mode = mode_;
+ RequestResult &original_mode = const_cast<RequestResult&>(mode_);
+ original_mode = RequestResult::NORMAL;
+ if (Install(path) != BackendInterface::CommandResult::OK) {
+ LOG(ERROR) << "Failed to install application. Cannot update";
+ return BackendInterface::CommandResult::UNKNOWN;
+ }
+ original_mode = tmp_mode;
+ return BackendInterface::CommandResult::OK;
+}
+
+BackendInterface::CommandResult BackendInterface::InstallPreloadSuccess(
+ const bf::path& path) const {
+ RequestResult tmp_mode = mode_;
+ RequestResult &original_mode = const_cast<RequestResult&>(mode_);
+ original_mode = RequestResult::NORMAL;
+ if (InstallPreload(path) != BackendInterface::CommandResult::OK) {
+ LOG(ERROR) << "Failed to install application. Cannot update";
+ return BackendInterface::CommandResult::UNKNOWN;
+ }
+ original_mode = tmp_mode;
+ return BackendInterface::CommandResult::OK;
+}
+
+BackendInterface::CommandResult BackendInterface::MountInstall(
+ const bf::path& path) const {
+ const char* argv[] = {"", "-w", path.c_str(), "-u", uid_str_.c_str()};
+ return CallBackend(SIZEOFARRAY(argv), argv);
+}
+
+BackendInterface::CommandResult BackendInterface::MountInstallSuccess(
+ const bf::path& path) const {
+ RequestResult tmp_mode = mode_;
+ RequestResult &original_mode = const_cast<RequestResult&>(mode_);
+ original_mode = RequestResult::NORMAL;
+ if (MountInstall(path) != BackendInterface::CommandResult::OK) {
+ LOG(ERROR) << "Failed to mount-install application. Cannot mount-update";
+ return BackendInterface::CommandResult::UNKNOWN;
+ }
+ original_mode = tmp_mode;
+ return BackendInterface::CommandResult::OK;
+}
+
+static boost::filesystem::path GetTrashPath(
+ const boost::filesystem::path& path) {
+ return path.string() + ".trash";
+}
+
+SmokeTestHelperRunner::Result SmokeTestHelperRunner::RunSubprocess(
+ std::vector<std::string> args) const {
+ args.push_back("-remove_plugin_steps");
+ ci::Subprocess backend = CreateSubprocess();
+ backend.RunWithArgs(args);
+ int status = backend.Wait();
+ if (WIFEXITED(status)) {
+ if (WEXITSTATUS(status) == 0)
+ return SmokeTestHelperRunner::Result::SUCCESS;
+ else
+ return SmokeTestHelperRunner::Result::FAIL;
+ }
+ return SmokeTestHelperRunner::Result::UnKnown;
+}
+
+SmokeTestHelperRunner::Result SmokeTestHelperRunner::RunSubprocessAndKill(
+ std::vector<std::string> args, useconds_t delay) const {
+ args.push_back("-remove_plugin_steps");
+ ci::Subprocess backend = CreateSubprocess();
+ backend.RunWithArgs(args);
+ usleep(delay);
+ backend.Kill();
+ int status = backend.Wait();
+ if (WIFEXITED(status)) {
+ if (WEXITSTATUS(status) == 0)
+ return SmokeTestHelperRunner::Result::SUCCESS;
+ else
+ return SmokeTestHelperRunner::Result::FAIL;
+ } else {
+ if (WTERMSIG(status) == SIGKILL)
+ return SmokeTestHelperRunner::Result::KILLED;
+ else
+ return SmokeTestHelperRunner::Result::UnKnown;
+ }
+}
+
+SmokeTestHelperRunner::Result SmokeTestHelperRunner::InstallWithSubprocess(
+ const bf::path& path, uid_t uid) const {
+ std::vector<std::string> args =
+ { "-i", path.string(), "-u", std::to_string(uid) };
+ return RunSubprocess(args);
+}
+
+SmokeTestHelperRunner::Result SmokeTestHelperRunner::MountInstallWithSubprocess(
+ const bf::path& path, uid_t uid) const {
+ std::vector<std::string> args =
+ { "-w", path.string(), "-u", std::to_string(uid) };
+ return RunSubprocess(args);
+}
+
+SmokeTestHelperRunner::Result SmokeTestHelperRunner::RecoveryWithSubprocess(
+ const bf::path& path, uid_t uid) const {
+ std::vector<std::string> args =
+ { "-b", path.string(), "-u", std::to_string(uid) };
+ return RunSubprocess(args);
+}
+
+SmokeTestHelperRunner::Result SmokeTestHelperRunner::UninstallWithSubprocess(
+ const std::string& pkgid, uid_t uid) const {
+ std::vector<std::string> args = { "-d", pkgid, "-u", std::to_string(uid) };
+ return RunSubprocess(args);
+}
+
+SmokeTestHelperRunner::Result
+ SmokeTestHelperRunner::InstallWithSubprocessAndKill(
+ const bf::path& path, uid_t uid, useconds_t delay) const {
+ std::vector<std::string> args =
+ { "-i", path.string(), "-u", std::to_string(uid) };
+ return RunSubprocessAndKill(args, delay);
+}
+
+SmokeTestHelperRunner::Result
+ SmokeTestHelperRunner::MountInstallWithSubprocessAndKill(
+ const bf::path& path, uid_t uid, useconds_t delay) const {
+ std::vector<std::string> args =
+ { "-w", path.string(), "-u", std::to_string(uid) };
+ return RunSubprocessAndKill(args, delay);
+}
+
+SmokeTestHelperRunner::Result
+ SmokeTestHelperRunner::UninstallWithSubprocessAndKill(
+ const std::string& pkgid, uid_t uid, useconds_t delay) const {
+ std::vector<std::string> args =
+ { "-d", pkgid, "-u", std::to_string(uid) };
+ return RunSubprocessAndKill(args, delay);
+}
+
+SmokeTestHelperRunner::Result SmokeTestHelperRunner::InstallPkgsWithSubprocess(
+ const std::vector<bf::path>& paths, uid_t uid) const {
+ std::vector<std::string> args;
+ args.emplace_back("-i");
+ for (const bf::path& p : paths)
+ args.emplace_back(p.string());
+ args.emplace_back("-u");
+ args.emplace_back(std::to_string(uid));
+ return RunSubprocess(args);
+}
+
+SmokeTestHelperRunner::Result
+ SmokeTestHelperRunner::MountInstallPkgsWithSubprocess(
+ const std::vector<bf::path>& paths, uid_t uid) const {
+ std::vector<std::string> args;
+ args.emplace_back("-w");
+ for (const bf::path& p : paths)
+ args.emplace_back(p.string());
+ args.emplace_back("-u");
+ args.emplace_back(std::to_string(uid));
+ return RunSubprocess(args);
+}
+
+SmokeTestHelperRunner::Result SmokeTestHelperRunner::RecoveryPkgsWithSubprocess(
+ const std::vector<bf::path>& paths, uid_t uid) const {
+ std::vector<std::string> args;
+ args.emplace_back("-b");
+ for (const bf::path& p : paths)
+ args.emplace_back(p.string());
+ args.emplace_back("-u");
+ args.emplace_back(std::to_string(uid));
+ return RunSubprocess(args);
+}
+
+SmokeTestHelperRunner::Result
+ SmokeTestHelperRunner::UninstallPkgsWithSubprocess(
+ const std::vector<std::string>& pkgids, uid_t uid) const {
+ std::vector<std::string> args;
+ args.emplace_back("-d");
+ args.insert(args.end(), pkgids.begin(), pkgids.end());
+ args.emplace_back("-u");
+ args.emplace_back(std::to_string(uid));
+ return RunSubprocess(args);
+}
+
+SmokeTestHelperRunner::Result
+ SmokeTestHelperRunner::InstallPkgsWithSubprocessAndKill(
+ const std::vector<bf::path>& paths, uid_t uid, useconds_t delay) const {
+ std::vector<std::string> args;
+ args.emplace_back("-i");
+ for (const bf::path& p : paths)
+ args.emplace_back(p.string());
+ args.emplace_back("-u");
+ args.emplace_back(std::to_string(uid));
+ return RunSubprocessAndKill(args, delay);
+}
+
+SmokeTestHelperRunner::Result
+ SmokeTestHelperRunner::MountInstallPkgsWithSubprocessAndKill(
+ const std::vector<bf::path>& paths, uid_t uid, useconds_t delay) const {
+ std::vector<std::string> args;
+ args.emplace_back("-w");
+ for (const bf::path& p : paths)
+ args.emplace_back(p.string());
+ args.emplace_back("-u");
+ args.emplace_back(std::to_string(uid));
+ return RunSubprocessAndKill(args, delay);
+}
+
+bool CopySmackAccess(const boost::filesystem::path& src,
+ const boost::filesystem::path& dst) {
+ if (!bf::exists(src) && !bf::is_symlink(src)) {
+ LOG(ERROR) << "Failed to copy smack access label";
+ return false;
+ }
+ int ret;
+ char* access_label = nullptr;
+ ret = smack_lgetlabel(src.c_str(), &access_label, SMACK_LABEL_ACCESS);
+ if (ret < 0) {
+ LOG(ERROR) << "get access label from [" << src << "] fail";
+ return false;
+ }
+ if (!access_label)
+ return true;
+ ret = smack_lsetlabel(dst.c_str(), access_label, SMACK_LABEL_ACCESS);
+ free(access_label);
+ if (ret < 0) {
+ LOG(ERROR) << "set access label to [" << dst << "] fail";
+ return false;
+ }
+ return true;
+}
+
+bool CopySmackExec(const boost::filesystem::path& src,
+ const boost::filesystem::path& dst) {
+ if (!bf::exists(src) && !bf::is_symlink(src)) {
+ LOG(ERROR) << "Failed to copy smack exec label";
+ return false;
+ }
+ int ret;
+ char *exec_label = nullptr;
+ ret = smack_lgetlabel(src.c_str(), &exec_label, SMACK_LABEL_EXEC);
+ if (ret < 0) {
+ LOG(ERROR) << "get exec label from [" << src << "] fail";
+ return false;
+ }
+ if (!exec_label)
+ return true;
+ ret = smack_lsetlabel(dst.c_str(), exec_label, SMACK_LABEL_EXEC);
+ free(exec_label);
+ if (ret < 0) {
+ LOG(ERROR) << "set exec label to [" << dst << "] fail";
+ return false;
+ }
+ return true;
+}
+
+bool CopySmackMmap(const boost::filesystem::path& src,
+ const boost::filesystem::path& dst) {
+ if (!bf::exists(src) && !bf::is_symlink(src)) {
+ LOG(ERROR) << "Failed to copy smack mmap label";
+ return false;
+ }
+ int ret;
+ char *mmap_label = nullptr;
+ ret = smack_lgetlabel(src.c_str(), &mmap_label, SMACK_LABEL_MMAP);
+ if (ret < 0) {
+ LOG(ERROR) << "get mmap label from [" << src << "] fail";
+ return false;
+ }
+ if (!mmap_label)
+ return true;
+ ret = smack_lsetlabel(dst.c_str(), mmap_label, SMACK_LABEL_MMAP);
+ free(mmap_label);
+ if (ret < 0) {
+ LOG(ERROR) << "set mmap label to [" << dst << "] fail";
+ return false;
+ }
+ return true;
+}
+
+bool CopySmackTransmute(const boost::filesystem::path& src,
+ const boost::filesystem::path& dst) {
+ if (!bf::exists(src)) {
+ LOG(ERROR) << "Failed to copy smack tranmute label";
+ return false;
+ }
+ int ret;
+ char *transmute_label = nullptr;
+ ret = smack_lgetlabel(src.c_str(), &transmute_label, SMACK_LABEL_TRANSMUTE);
+ if (ret < 0) {
+ LOG(ERROR) << "get access label from [" << src << "] fail";
+ return false;
+ }
+ if (!transmute_label) {
+ ret = smack_lsetlabel(dst.c_str(), "0", SMACK_LABEL_TRANSMUTE);
+ } else {
+ if (strcmp(transmute_label, "TRUE") == 0)
+ ret = smack_lsetlabel(dst.c_str(), "1", SMACK_LABEL_TRANSMUTE);
+ else
+ ret = smack_lsetlabel(dst.c_str(), "0", SMACK_LABEL_TRANSMUTE);
+ free(transmute_label);
+ if (ret < 0) {
+ LOG(ERROR) << "set access label to [" << dst << "] fail";
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool CopySmackLabels(const boost::filesystem::path& src,
+ const boost::filesystem::path& dst) {
+ if (!CopySmackAccess(src, dst))
+ return false;
+ if (!CopySmackExec(src, dst))
+ return false;
+ if (!CopySmackMmap(src, dst))
+ return false;
+ if (!bf::is_symlink(src) && bf::is_directory(src)) {
+ if (!CopySmackTransmute(src, dst))
+ return false;
+ }
+ return true;
+}
+
+bool CopyAndRemoveWithSmack(const bf::path& src, const bf::path& dst) {
+ bs::error_code error;
+ if (bf::exists(dst)) {
+ try {
+ bf::remove_all(dst, error);
+ } catch (...) {
+ std::cout << "Exception occurred during remove [" << dst.string()
+ << "], and skip this file"<< std::endl;
+ }
+ if (error) {
+ if (!bf::is_directory(dst)) {
+ LOG(ERROR) << "remove_all fail";
+ return false;
+ }
+ }
+ }
+ try {
+ if (bf::is_symlink(src)) {
+ bf::copy_symlink(src, dst, error);
+ if (error) {
+ LOG(ERROR) << "Failed to copy symlink: " << src << ", "
+ << error.message();
+ return false;
+ }
+ if (!CopySmackLabels(src, dst)) {
+ LOG(ERROR) << "copy smack label from [" << src.string()
+ << "] to [" << dst.string() << "] fail";
+ return false;
+ }
+ } else if (bf::is_directory(src)) {
+ if (!bf::exists(dst)) {
+ bf::create_directories(dst, error);
+ if (error) {
+ LOG(ERROR) << "create directories fail";
+ return false;
+ }
+ ci::CopyOwnershipAndPermissions(src, dst);
+ if (!CopySmackLabels(src, dst)) {
+ LOG(ERROR) << "copy smack label from [" << src.string()
+ << "] to [" << dst.string() << "] fail";
+ return false;
+ }
+ }
+ bool success = true;
+ for (bf::directory_iterator file(src);
+ file != bf::directory_iterator();
+ ++file) {
+ bf::path current(file->path());
+ bf::path target = dst / current.filename();
+ success &= CopyAndRemoveWithSmack(current, target);
+ }
+ bf::remove_all(src);
+ if (!success)
+ return false;
+ } else {
+ bf::copy_file(src, dst);
+ ci::CopyOwnershipAndPermissions(src, dst);
+ if (!CopySmackLabels(src, dst)) {
+ LOG(ERROR) << "copy smack label from [" << src.string()
+ << "] to [" << dst.string() << "] fail";
+ return false;
+ }
+ bf::remove_all(src);
+ }
+ } catch (...) {
+ std::cout << "Exception occurred during copy [" << src.string()
+ << "], and skip this file"<< std::endl;
+ return true;
+ }
+
+ return true;
+}
+
+bool BackupPathCopyAndRemove(const bf::path& path) {
+ if (!bf::exists(path))
+ return true;
+
+ bf::path backup_path = path.string() + ".bck";
+ std::cout << "Backup path: " << path << " to " << backup_path << std::endl;
+ if (!CopyAndRemoveWithSmack(path, backup_path)) {
+ LOG(ERROR) << "Failed to setup test environment. Does some previous"
+ << " test crashed? Path: "
+ << backup_path << " should not exist.";
+ return false;
+ }
+ return true;
+}
+
+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;
+ 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.";
+ return false;
+ }
+ assert(!error);
+ if (bf::is_directory(backup_path))
+ bf::create_directory(path);
+ }
+ return true;
+}
+
+bool RestorePathCopyAndRemove(const bf::path& path) {
+ bf::path backup_path = path.string() + ".bck";
+ if (!bf::exists(backup_path))
+ return true;
+
+ std::cout << "Restore path: " << path << " from " << backup_path << std::endl;
+ if (!CopyAndRemoveWithSmack(backup_path, path)) {
+ LOG(ERROR) << "Failed to restore backup path: " << backup_path;
+ return false;
+ }
+ return true;
+}
+
+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) {
+ 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) {
+ LOG(ERROR) << "Failed to restore backup path: " << backup_path
+ << " (" << error.message() << ")";
+ return false;
+ }
+ }
+ return true;
+}
+
+std::vector<bf::path> SetupBackupDirectories(uid_t test_uid) {
+ std::vector<bf::path> entries;
+ bf::path db_dir = bf::path(tzplatform_getenv(TZ_SYS_DB));
+ if (test_uid != kGlobalUserUid)
+ db_dir = db_dir / "user" / std::to_string(test_uid);
+ for (auto e : kDBEntries) {
+ bf::path path = db_dir / e;
+ entries.emplace_back(path);
+ }
+
+ if (getuid() == 0) {
+ entries.emplace_back(kPreloadApps);
+ entries.emplace_back(kPreloadManifestDir);
+ entries.emplace_back(kPreloadIcons);
+ }
+
+ if (test_uid == kGlobalUserUid) {
+ entries.emplace_back(kSkelDir);
+ entries.emplace_back(kGlobalManifestDir);
+ ci::UserList list = ci::GetUserList();
+ for (auto l : list) {
+ bf::path apps = std::get<2>(l) / "apps_rw";
+ entries.emplace_back(apps);
+ }
+ } else {
+ tzplatform_set_user(test_uid);
+ bf::path approot = tzplatform_getenv(TZ_USER_APPROOT);
+ tzplatform_reset_user();
+ entries.emplace_back(approot);
+ }
+
+ bf::path apps_rw = ci::GetRootAppPath(false, test_uid);
+ entries.emplace_back(apps_rw);
+ entries.emplace_back(kSdkDirectory);
+
+ return entries;
+}
+
+void UninstallAllAppsInDirectory(bf::path dir, bool is_preload,
+ BackendInterface* backend) {
+ 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-Z0-9]{5,}");
+ if (std::regex_match(package, pkg_regex)) {
+ BackendInterface::CommandResult result =
+ BackendInterface::CommandResult::OK;
+ if (is_preload)
+ result = backend->UninstallPreload(
+ dir_entry.path().filename().string());
+ else
+ result = backend->Uninstall(
+ dir_entry.path().filename().string());
+ if (result != BackendInterface::CommandResult::OK) {
+ LOG(ERROR) << "Cannot uninstall smoke test app: "
+ << dir_entry.path().filename().string();
+ }
+ }
+ }
+ }
+ }
+}
+
+void UninstallAllSmokeApps(ci::RequestMode request_mode, uid_t test_uid,
+ BackendInterface *backend) {
+ std::cout << "Uninstalling all smoke apps" << std::endl;
+ bf::path apps_rw = ci::GetRootAppPath(false, test_uid);
+ UninstallAllAppsInDirectory(apps_rw, false, backend);
+ if (getuid() == 0 && request_mode == ci::RequestMode::GLOBAL) {
+ bf::path root_path = kPreloadApps;
+ UninstallAllAppsInDirectory(root_path, true, backend);
+ }
+}
+
+int GetAppInstalledTime(const char* appid, uid_t uid) {
+ int ret = 0;
+ int installed_time = 0;
+ pkgmgrinfo_appinfo_h handle = NULL;
+ ret = pkgmgrinfo_appinfo_get_usr_appinfo(appid, uid, &handle);
+ if (ret != PMINFO_R_OK)
+ return -1;
+ ret = pkgmgrinfo_appinfo_get_installed_time(handle, &installed_time);
+ if (ret != PMINFO_R_OK) {
+ pkgmgrinfo_appinfo_destroy_appinfo(handle);
+ return -1;
+ }
+ pkgmgrinfo_appinfo_destroy_appinfo(handle);
+ return installed_time;
+}
+
+} // namespace smoke_test
--- /dev/null
+// 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 SMOKE_TESTS_COMMON_SMOKE_UTILS_H_
+#define SMOKE_TESTS_COMMON_SMOKE_UTILS_H_
+
+#include <pkgmgr-info.h>
+#include <signal.h>
+#include <unistd.h>
+#include <tzplatform_config.h>
+
+#include <boost/filesystem/operations.hpp>
+#include <boost/range/iterator_range.hpp>
+#include <boost/format.hpp>
+#include <boost/program_options.hpp>
+#include <boost/system/error_code.hpp>
+
+#include <gtest/gtest.h>
+#include <gtest/gtest-death-test.h>
+
+#include <manifest_parser/utils/version_number.h>
+
+#include <common/utils/subprocess.h>
+#include <common/utils/user_util.h>
+#include <common/utils/file_util.h>
+#include <common/utils/request.h>
+#include <common/tzip_interface.h>
+#include <common/installer/app_installer.h>
+#include <common/utils/paths.h>
+#include <common/utils/pkgmgr_query.h>
+#include <common/recovery_file.h>
+
+#include <array>
+#include <cstdio>
+#include <cstdlib>
+#include <memory>
+#include <regex>
+#include <string>
+#include <vector>
+#include <utility>
+
+#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 smoke_test {
+
+extern const bf::path kSmokePackagesDirectory;
+extern const bf::path kSdkDirectory;
+extern const uid_t kGlobalUserUid;
+extern const uid_t kGlobalUserGid;
+extern const char kLegacyExtImageDir[];
+extern const std::string& kDefaultUserIdStr;
+
+using App = std::pair<std::string, std::string>;
+using Apps = std::vector<App>;
+
+enum class RequestResult {
+ NORMAL,
+ FAIL
+};
+
+enum class StorageType {
+ INTERNAL,
+ EXTERNAL,
+ EXTENDED
+};
+
+class ScopedTzipInterface {
+ public:
+ explicit ScopedTzipInterface(const std::string& pkgid, uid_t test_user)
+ : pkg_path_(boost::filesystem::path(
+ common_installer::GetRootAppPath(false, test_user)) / pkgid),
+ interface_(common_installer::GetMountLocation(pkg_path_)),
+ mounted_(true) {
+ interface_.MountZip(common_installer::GetZipPackageLocation(pkg_path_,
+ pkgid));
+ }
+
+ void Release() {
+ if (mounted_) {
+ interface_.UnmountZip();
+ mounted_ = false;
+ }
+ }
+
+ ~ScopedTzipInterface() {
+ Release();
+ }
+
+ private:
+ boost::filesystem::path pkg_path_;
+ common_installer::TzipInterface interface_;
+ bool mounted_;
+};
+
+class TestPkgmgrInstaller : public common_installer::PkgmgrInstallerInterface {
+ public:
+ bool CreatePkgMgrInstaller(pkgmgr_installer** installer,
+ common_installer::InstallationMode* mode) {
+ *installer = pkgmgr_installer_offline_new();
+ if (!*installer)
+ return false;
+ *mode = common_installer::InstallationMode::ONLINE;
+ return true;
+ }
+
+ bool ShouldCreateSignal() const {
+ return false;
+ }
+};
+
+enum class PackageType {
+ TPK,
+ WGT,
+ HYBRID
+};
+
+struct User {
+ uid_t uid = kGlobalUserUid;
+ gid_t gid = kGlobalUserGid;
+};
+
+struct TestParameters {
+ TestParameters(PackageType type, bool readonly) :
+ pkg_type(type), is_readonly(readonly) {}
+ TestParameters(const TestParameters& other) : pkg_type(other.pkg_type),
+ is_readonly(other.is_readonly), test_user{other.test_user} {}
+ PackageType pkg_type;
+ bool is_readonly;
+ User test_user;
+};
+
+struct PackageAttributes {
+ explicit PackageAttributes(common_installer::PkgQueryInterface pi)
+ : is_global(pi.IsGlobalPackage()), is_readonly(pi.IsReadonlyPackage()),
+ is_update(pi.IsUpdatedPackage()), is_preload(pi.IsPreloadPackage()),
+ is_system(pi.IsSystemPackage()), is_removable(pi.IsRemovablePackage()) {
+ }
+
+ bool operator==(const PackageAttributes& other) const {
+ return (is_global == other.is_global) &&
+ (is_readonly == other.is_readonly) &&
+ (is_update == other.is_update) &&
+ (is_preload == other.is_preload) &&
+ (is_system == other.is_system) &&
+ (is_removable == other.is_removable);
+ }
+
+ bool is_global;
+ bool is_readonly;
+ bool is_update;
+ bool is_preload;
+ bool is_system;
+ bool is_removable;
+};
+
+common_installer::RequestMode ParseRequestMode(int argc, char** argv);
+
+bool TouchFile(const boost::filesystem::path& path);
+
+void AddDataFiles(const std::string& pkgid, uid_t uid);
+
+bool AddTestUser(User* test_user);
+
+bool DeleteTestUser();
+
+void RemoveAllRecoveryFiles(const std::string& prefix, uid_t uid);
+
+boost::filesystem::path FindRecoveryFile(const std::string& prefix, uid_t uid);
+
+boost::filesystem::path GetPackageRoot(const std::string& pkgid, uid_t uid);
+
+std::unique_ptr<common_installer::recovery::RecoveryFile> GetRecoverFileInfo(
+ const bf::path& recovery_file_path);
+
+bool ValidateFileContentInPackage(const std::string& pkgid,
+ const std::string& relative,
+ const std::string& expected,
+ const TestParameters& params);
+
+bool ValidatePackage(const std::string& pkgid, const Apps& apps,
+ const TestParameters& params);
+
+bool ValidateDataFiles(const std::string& pkgid, uid_t uid);
+
+bool ValidateExternalPackage(const std::string& pkgid, const Apps& apps,
+ const TestParameters& params);
+bool ValidateExtendedPackage(const std::string& pkgid, const Apps& apps,
+ const TestParameters& params);
+
+bool CheckPackageNonExistance(const std::string& pkgid,
+ const TestParameters& params);
+
+bool CheckPackageReadonlyNonExistance(const std::string& pkgid,
+ const TestParameters& params);
+
+bool CheckSharedDataExistance(const std::string& pkgid,
+ const TestParameters& params);
+
+bool CheckSharedDataNonExistance(const std::string& pkgid,
+ const TestParameters& params);
+
+bool TouchFile(const boost::filesystem::path& path);
+
+class SmokeInstallerFactory {
+ public:
+ using AppInstallerPtr = std::unique_ptr<common_installer::AppInstaller>;
+ virtual AppInstallerPtr CreateInstaller(
+ int idx, common_installer::PkgMgrPtr pkgmgr) const = 0;
+ virtual AppInstallerPtr CreateFailExpectedInstaller(
+ int idx, common_installer::PkgMgrPtr pkgmgr, int fail_at = -1) const = 0;
+};
+
+class BackendInterface {
+ public:
+ using CommandResult = common_installer::AppInstaller::Result;
+ using SmokeInstallerFactoryPtr = std::unique_ptr<SmokeInstallerFactory>;
+ explicit BackendInterface(std::string uid,
+ RequestResult mode = RequestResult::NORMAL)
+ : uid_str_(uid), mode_(mode) {}
+ explicit BackendInterface(SmokeInstallerFactoryPtr factory,
+ std::string uid,
+ RequestResult mode = RequestResult::NORMAL)
+ : factory_(std::move(factory)), uid_str_(uid), mode_(mode) {}
+ virtual ~BackendInterface() {}
+
+ void TestRollbackAfterEachStep(int argc, const char* argv[],
+ std::function<bool()> validator) const;
+ void CrashAfterEachStep(std::vector<std::string>* args,
+ std::function<bool(int iter)> validator,
+ PackageType type) const;
+ CommandResult Install(const std::vector<bf::path>& paths) const;
+ CommandResult InstallSuccess(const std::vector<bf::path>& paths) const;
+ CommandResult Install(const boost::filesystem::path& path) const;
+ CommandResult InstallPreload(const boost::filesystem::path& path) const;
+ CommandResult InstallWithStorage(const boost::filesystem::path& path,
+ StorageType type = StorageType::INTERNAL) const;
+ CommandResult InstallSuccess(const bf::path& path) const;
+ CommandResult InstallPreloadSuccess(
+ const boost::filesystem::path& path) const;
+
+ CommandResult Uninstall(const std::vector<std::string>& pkgids) const;
+ CommandResult Uninstall(const std::string& pkgid) const;
+ CommandResult UninstallPreload(const std::string& pkgid) const;
+
+ CommandResult EnablePackage(const std::string& pkgid) const;
+ CommandResult DisablePackage(const std::string& pkgid) const;
+
+ CommandResult MountInstall(const boost::filesystem::path& path) const;
+ CommandResult MountInstallSuccess(const bf::path& path) const;
+ CommandResult ManifestDirectInstall(const std::string& pkgid) const;
+
+ CommandResult MigrateLegacyExternalImage(const std::string& pkgid,
+ const boost::filesystem::path& path,
+ const boost::filesystem::path& legacy_path) const;
+
+ CommandResult RDSUpdate(const boost::filesystem::path& path,
+ const std::string& pkgid) const;
+
+ CommandResult Recover(const boost::filesystem::path& recovery_file) const;
+
+ protected:
+ CommandResult CallBackend(int argc, const char* argv[]) const;
+ CommandResult CallBackendWithRunner(int argc, const char* argv[]) const;
+ using AppQueryInterfacePtr =
+ std::unique_ptr<common_installer::AppQueryInterface>;
+ using AppInstallerPtr = std::unique_ptr<common_installer::AppInstaller>;
+ SmokeInstallerFactoryPtr factory_;
+ std::string uid_str_;
+ RequestResult mode_;
+
+ private:
+ CommandResult RunInstallerWithPkgrmgr(
+ common_installer::PkgMgrPtr pkgmgr) const;
+ virtual AppQueryInterfacePtr CreateQueryInterface() const = 0;
+ virtual AppInstallerPtr CreateInstaller(
+ common_installer::PkgMgrPtr pkgmgr) const = 0;
+ virtual AppInstallerPtr CreateFailExpectedInstaller(
+ common_installer::PkgMgrPtr pkgmgr, int fail_at = -1) const = 0;
+ CommandResult RunInstallersWithPkgmgr(
+ common_installer::PkgMgrPtr pkgmgr) const;
+};
+
+class SmokeTestHelperRunner {
+ public:
+ enum class Result {
+ SUCCESS,
+ FAIL,
+ KILLED,
+ UnKnown
+ };
+
+ Result InstallWithSubprocess(const bf::path& path, uid_t uid) const;
+ Result MountInstallWithSubprocess(const bf::path& path, uid_t uid) const;
+ Result RecoveryWithSubprocess(const bf::path& path, uid_t uid) const;
+ Result UninstallWithSubprocess(const std::string& pkgid, uid_t uid) const;
+ Result InstallWithSubprocessAndKill(
+ const bf::path& path, uid_t uid, useconds_t delay) const;
+ Result MountInstallWithSubprocessAndKill(
+ const bf::path& path, uid_t uid, useconds_t delay) const;
+ Result UninstallWithSubprocessAndKill(
+ const std::string& pkgid, uid_t uid, useconds_t delay) const;
+ Result InstallPkgsWithSubprocess(
+ const std::vector<bf::path>& paths, uid_t uid) const;
+ Result MountInstallPkgsWithSubprocess(
+ const std::vector<bf::path>& paths, uid_t uid) const;
+ Result RecoveryPkgsWithSubprocess(
+ const std::vector<bf::path>& paths, uid_t uid) const;
+ Result UninstallPkgsWithSubprocess(
+ const std::vector<std::string>& pkgids, uid_t uid) const;
+ Result InstallPkgsWithSubprocessAndKill(
+ const std::vector<bf::path>& paths, uid_t uid, useconds_t delay) const;
+ Result MountInstallPkgsWithSubprocessAndKill(
+ const std::vector<bf::path>& paths, uid_t uid, useconds_t delay) const;
+
+ private:
+ Result RunSubprocess(std::vector<std::string> args) const;
+ Result RunSubprocessAndKill(std::vector<std::string> args,
+ useconds_t delay) const;
+ virtual common_installer::Subprocess CreateSubprocess() const = 0;
+};
+
+bool CheckAvailableExternalPath();
+
+bool CheckAvailableExtendedPath();
+
+bool BackupPathCopyAndRemove(const boost::filesystem::path& path);
+
+bool BackupPath(const boost::filesystem::path& path);
+
+bool RestorePathCopyAndRemove(const boost::filesystem::path& path);
+
+bool RestorePath(const boost::filesystem::path& path);
+
+std::vector<boost::filesystem::path> SetupBackupDirectories(uid_t test_uid);
+
+void UninstallAllAppsInDirectory(boost::filesystem::path dir, bool is_preload,
+ BackendInterface* backend);
+
+void UninstallAllSmokeApps(common_installer::RequestMode request_mode,
+ uid_t test_uid, BackendInterface* backend);
+
+int GetAppInstalledTime(const char* appid, uid_t uid);
+
+enum class CrashStepType {
+ PROCESS,
+ CLEAN
+};
+
+class StepCrash : public common_installer::Step {
+ public:
+ using Step::Step;
+
+ explicit StepCrash(common_installer::InstallerContext* context,
+ CrashStepType type)
+ : common_installer::Step::Step(context), type_(type) {}
+
+ common_installer::Step::Status process() override {
+ if (type_ == CrashStepType::PROCESS)
+ raise(SIGSEGV);
+ return Status::OK;
+ }
+ common_installer::Step::Status clean() override {
+ if (type_ == CrashStepType::CLEAN)
+ raise(SIGSEGV);
+ return Status::OK;
+ }
+ common_installer::Step::Status undo() override {
+ return common_installer::Step::Status::OK;
+ }
+ common_installer::Step::Status precheck() override {
+ return common_installer::Step::Status::OK;
+ }
+
+ STEP_NAME(Crash)
+
+ private:
+ CrashStepType type_;
+};
+
+} // namespace smoke_test
+
+#endif // SMOKE_TESTS_COMMON_SMOKE_UTILS_H_
--- /dev/null
+SET(PLUGIN_DIR ${SHAREDIR}/${DESTINATION_DIR}/test_samples/plugins/)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../../..)
+
+ADD_LIBRARY(${TARGET_ASSESSOR_LIB} SHARED
+ test_assessor.cc
+)
+ADD_LIBRARY(${TARGET_TEST_TAG_PLUGIN} SHARED
+ test_tag_plugin.cc
+)
+ADD_LIBRARY(${TARGET_TEST_CATEGORY_PLUGIN} SHARED
+ test_category_plugin.cc
+)
+ADD_LIBRARY(${TARGET_TEST_METADATA_PLUGIN} SHARED
+ test_metadata_plugin.cc
+)
+ADD_LIBRARY(${TARGET_TEST_TAG_FAIL_PLUGIN} SHARED
+ test_tag_fail_plugin.cc
+)
+ADD_LIBRARY(${TARGET_TEST_CATEGORY_FAIL_PLUGIN} SHARED
+ test_category_fail_plugin.cc
+)
+ADD_LIBRARY(${TARGET_TEST_METADATA_FAIL_PLUGIN} SHARED
+ test_metadata_fail_plugin.cc
+)
+
+TARGET_LINK_LIBRARIES(${TARGET_ASSESSOR_LIB} PUBLIC ${TARGET_LIBNAME_COMMON})
+TARGET_LINK_LIBRARIES(${TARGET_TEST_TAG_PLUGIN} PUBLIC ${TARGET_LIBNAME_COMMON} ${TARGET_ASSESSOR_LIB})
+TARGET_LINK_LIBRARIES(${TARGET_TEST_CATEGORY_PLUGIN} PUBLIC ${TARGET_LIBNAME_COMMON} ${TARGET_ASSESSOR_LIB})
+TARGET_LINK_LIBRARIES(${TARGET_TEST_METADATA_PLUGIN} PUBLIC ${TARGET_LIBNAME_COMMON} ${TARGET_ASSESSOR_LIB})
+TARGET_LINK_LIBRARIES(${TARGET_TEST_TAG_FAIL_PLUGIN} PUBLIC ${TARGET_LIBNAME_COMMON} ${TARGET_ASSESSOR_LIB})
+TARGET_LINK_LIBRARIES(${TARGET_TEST_CATEGORY_FAIL_PLUGIN} PUBLIC ${TARGET_LIBNAME_COMMON} ${TARGET_ASSESSOR_LIB})
+TARGET_LINK_LIBRARIES(${TARGET_TEST_METADATA_FAIL_PLUGIN} PUBLIC ${TARGET_LIBNAME_COMMON} ${TARGET_ASSESSOR_LIB})
+
+INSTALL(TARGETS ${TARGET_ASSESSOR_LIB} DESTINATION ${LIBDIR})
+INSTALL(TARGETS ${TARGET_TEST_TAG_PLUGIN} DESTINATION ${PLUGIN_DIR})
+INSTALL(TARGETS ${TARGET_TEST_CATEGORY_PLUGIN} DESTINATION ${PLUGIN_DIR})
+INSTALL(TARGETS ${TARGET_TEST_METADATA_PLUGIN} DESTINATION ${PLUGIN_DIR})
+INSTALL(TARGETS ${TARGET_TEST_TAG_FAIL_PLUGIN} DESTINATION ${PLUGIN_DIR})
+INSTALL(TARGETS ${TARGET_TEST_CATEGORY_FAIL_PLUGIN} DESTINATION ${PLUGIN_DIR})
+INSTALL(TARGETS ${TARGET_TEST_METADATA_FAIL_PLUGIN} DESTINATION ${PLUGIN_DIR})
--- /dev/null
+// Copyright (c) 2016 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 "smoke_tests/libs/test_assessor.h"
+
+namespace common_installer {
+
+const char kTagPluginName[] = "tag";
+const char kCategoryPluginName[] = "category";
+const char kMetadataPluginName[] = "metadata";
+const char kTestPackageId[] = "org.tizen.testapp";
+const char kTestApplicationId[] = "org.tizen.testapp.main";
+
+void TestAssessor::ClearResults() {
+ results.clear();
+}
+
+void TestAssessor::AddResult(const ResultLine& result,
+ const boost::optional<std::string>& error) {
+ results.insert(std::make_pair(result, error));
+}
+
+const TestAssessor::ResultStore& TestAssessor::GetResults() const {
+ return results;
+}
+
+} // namespace common_installer
--- /dev/null
+// Copyright (c) 2016 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 SMOKE_TESTS_LIBS_TEST_ASSESSOR_H_
+#define SMOKE_TESTS_LIBS_TEST_ASSESSOR_H_
+
+#include <boost/optional/optional.hpp>
+
+#include <map>
+#include <string>
+#include <tuple>
+#include <utility>
+
+#include "common/plugins/plugin.h"
+#include "common/utils/singleton.h"
+
+namespace common_installer {
+
+extern const char kTagPluginName[];
+extern const char kCategoryPluginName[];
+extern const char kMetadataPluginName[];
+extern const char kTestPackageId[];
+extern const char kTestApplicationId[];
+
+class TestAssessor : public common_installer::Singleton<TestAssessor> {
+ CRTP_DECLARE_DEFAULT_CONSTRUCTOR_CLASS(TestAssessor)
+ public:
+ using ResultLine = std::tuple<std::string, Plugin::ActionType,
+ Plugin::ProcessType>;
+ using ResultStore = std::map<ResultLine, boost::optional<std::string>>;
+
+ void ClearResults();
+ void AddResult(const ResultLine& result,
+ const boost::optional<std::string> &error);
+ const ResultStore& GetResults() const;
+
+ private:
+ ResultStore results;
+};
+
+} // namespace common_installer
+
+#endif // SMOKE_TESTS_LIBS_TEST_ASSESSOR_H_
--- /dev/null
+// Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include <boost/optional/optional.hpp>
+
+#include <pkgmgr_parser.h>
+
+#include <glib/glist.h>
+
+#include <cstring>
+#include <string>
+#include <tuple>
+
+#include "common/plugins/plugin.h"
+#include "common/utils/glist_range.h"
+
+extern "C" int PKGMGR_CATEGORY_PARSER_PLUGIN_INSTALL(
+ const char*, const char*, GList*) {
+ return -1;
+}
+
+extern "C" int PKGMGR_CATEGORY_PARSER_PLUGIN_UPGRADE(
+ const char*, const char*, GList*) {
+ return -1;
+}
+
+extern "C" int PKGMGR_CATEGORY_PARSER_PLUGIN_UNINSTALL(
+ const char*, const char*, GList*) {
+ return -1;
+}
--- /dev/null
+// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include <boost/optional/optional.hpp>
+
+#include <pkgmgr_parser.h>
+
+#include <glib/glist.h>
+
+#include <cstring>
+#include <string>
+#include <tuple>
+
+#include "common/plugins/plugin.h"
+#include "common/utils/glist_range.h"
+#include "smoke_tests/libs/test_assessor.h"
+
+namespace ci = common_installer;
+
+namespace {
+
+boost::optional<std::string> CheckArgs(
+ const char* pkgid,
+ const char* appid,
+ GList* categories) {
+ if (!pkgid)
+ return std::string("Package id is null for category plugin");
+ if (!appid)
+ return std::string("Application id is null for category plugin");
+ if (strcmp(pkgid, ci::kTestPackageId) != 0)
+ return std::string("Package id doesn't match for category plugin");
+ if (strcmp(appid, ci::kTestApplicationId) != 0)
+ return std::string("Application id doesn't match for category plugin");
+ auto range = GListRange<__category_t*>(categories);
+ if (range.Size() != 3)
+ return std::string("Metadata Glist is wrong size for category plugin");
+ bool found = false;
+ for (__category_t* category : range) {
+ if (strcmp(category->name, "http://tizen.org/category/test_category") == 0)
+ found = true;
+ }
+ if (!found)
+ return std::string("Category value not found");
+ return {};
+}
+
+} // namespace
+
+extern "C" int PKGMGR_CATEGORY_PARSER_PLUGIN_INSTALL(
+ const char* pkgid,
+ const char* appid,
+ GList* categories) {
+ ci::TestAssessor::Instance().AddResult(std::make_tuple(
+ ci::kCategoryPluginName,
+ ci::Plugin::ActionType::Install,
+ ci::Plugin::ProcessType::Main),
+ CheckArgs(pkgid, appid, categories));
+ return 0;
+}
+
+extern "C" int PKGMGR_CATEGORY_PARSER_PLUGIN_UPGRADE(
+ const char* pkgid,
+ const char* appid,
+ GList* categories) {
+ ci::TestAssessor::Instance().AddResult(std::make_tuple(
+ ci::kCategoryPluginName,
+ ci::Plugin::ActionType::Upgrade,
+ ci::Plugin::ProcessType::Main),
+ CheckArgs(pkgid, appid, categories));
+ return 0;
+}
+
+extern "C" int PKGMGR_CATEGORY_PARSER_PLUGIN_UNINSTALL(
+ const char* pkgid,
+ const char* appid,
+ GList* categories) {
+ ci::TestAssessor::Instance().AddResult(std::make_tuple(
+ ci::kCategoryPluginName,
+ ci::Plugin::ActionType::Uninstall,
+ ci::Plugin::ProcessType::Main),
+ CheckArgs(pkgid, appid, categories));
+ return 0;
+}
--- /dev/null
+// Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include <boost/optional/optional.hpp>
+
+#include <pkgmgr_parser.h>
+
+#include <glib/glist.h>
+
+#include <cstring>
+#include <string>
+#include <tuple>
+
+#include "common/plugins/plugin.h"
+#include "common/utils/glist_range.h"
+
+extern "C" int PKGMGR_MDPARSER_PLUGIN_INSTALL(
+ const char*, const char*, GList*) {
+ return -1;
+}
+
+extern "C" int PKGMGR_MDPARSER_PLUGIN_UPGRADE(
+ const char*, const char*, GList*) {
+ return -1;
+}
+
+extern "C" int PKGMGR_MDPARSER_PLUGIN_UNINSTALL(
+ const char*, const char*, GList*) {
+ return -1;
+}
--- /dev/null
+// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include <boost/optional/optional.hpp>
+
+#include <pkgmgr_parser.h>
+
+#include <glib/glist.h>
+
+#include <cstring>
+#include <string>
+#include <tuple>
+
+#include "common/plugins/plugin.h"
+#include "common/utils/glist_range.h"
+#include "smoke_tests/libs/test_assessor.h"
+
+namespace ci = common_installer;
+
+namespace {
+
+boost::optional<std::string> CheckArgs(
+ const char* pkgid,
+ const char* appid,
+ GList* metadata) {
+ if (!pkgid)
+ return std::string("Package id is null for metadata plugin");
+ if (!appid)
+ return std::string("Application id is null for metadata plugin");
+ if (strcmp(pkgid, ci::kTestPackageId) != 0)
+ return std::string("Package id doesn't match for metadata plugin");
+ if (strcmp(appid, ci::kTestApplicationId) != 0)
+ return std::string("Application id doesn't match for metadata plugin");
+ auto range = GListRange<__metadata_t*>(metadata);
+ if (range.Size() != 3)
+ return std::string("Metadata Glist is wrong size for metadata plugin");
+ bool found_a = false;
+ bool found_b = false;
+ bool found_c = false;
+ for (__metadata_t* meta : range) {
+ if (strcmp(meta->key,
+ "http://developer.samsung.com/tizen/metadata/test_metadata/key_a")
+ == 0 && strcmp(meta->value, "value_a") == 0) {
+ found_a = true;
+ }
+ if (strcmp(meta->key,
+ "http://developer.samsung.com/tizen/metadata/test_metadata/key_b")
+ == 0 && strcmp(meta->value, "value_b") == 0) {
+ found_b = true;
+ }
+ if (strcmp(meta->key,
+ "http://developer.samsung.com/tizen/metadata/test_metadata/key_c")
+ == 0 && strcmp(meta->value, "value_c") == 0) {
+ found_c = true;
+ }
+ }
+ if (!found_a)
+ return std::string("Metadata key_a incorrect or not found");
+ if (!found_b)
+ return std::string("Metadata key_b incorrect or not found");
+ if (!found_c)
+ return std::string("Metadata key_c incorrect or not found");
+ return {};
+}
+
+} // namespace
+
+extern "C" int PKGMGR_MDPARSER_PLUGIN_INSTALL(
+ const char* pkgid,
+ const char* appid,
+ GList* metadata) {
+ ci::TestAssessor::Instance().AddResult(std::make_tuple(
+ ci::kMetadataPluginName,
+ ci::Plugin::ActionType::Install,
+ ci::Plugin::ProcessType::Main),
+ CheckArgs(pkgid, appid, metadata));
+ return 0;
+}
+
+extern "C" int PKGMGR_MDPARSER_PLUGIN_UPGRADE(
+ const char* pkgid,
+ const char* appid,
+ GList* metadata) {
+ ci::TestAssessor::Instance().AddResult(std::make_tuple(
+ ci::kMetadataPluginName,
+ ci::Plugin::ActionType::Upgrade,
+ ci::Plugin::ProcessType::Main),
+ CheckArgs(pkgid, appid, metadata));
+ return 0;
+}
+
+extern "C" int PKGMGR_MDPARSER_PLUGIN_UNINSTALL(
+ const char* pkgid,
+ const char* appid,
+ GList* metadata) {
+ ci::TestAssessor::Instance().AddResult(std::make_tuple(
+ ci::kMetadataPluginName,
+ ci::Plugin::ActionType::Uninstall,
+ ci::Plugin::ProcessType::Main),
+ CheckArgs(pkgid, appid, metadata));
+ return 0;
+}
--- /dev/null
+// Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include <boost/optional/optional.hpp>
+
+#include <cstring>
+#include <string>
+#include <tuple>
+
+#include "common/plugins/plugin.h"
+
+extern "C" int PKGMGR_PARSER_PLUGIN_PRE_INSTALL(const char*) {
+ return 0;
+}
+
+extern "C" int PKGMGR_PARSER_PLUGIN_PRE_UPGRADE(const char*) {
+ return 0;
+}
+extern "C" int PKGMGR_PARSER_PLUGIN_PRE_UNINSTALL(const char*) {
+ return 0;
+}
+
+extern "C" int PKGMGR_PARSER_PLUGIN_INSTALL(xmlDocPtr, const char*) {
+ return 0;
+}
+
+extern "C" int PKGMGR_PARSER_PLUGIN_UPGRADE(xmlDocPtr, const char*) {
+ return 0;
+}
+
+extern "C" int PKGMGR_PARSER_PLUGIN_UNINSTALL(xmlDocPtr, const char*) {
+ return 0;
+}
+
+extern "C" int PKGMGR_PARSER_PLUGIN_POST_INSTALL(const char*) {
+ return -1;
+}
+
+extern "C" int PKGMGR_PARSER_PLUGIN_POST_UPGRADE(const char*) {
+ return -1;
+}
+
+extern "C" int PKGMGR_PARSER_PLUGIN_POST_UNINSTALL(const char*) {
+ return -1;
+}
--- /dev/null
+// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include <boost/optional/optional.hpp>
+
+#include <cstring>
+#include <string>
+#include <tuple>
+
+#include "common/plugins/plugin.h"
+#include "smoke_tests/libs/test_assessor.h"
+
+namespace ci = common_installer;
+
+namespace {
+
+boost::optional<std::string> CheckArgs(const char* pkgid) {
+ if (!pkgid)
+ return std::string("Package id is null for tag plugin");
+ if (strcmp(pkgid, ci::kTestPackageId) != 0)
+ return std::string("Package id doesn't match for tag plugin") +
+ "Expected: " + ci::kTestPackageId + " actual: " + pkgid;
+ return {};
+}
+
+boost::optional<std::string> CheckArgs(xmlDocPtr doc, const char* pkgid) {
+ if (!doc)
+ return std::string("XML doc pointer is null for tag plugin");
+ return CheckArgs(pkgid);
+}
+
+} // namespace
+
+extern "C" int PKGMGR_PARSER_PLUGIN_PRE_INSTALL(const char* package) {
+ ci::TestAssessor::Instance().AddResult(std::make_tuple(
+ ci::kTagPluginName,
+ ci::Plugin::ActionType::Install,
+ ci::Plugin::ProcessType::Pre),
+ CheckArgs(package));
+ return 0;
+}
+
+extern "C" int PKGMGR_PARSER_PLUGIN_PRE_UPGRADE(const char* package) {
+ ci::TestAssessor::Instance().AddResult(std::make_tuple(
+ ci::kTagPluginName,
+ ci::Plugin::ActionType::Upgrade,
+ ci::Plugin::ProcessType::Pre),
+ CheckArgs(package));
+ return 0;
+}
+extern "C" int PKGMGR_PARSER_PLUGIN_PRE_UNINSTALL(const char* package) {
+ ci::TestAssessor::Instance().AddResult(std::make_tuple(
+ ci::kTagPluginName,
+ ci::Plugin::ActionType::Uninstall,
+ ci::Plugin::ProcessType::Pre),
+ CheckArgs(package));
+ return 0;
+}
+
+extern "C" int PKGMGR_PARSER_PLUGIN_INSTALL(xmlDocPtr doc,
+ const char* package) {
+ ci::TestAssessor::Instance().AddResult(std::make_tuple(
+ ci::kTagPluginName,
+ ci::Plugin::ActionType::Install,
+ ci::Plugin::ProcessType::Main),
+ CheckArgs(doc, package));
+ return 0;
+}
+
+extern "C" int PKGMGR_PARSER_PLUGIN_UPGRADE(xmlDocPtr doc,
+ const char* package) {
+ ci::TestAssessor::Instance().AddResult(std::make_tuple(
+ ci::kTagPluginName,
+ ci::Plugin::ActionType::Upgrade,
+ ci::Plugin::ProcessType::Main),
+ CheckArgs(doc, package));
+ return 0;
+}
+
+extern "C" int PKGMGR_PARSER_PLUGIN_UNINSTALL(xmlDocPtr doc,
+ const char* package) {
+ ci::TestAssessor::Instance().AddResult(std::make_tuple(
+ ci::kTagPluginName,
+ ci::Plugin::ActionType::Uninstall,
+ ci::Plugin::ProcessType::Main),
+ CheckArgs(doc, package));
+ return 0;
+}
+
+extern "C" int PKGMGR_PARSER_PLUGIN_POST_INSTALL(const char* package) {
+ ci::TestAssessor::Instance().AddResult(std::make_tuple(
+ ci::kTagPluginName,
+ ci::Plugin::ActionType::Install,
+ ci::Plugin::ProcessType::Post),
+ CheckArgs(package));
+ return 0;
+}
+
+extern "C" int PKGMGR_PARSER_PLUGIN_POST_UPGRADE(const char* package) {
+ ci::TestAssessor::Instance().AddResult(std::make_tuple(
+ ci::kTagPluginName,
+ ci::Plugin::ActionType::Upgrade,
+ ci::Plugin::ProcessType::Post),
+ CheckArgs(package));
+ return 0;
+}
+
+extern "C" int PKGMGR_PARSER_PLUGIN_POST_UNINSTALL(const char* package) {
+ ci::TestAssessor::Instance().AddResult(std::make_tuple(
+ ci::kTagPluginName,
+ ci::Plugin::ActionType::Uninstall,
+ ci::Plugin::ProcessType::Post),
+ CheckArgs(package));
+ return 0;
+}
--- /dev/null
+// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include <boost/filesystem/path.hpp>
+#include <gtest/gtest.h>
+
+#include <memory>
+#include <iterator>
+#include <tuple>
+
+#include "common/installer_context.h"
+#include "common/step/configuration/step_parse_manifest.h"
+#include "common/plugins/plugin_factory.h"
+#include "common/plugins/plugin_list_parser.h"
+#include "common/plugins/plugin_manager.h"
+#include "common/plugins/plugin_xml_parser.h"
+#include "smoke_tests/libs/test_assessor.h"
+
+namespace bf = boost::filesystem;
+namespace ci = common_installer;
+
+namespace {
+
+const char kPluginsTestFiles[] =
+ "/usr/share/app-installers-ut/test_samples/plugins";
+
+const bf::path kTestTagPlugin =
+ bf::path(kPluginsTestFiles) / "libtest-tag-plugin.so";
+const bf::path kTestCategoryPlugin =
+ bf::path(kPluginsTestFiles) / "libtest-category-plugin.so";
+const bf::path kTestMetadataPlugin =
+ bf::path(kPluginsTestFiles) / "libtest-metadata-plugin.so";
+const bf::path kTestValidPluginsListDir =
+ bf::path(kPluginsTestFiles) / "valid-parser-plugins";
+const bf::path kTestValidFailPluginsListDir =
+ bf::path(kPluginsTestFiles) / "valid-fail-parser-plugins";
+const bf::path kTestInvalidPluginsListDir =
+ bf::path(kPluginsTestFiles) / "invalid-parser-plugins";
+
+void CheckCall(
+ const ci::TestAssessor::ResultStore& store,
+ const std::string& name,
+ ci::Plugin::ActionType action) {
+ auto iter_pre = store.find(
+ std::make_tuple(name, action, ci::Plugin::ProcessType::Pre));
+ auto iter_main = store.find(
+ std::make_tuple(name, action, ci::Plugin::ProcessType::Main));
+ auto iter_post = store.find(
+ std::make_tuple(name, action, ci::Plugin::ProcessType::Post));
+ ASSERT_NE(iter_pre, store.end());
+ ASSERT_NE(iter_main, store.end());
+ ASSERT_NE(iter_post, store.end());
+
+ // Error is not set
+ ASSERT_TRUE(!iter_pre->second) << *iter_pre->second;
+ ASSERT_TRUE(!iter_main->second) << *iter_main->second;
+ ASSERT_TRUE(!iter_post->second) << *iter_post->second;
+
+ // Check order of calling
+ auto ts_pre = std::distance(store.begin(), iter_pre);
+ auto ts_main = std::distance(store.begin(), iter_main);
+ auto ts_post = std::distance(store.begin(), iter_post);
+ ASSERT_GT(ts_main, ts_pre);
+ ASSERT_GT(ts_post, ts_main);
+}
+
+void CheckCallMain(
+ const ci::TestAssessor::ResultStore& store,
+ const std::string& name,
+ ci::Plugin::ActionType action) {
+ auto iter_main = store.find(
+ std::make_tuple(name, action, ci::Plugin::ProcessType::Main));
+ ASSERT_NE(iter_main, store.end());
+
+ // Error is not set
+ ASSERT_TRUE(!iter_main->second) << *iter_main->second;
+}
+
+} // namespace
+
+namespace common_installer {
+
+class PluginTest : public testing::Test {
+};
+
+TEST_F(PluginTest, PluginsXmlParser_Valid) {
+ bf::path manifest = bf::path(kPluginsTestFiles) / "tizen-manifest.xml";
+ PluginsXmlParser parser(manifest);
+ ASSERT_TRUE(parser.Parse());
+ ASSERT_NE(parser.doc_ptr(), nullptr);
+ auto tags = parser.tags_list();
+ ASSERT_NE(std::find(tags.begin(), tags.end(), "author"), tags.end());
+ ASSERT_NE(std::find(tags.begin(), tags.end(), "description"), tags.end());
+ ASSERT_NE(std::find(tags.begin(), tags.end(), "ui-application"), tags.end());
+ ASSERT_NE(std::find(tags.begin(), tags.end(), "test"), tags.end());
+
+ ASSERT_EQ(std::find(tags.begin(), tags.end(), "label"), tags.end());
+ ASSERT_EQ(std::find(tags.begin(), tags.end(), "app-control"), tags.end());
+ ASSERT_EQ(std::find(tags.begin(), tags.end(), "datacontrol"), tags.end());
+ ASSERT_EQ(std::find(tags.begin(), tags.end(), "mime"), tags.end());
+ ASSERT_EQ(std::find(tags.begin(), tags.end(), "operation"), tags.end());
+ ASSERT_EQ(std::find(tags.begin(), tags.end(), "uri"), tags.end());
+ ASSERT_EQ(std::find(tags.begin(), tags.end(), "key"), tags.end());
+ ASSERT_EQ(std::find(tags.begin(), tags.end(), "name"), tags.end());
+ ASSERT_EQ(std::find(tags.begin(), tags.end(), ""), tags.end());
+}
+
+TEST_F(PluginTest, PluginsXmlParser_Invalid) {
+ bf::path manifest = bf::path(kPluginsTestFiles) / "invalid_manifest.xml";
+ PluginsXmlParser parser(manifest);
+ ASSERT_FALSE(parser.Parse());
+}
+
+TEST_F(PluginTest, PluginsListParser_Valid) {
+ PluginsListParser parser(kTestValidPluginsListDir);
+ ASSERT_TRUE(parser.Parse());
+ auto list = parser.PluginInfoList();
+ ASSERT_EQ(list.size(), 3);
+ for (auto list_item : list) {
+ if (list_item->type() == "tag") {
+ ASSERT_EQ(list_item->name(), "test");
+ ASSERT_EQ(list_item->path(), kTestTagPlugin.string());
+ } else if (list_item->type() == "category") {
+ ASSERT_EQ(list_item->name(), "http://tizen.org/category/test_category");
+ ASSERT_EQ(list_item->path(), kTestCategoryPlugin.string());
+ } else if (list_item->type() == "metadata") {
+ ASSERT_EQ(list_item->name(),
+ "http://developer.samsung.com/tizen/metadata/test_metadata");
+ ASSERT_EQ(list_item->path(), kTestMetadataPlugin.string());
+ }
+ }
+}
+
+TEST_F(PluginTest, PluginsListParser_Invalid) {
+ PluginsListParser parser(kTestInvalidPluginsListDir);
+ ASSERT_FALSE(parser.Parse());
+}
+
+TEST_F(PluginTest, PluginFactory_CreatingPlugins) {
+ PluginFactory factory;
+ PluginInfo tag_info("tag", "test", kTestTagPlugin.string(), false);
+ ASSERT_TRUE(!!factory.CreatePluginByPluginInfo(tag_info));
+ PluginInfo category_info("category", "category",
+ kTestCategoryPlugin.string(), false);
+ ASSERT_TRUE(!!factory.CreatePluginByPluginInfo(category_info));
+ PluginInfo metadata_info("metadata", "metadata",
+ kTestMetadataPlugin.string(), false);
+ ASSERT_TRUE(!!factory.CreatePluginByPluginInfo(metadata_info));
+ PluginInfo tag_info2("tag", "test", kTestTagPlugin.string(), true);
+ ASSERT_TRUE(!!factory.CreatePluginByPluginInfo(tag_info2));
+ PluginInfo category_info2("category", "category",
+ kTestCategoryPlugin.string(), true);
+ ASSERT_TRUE(!!factory.CreatePluginByPluginInfo(category_info2));
+ PluginInfo metadata_info2("metadata", "metadata",
+ kTestMetadataPlugin.string(), true);
+ ASSERT_TRUE(!!factory.CreatePluginByPluginInfo(metadata_info2));
+ PluginInfo missing_info("tag", "test",
+ "/usr/lib/libmynonexistingplugin.so", false);
+ ASSERT_FALSE(!!factory.CreatePluginByPluginInfo(missing_info));
+ PluginInfo new_info("newtype", "test", kTestTagPlugin.string(), false);
+ ASSERT_FALSE(!!factory.CreatePluginByPluginInfo(new_info));
+}
+
+#define CALLING_PLUGIN_FOR_ACTION_TEST(NAME, ACTION) \
+ TEST_F(PluginTest, PluginManager_CallingPlugins ## NAME) { \
+ TestAssessor::Instance().ClearResults(); \
+ \
+ bf::path manifest = bf::path(kPluginsTestFiles) / "tizen-manifest.xml"; \
+ bf::path list = kTestValidPluginsListDir; \
+ \
+ InstallerContext context; \
+ context.unpacked_dir_path.set(manifest.parent_path()); \
+ configuration::StepParseManifest step(&context, \
+ configuration::StepParseManifest::ManifestLocation::PACKAGE, \
+ configuration::StepParseManifest::StoreLocation::NORMAL); \
+ ASSERT_EQ(step.process(), Step::Status::OK); \
+ PluginManager manager(manifest, list, context.pkgid.get(), \
+ context.manifest_data.get(), getuid()); \
+ ASSERT_TRUE(manager.LoadPlugins(ACTION)); \
+ manager.RunPlugins(ACTION); \
+ auto result = TestAssessor::Instance().GetResults(); \
+ ASSERT_EQ(result.size(), 5); \
+ CheckCall(result, kTagPluginName, ACTION); \
+ CheckCallMain(result, kMetadataPluginName, ACTION); \
+ CheckCallMain(result, kCategoryPluginName, ACTION); \
+ }
+
+CALLING_PLUGIN_FOR_ACTION_TEST(Install, Plugin::ActionType::Install)
+CALLING_PLUGIN_FOR_ACTION_TEST(Upgrade, Plugin::ActionType::Upgrade)
+CALLING_PLUGIN_FOR_ACTION_TEST(Uninstall, Plugin::ActionType::Uninstall)
+
+#define CALLING_PLUGIN_FOR_FAIL_ACTION_TEST(NAME, ACTION) \
+ TEST_F(PluginTest, PluginManager_CallingFailPlugins ## NAME) { \
+ std::string kind_of_plugins[3] = {"category", "metadata", "tag"}; \
+ for (auto name : kind_of_plugins) { \
+ std::string manifest_dir = name + "-manifest"; \
+ bf::path manifest = \
+ bf::path(kPluginsTestFiles) / manifest_dir / "tizen-manifest.xml"; \
+ bf::path list = kTestValidFailPluginsListDir; \
+ \
+ InstallerContext context; \
+ context.unpacked_dir_path.set(manifest.parent_path()); \
+ configuration::StepParseManifest step(&context, \
+ configuration::StepParseManifest::ManifestLocation::PACKAGE, \
+ configuration::StepParseManifest::StoreLocation::NORMAL); \
+ ASSERT_EQ(step.process(), Step::Status::OK); \
+ PluginManager manager(manifest, list, context.pkgid.get(), \
+ context.manifest_data.get(), getuid()); \
+ ASSERT_TRUE(manager.LoadPlugins(ACTION)); \
+ ASSERT_FALSE(manager.RunPlugins(ACTION)); \
+ } \
+ }
+
+CALLING_PLUGIN_FOR_FAIL_ACTION_TEST(Install, Plugin::ActionType::Install)
+CALLING_PLUGIN_FOR_FAIL_ACTION_TEST(Upgrade, Plugin::ActionType::Upgrade)
+CALLING_PLUGIN_FOR_FAIL_ACTION_TEST(Uninstall, Plugin::ActionType::Uninstall)
+
+} // namespace common_installer
--- /dev/null
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include <boost/filesystem/path.hpp>
+#include <gtest/gtest.h>
+
+#include <memory>
+
+#include "common/certificate_validation.h"
+
+namespace bf = boost::filesystem;
+
+namespace common_installer {
+namespace security {
+
+class SignatureValidatorTest : public testing::Test {
+ protected:
+ std::unique_ptr<bf::path> signature_file;
+};
+
+// Tests signature verifier with proper signatures
+TEST_F(SignatureValidatorTest, HandlesInitializedSignatureDir) {
+ signature_file.reset(new bf::path(
+ "/usr/share/app-installers-ut/test_samples/good_signatures"));
+ PrivilegeLevel level = PrivilegeLevel::UNTRUSTED;
+ common_installer::CertificateInfo cert_info;
+ std::string error;
+ EXPECT_TRUE(ValidateSignatures(*signature_file, &level, &cert_info, true,
+ &error));
+}
+
+// Tests signature verifier with signature directory containing bad signatures
+TEST_F(SignatureValidatorTest, HandlesBadSignatureDir) {
+ signature_file.reset(new bf::path(
+ "/usr/share/app-installers-ut/test_samples/bad_signatures"));
+ PrivilegeLevel level = PrivilegeLevel::UNTRUSTED;
+ common_installer::CertificateInfo cert_info;
+ std::string error;
+ EXPECT_FALSE(ValidateSignatures(*signature_file, &level, &cert_info, true,
+ &error));
+}
+
+} // namespace security
+} // namespace common_installer
--- /dev/null
+<Signature xmlns="http://www.w3.org/2000/09/xmldsig#" Id="AuthorSignature">
+<SignedInfo>
+<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></CanonicalizationMethod>
+<SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"></SignatureMethod>
+<Reference URI="config.xml">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>iEX0LuZs81Q6Du/SkXgbMd+Qa6puMxgyRUCLqhrfpJ8=</DigestValue>
+</Reference>
+<Reference URI="icon.png">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>1d0oEZHqPn+QzNzGIHwj9ODby6x9ggFs9uOsav6jPNs=</DigestValue>
+</Reference>
+<Reference URI="index.html">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>rJOIi81O4OG/Gar/hwrjvD623MpScv6TMdurRZgzDf0=</DigestValue>
+</Reference>
+<Reference URI="version.txt">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>MjYb9c/C/J56bHY6rlIjfDqkpjFtsUBjLLkco/rcfFY=</DigestValue>
+</Reference>
+<Reference URI="#prop">
+<Transforms>
+<Transform Algorithm="http://www.w3.org/2006/12/xml-c14n11"></Transform>
+</Transforms>
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>lpo8tUDs054eLlBQXiDPVDVKfw30ZZdtkRs1jd7H5K8=</DigestValue>
+</Reference>
+</SignedInfo>
+<SignatureValue>
+c7Jd7btw6Bi9MxzKVv6JY9xcegxv42DhOzZhyrjz3EMN/60dhcGJClfKBY39FwH6exMajoThyFIW
+djtnp7pqIiQJCJkGRs0vAQThcm8JniVSbUwHMcMw7WjAW5VPsLQZKmEe16YW00YkoT6KfZLC1ySw
+48WNrHrCrTcj6LZRrld=
+</SignatureValue>
+<KeyInfo>
+<X509Data>
+<X509Certificate>
+MIIC2zCCAcOgAwIBAgIGAUudC0tkMA0GCSqGSIb3DQEBBQUAMFYxGjAYBgNVBAoMEVRpemVuIEFz
+c29jaWF0aW9uMRowGAYDVQQLDBFUaXplbiBBc3NvY2lhdGlvbjEcMBoGA1UEAwwTVGl6ZW4gRGV2
+ZWxvcGVycyBDQTAeFw0xMjExMDEwMDAwMDBaFw0xOTAxMDEwMDAwMDBaMFcxCzAJBgNVBAYTAlBM
+MQ8wDQYDVQQHDAZXYXJzYXcxEDAOBgNVBAoMB1NhbXN1bmcxFDASBgNVBAsMC1dlYlBsYXRmb3Jt
+MQ8wDQYDVQQDDAZhdXRob3IwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM0kQ8aPoKnJaBjk
+3ET7XdOS5C3ueSemfA8tYNihWQ3VX95CKX38ARLpaAGRSfOdo2L1vTIBtaO/UWEEl/XKQzqwem22
+A9UuLwl0rJNDeoq5Xz5oJD1z9eA+uuNde6cAcPmxRQDsilnVZNHlpATdDOeKUSs8+Y5UxPDz1c6j
+kUTpAgMBAAGjMjAwMAwGA1UdEwEB/wQCMAAwCwYDVR0PBAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUF
+BwMDMA0GCSqGSIb3DQEBBQUAA4IBAQC2kGzwMPMgxRrAi3ZaRu+i8x2ApZEWW4Y5uaZ9s7p4483A
+l+RBZ1/zHhkmZaekhCm2YwOpWIkXLiQc2wm9YRq+W1OorrArl/wgxtpO7hajlCxDS3X8GgJqCy7v
+8vQYTBvNXayQaRB496mC9lLZDjRL9ycYnPk55eimL3HEYclbibDjOvks4bdN/fedA8jovir+wA+b
+tIC+GGkiwGco6URdxigydxdpNEwRECCl78YVybf9agKeowXL08kwDZN9DAHCixu76kw1qtpfwm3T
+t/lz7VB1pDFhjzfuG6runH4H257bBYLkJnSBchiNItMuK2zvTVP8HsQmBeOLAFGtsoas
+</X509Certificate>
+<X509Certificate>
+MIIDOTCCAiGgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMRowGAYDVQQKDBFUaXplbiBBc3NvY2lh
+dGlvbjEaMBgGA1UECwwRVGl6ZW4gQXNzb2NpYXRpb24xHjAcBgNVBAMMFVRpemVuIERldmVsb3Bl
+cnMgUm9vdDAeFw0xMjAxMDEwMDAwMDBaFw0yNzAxMDEwMDAwMDBaMFYxGjAYBgNVBAoMEVRpemVu
+IEFzc29jaWF0aW9uMRowGAYDVQQLDBFUaXplbiBBc3NvY2lhdGlvbjEcMBoGA1UEAwwTVGl6ZW4g
+RGV2ZWxvcGVycyBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANVGhRGmMIUyBA7o
+PCz8Sxut6z6HNkF4oDIuzuKaMzRYPeWodwe9O0gmqAkToQHfwg2giRhE5GoPld0fq+OYMMwSasCu
+g8dwODx1eDeSYVuOLWRxpAmbTXOsSFi6VoWeyaPEm18JBHvZBsU5YQtgZ6Kp7MqzvQg3pXOxtajj
+vyHxiatJl+xXrHgcXC1wgyG3buty7u/Fi2mvKXJ0PRJcCjjK81dqe/Vr20sRUCrbk02zbm5ggFt/
+jIEhV8wbFRQpliobc7J4dSTKhFfrqGM8rdd54LYhD7gSI1CFSe16pUXfcVR7FhJztRaiGLnCrwBE
+dyTZ248+D4L/qR/D0axb3jcCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOC
+AQEAnOXXQ/1O/QTDHyrmQDtFziqPY3xWlJBqJtEqXiT7Y+Ljpe66e+Ee/OjQMlZe8gu21/8cKklH
+95RxjopMWCVedXDUbWdvS2+CdyvVW/quT2E0tjqIzXDekUTYwwhlPWlGxvfj3VsxqSFq3p8Brl04
+1Gx5RKAGyKVsMfTLhbbwSWwApuBUxYfcNpKwLWGPXkysu+HctY03OKv4/xKBnVWiN8ex/Sgesi0M
++OBAOMdZMPK32uJBTeKFx1xZgTLIhk45V0hPOomPjZloiv0LSS11eyd451ufjW0iHRE7WlpR6EvI
+W6TFyZgMpQq+kg4hWl2SBTf3s2VI8Ygz7gj8TMlClg==
+</X509Certificate>
+</X509Data>
+</KeyInfo>
+<Object Id="prop"><SignatureProperties xmlns:dsp="http://www.w3.org/2009/xmldsig-properties"><SignatureProperty Id="profile" Target="#AuthorSignature"><dsp:Profile URI="http://www.w3.org/ns/widgets-digsig#profile"></dsp:Profile></SignatureProperty><SignatureProperty Id="role" Target="#AuthorSignature"><dsp:Role URI="http://www.w3.org/ns/widgets-digsig#role-author"></dsp:Role></SignatureProperty><SignatureProperty Id="identifier" Target="#AuthorSignature"><dsp:Identifier></dsp:Identifier></SignatureProperty></SignatureProperties></Object>
+</Signature>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<widget xmlns="http://www.w3.org/ns/widgets" xmlns:tizen="http://tizen.org/ns/widgets" id="http://yourdomain/AppInstallersTest" version="1.0.0" viewmodes="maximized">
+ <tizen:application id="ZK6wgb4nwt.AppInstallersTest" package="ZK6wgb4nwt" required_version="2.3"/>
+ <content src="index.html"/>
+ <feature name="http://tizen.org/feature/screen.size.all"/>
+ <icon src="icon.png"/>
+ <name>AppInstallersTest</name>
+ <tizen:profile name="mobile"/>
+</widget>
--- /dev/null
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
+ <meta name="description" content="Tizen basic template generated by Tizen Web IDE"/>
+
+ <title>Tizen Web IDE - Tizen - Tizen basic Application</title>
+</head>
+
+<body>
+ <header>
+ <hgroup>
+ <h1>Tizen app</h1>
+ <h2>An empty template of tizen</h2>
+ </hgroup>
+ </header>
+
+ <nav>
+ <ul>
+ <li><a href="#">Home</a></li>
+ <li><a href="#">About Us</a></li>
+ <li><a href="#">Contact Us</a></li>
+ </ul>
+ </nav>
+
+ <article>
+ <p>This is an empty template of Tizen Web Application. Tizen will support multiple device categories:</p>
+ <ul>
+ <li>smartphones, tablets and smart TVs
+ <li>netbooks, in-vehicle infotainment devices
+ </ul>
+ <section>
+ <p>This is a basic section of a document.</p>
+ <p>The following button displays a time using JavaScript.</p>
+ <div id="divbutton1">
+ <button>Clock</button>
+ </div>
+ </section>
+ </article>
+
+ <footer>
+ <p>© 2012 Company Name. All rights reserved.</p>
+ </footer>
+</body>
+</html>
--- /dev/null
+<Signature xmlns="http://www.w3.org/2000/09/xmldsig#" Id="DistributorSignature">
+<SignedInfo>
+<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></CanonicalizationMethod>
+<SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"></SignatureMethod>
+<Reference URI="author-signature.xml">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>opfWp60FUsKzpdQBgTp3x31PB1GzC9mS6M7B6n2m63c=</DigestValue>
+</Reference>
+<Reference URI="config.xml">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>iEX0LuZs81Q6Du/SkXgbMd+Qa6puMxgyRUCLqhrfpJ8=</DigestValue>
+</Reference>
+<Reference URI="icon.png">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>1d0oEZHqPn+QzNzGIHwj9ODby6x9ggFs9uOsav6jPNs=</DigestValue>
+</Reference>
+<Reference URI="index.html">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>rJOIi81O4OG/Gar/hwrjvD623MpScv6TMdurRZgzDf0=</DigestValue>
+</Reference>
+<Reference URI="version.txt">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>MjYb9c/C/J56bHY6rlIjfDqkpjFtsUBjLLkco/rcfFY=</DigestValue>
+</Reference>
+<Reference URI="#prop">
+<Transforms>
+<Transform Algorithm="http://www.w3.org/2006/12/xml-c14n11"></Transform>
+</Transforms>
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>u/jU3U4Zm5ihTMSjKGlGYbWzDfRkGphPPHx3gJIYEJ4=</DigestValue>
+</Reference>
+</SignedInfo>
+<SignatureValue>
+O6yHkXzPKe+8nGxjh06ivDImxKSKygVOgvZzmKKHVWn879K2K8vY08/f7FXKG+zRXEouXbZd7aip
+IGyOCpulXUzESCQMIiffzMVgTV0Ho+kXx44xbME/XKy7DJYpZOvZFXX1S9ZXvU2BmmgHtWWLS/gc
+sFiYVHpRxLnify3npXF=
+</SignatureValue>
+<KeyInfo>
+<X509Data>
+<X509Certificate>
+MIICmzCCAgQCCQDXI7WLdVZwiTANBgkqhkiG9w0BAQUFADCBjzELMAkGA1UEBhMCS1IxDjAMBgNV
+BAgMBVN1d29uMQ4wDAYDVQQHDAVTdXdvbjEWMBQGA1UECgwNVGl6ZW4gVGVzdCBDQTEiMCAGA1UE
+CwwZVGl6ZW4gRGlzdHJpYnV0b3IgVGVzdCBDQTEkMCIGA1UEAwwbVGl6ZW4gUHVibGljIERpc3Ry
+aWJ1dG9yIENBMB4XDTEyMTAyOTEzMDMwNFoXDTIyMTAyNzEzMDMwNFowgZMxCzAJBgNVBAYTAktS
+MQ4wDAYDVQQIDAVTdXdvbjEOMAwGA1UEBwwFU3V3b24xFjAUBgNVBAoMDVRpemVuIFRlc3QgQ0Ex
+IjAgBgNVBAsMGVRpemVuIERpc3RyaWJ1dG9yIFRlc3QgQ0ExKDAmBgNVBAMMH1RpemVuIFB1Ymxp
+YyBEaXN0cmlidXRvciBTaWduZXIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALtMvlc5hENK
+90ZdA+y66+Sy0enD1gpZDBh5T9RP0oRsptJv5jjNTseQbQi0SZOdOXb6J7iQdlBCtR343RpIEz8H
+mrBy7mSY7mgwoU4EPpp4CTSUeAuKcmvrNOngTp5Hv7Ngf02TTHOLK3hZLpGayaDviyNZB5PdqQdB
+hokKjzAzAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAvGp1gxxAIlFfhJH1efjb9BJK/rtRkbYn9+Ez
+GEbEULg1svsgnyWisFimI3uFvgI/swzr1eKVY3Sc8MQ3+Fdy3EkbDZ2+WAubhcEkorTWjzWz2fL1
+vKaYjeIsuEX6TVRUugHWudPzcEuQRLQf8ibZWjbQdBmpeQYBMg5x+xKLCJc=
+</X509Certificate>
+<X509Certificate>
+MIICtDCCAh2gAwIBAgIJAMDbehElPNKvMA0GCSqGSIb3DQEBBQUAMIGVMQswCQYDVQQGEwJLUjEO
+MAwGA1UECAwFU3V3b24xDjAMBgNVBAcMBVN1d29uMRYwFAYDVQQKDA1UaXplbiBUZXN0IENBMSMw
+IQYDVQQLDBpUVGl6ZW4gRGlzdHJpYnV0b3IgVGVzdCBDQTEpMCcGA1UEAwwgVGl6ZW4gUHVibGlj
+IERpc3RyaWJ1dG9yIFJvb3QgQ0EwHhcNMTIxMDI5MTMwMjUwWhcNMjIxMDI3MTMwMjUwWjCBjzEL
+MAkGA1UEBhMCS1IxDjAMBgNVBAgMBVN1d29uMQ4wDAYDVQQHDAVTdXdvbjEWMBQGA1UECgwNVGl6
+ZW4gVGVzdCBDQTEiMCAGA1UECwwZVGl6ZW4gRGlzdHJpYnV0b3IgVGVzdCBDQTEkMCIGA1UEAwwb
+VGl6ZW4gUHVibGljIERpc3RyaWJ1dG9yIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDe
+OTS/3nXvkDEmsFCJIvRlQ3RKDcxdWJJp625pFqHdmoJBdV+x6jl1raGK2Y1sp2Gdvpjc/z92yzAp
+bE/UVLPh/tRNZPeGhzU4ejDDm7kzdr2f7Ia0U98K+OoY12ucwg7TYNItj9is7Cj4blGfuMDzd2ah
+2AgnCGlwNwV/pv+uVQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBACqJ
+KO33YdoGudwanZIxMdXuxnnD9R6u72ltKk1S4zPfMJJv482CRGCI4FK6djhlsI4i0Lt1SVIJEed+
+yc3qckGm19dW+4xdlkekon7pViEBWuyHw8OWv3RXtTum1+PGHjBJ2eYY4ZKIpz73U/1NC16sTB/0
+VhfnkHwPltmrpYVe
+</X509Certificate>
+</X509Data>
+</KeyInfo>
+<Object Id="prop"><SignatureProperties xmlns:dsp="http://www.w3.org/2009/xmldsig-properties"><SignatureProperty Id="profile" Target="#DistributorSignature"><dsp:Profile URI="http://www.w3.org/ns/widgets-digsig#profile"></dsp:Profile></SignatureProperty><SignatureProperty Id="role" Target="#DistributorSignature"><dsp:Role URI="http://www.w3.org/ns/widgets-digsig#role-distributor"></dsp:Role></SignatureProperty><SignatureProperty Id="identifier" Target="#DistributorSignature"><dsp:Identifier></dsp:Identifier></SignatureProperty></SignatureProperties></Object>
+</Signature>
--- /dev/null
+<Signature xmlns="http://www.w3.org/2000/09/xmldsig#" Id="AuthorSignature">
+<SignedInfo>
+<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></CanonicalizationMethod>
+<SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"></SignatureMethod>
+<Reference URI="config.xml">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>iEX0LuZs81Q6Du/SkXgbMd+Qa6puMxgyRUCLqhrfpJ8=</DigestValue>
+</Reference>
+<Reference URI="icon.png">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>1d0oEZHqPn+QzNzGIHwj9ODby6x9ggFs9uOsav6jPNs=</DigestValue>
+</Reference>
+<Reference URI="index.html">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>rJOIi81O4OG/Gar/hwrjvD623MpScv6TMdurRZgzDf0=</DigestValue>
+</Reference>
+<Reference URI="version.txt">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>MjYb9c/C/J56bHY6rlIjfDqkpjFtsUBjLLkco/rcfFY=</DigestValue>
+</Reference>
+<Reference URI="#prop">
+<Transforms>
+<Transform Algorithm="http://www.w3.org/2006/12/xml-c14n11"></Transform>
+</Transforms>
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>lpo8tUDs054eLlBQXiDPVDVKfw30ZZdtkRs1jd7H5K8=</DigestValue>
+</Reference>
+</SignedInfo>
+<SignatureValue>
+c7Jd7btw6Bi9MxzKVv6JY9xcegxv42DhOzZhyrjz3EMN/60dhcGJClfKBY39FwH6exMajoThyFIW
+djtnp7pqIiQJCJkGRs0vAQThcm8JniVSbUwHMcMw7WjAW5VPsLQZKmEe16YW00YkoT6KfZLC1ySw
+48WNrHrCrTcj6LZRrlc=
+</SignatureValue>
+<KeyInfo>
+<X509Data>
+<X509Certificate>
+MIIC2zCCAcOgAwIBAgIGAUudC0tkMA0GCSqGSIb3DQEBBQUAMFYxGjAYBgNVBAoMEVRpemVuIEFz
+c29jaWF0aW9uMRowGAYDVQQLDBFUaXplbiBBc3NvY2lhdGlvbjEcMBoGA1UEAwwTVGl6ZW4gRGV2
+ZWxvcGVycyBDQTAeFw0xMjExMDEwMDAwMDBaFw0xOTAxMDEwMDAwMDBaMFcxCzAJBgNVBAYTAlBM
+MQ8wDQYDVQQHDAZXYXJzYXcxEDAOBgNVBAoMB1NhbXN1bmcxFDASBgNVBAsMC1dlYlBsYXRmb3Jt
+MQ8wDQYDVQQDDAZhdXRob3IwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM0kQ8aPoKnJaBjk
+3ET7XdOS5C3ueSemfA8tYNihWQ3VX95CKX38ARLpaAGRSfOdo2L1vTIBtaO/UWEEl/XKQzqwem22
+A9UuLwl0rJNDeoq5Xz5oJD1z9eA+uuNde6cAcPmxRQDsilnVZNHlpATdDOeKUSs8+Y5UxPDz1c6j
+kUTpAgMBAAGjMjAwMAwGA1UdEwEB/wQCMAAwCwYDVR0PBAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUF
+BwMDMA0GCSqGSIb3DQEBBQUAA4IBAQC2kGzwMPMgxRrAi3ZaRu+i8x2ApZEWW4Y5uaZ9s7p4483A
+l+RBZ1/zHhkmZaekhCm2YwOpWIkXLiQc2wm9YRq+W1OorrArl/wgxtpO7hajlCxDS3X8GgJqCy7v
+8vQYTBvNXayQaRB496mC9lLZDjRL9ycYnPk55eimL3HEYclbibDjOvks4bdN/fedA8jovir+wA+b
+tIC+GGkiwGco6URdxigydxdpNEwRECCl78YVybf9agKeowXL08kwDZN9DAHCixu76kw1qtpfwm3T
+t/lz7VB1pDFhjzfuG6runH4H257bBYLkJnSBchiNItMuK2zvTVP8HsQmBeOLAFGtsoas
+</X509Certificate>
+<X509Certificate>
+MIIDOTCCAiGgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMRowGAYDVQQKDBFUaXplbiBBc3NvY2lh
+dGlvbjEaMBgGA1UECwwRVGl6ZW4gQXNzb2NpYXRpb24xHjAcBgNVBAMMFVRpemVuIERldmVsb3Bl
+cnMgUm9vdDAeFw0xMjAxMDEwMDAwMDBaFw0yNzAxMDEwMDAwMDBaMFYxGjAYBgNVBAoMEVRpemVu
+IEFzc29jaWF0aW9uMRowGAYDVQQLDBFUaXplbiBBc3NvY2lhdGlvbjEcMBoGA1UEAwwTVGl6ZW4g
+RGV2ZWxvcGVycyBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANVGhRGmMIUyBA7o
+PCz8Sxut6z6HNkF4oDIuzuKaMzRYPeWodwe9O0gmqAkToQHfwg2giRhE5GoPld0fq+OYMMwSasCu
+g8dwODx1eDeSYVuOLWRxpAmbTXOsSFi6VoWeyaPEm18JBHvZBsU5YQtgZ6Kp7MqzvQg3pXOxtajj
+vyHxiatJl+xXrHgcXC1wgyG3buty7u/Fi2mvKXJ0PRJcCjjK81dqe/Vr20sRUCrbk02zbm5ggFt/
+jIEhV8wbFRQpliobc7J4dSTKhFfrqGM8rdd54LYhD7gSI1CFSe16pUXfcVR7FhJztRaiGLnCrwBE
+dyTZ248+D4L/qR/D0axb3jcCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOC
+AQEAnOXXQ/1O/QTDHyrmQDtFziqPY3xWlJBqJtEqXiT7Y+Ljpe66e+Ee/OjQMlZe8gu21/8cKklH
+95RxjopMWCVedXDUbWdvS2+CdyvVW/quT2E0tjqIzXDekUTYwwhlPWlGxvfj3VsxqSFq3p8Brl04
+1Gx5RKAGyKVsMfTLhbbwSWwApuBUxYfcNpKwLWGPXkysu+HctY03OKv4/xKBnVWiN8ex/Sgesi0M
++OBAOMdZMPK32uJBTeKFx1xZgTLIhk45V0hPOomPjZloiv0LSS11eyd451ufjW0iHRE7WlpR6EvI
+W6TFyZgMpQq+kg4hWl2SBTf3s2VI8Ygz7gj8TMlClg==
+</X509Certificate>
+</X509Data>
+</KeyInfo>
+<Object Id="prop"><SignatureProperties xmlns:dsp="http://www.w3.org/2009/xmldsig-properties"><SignatureProperty Id="profile" Target="#AuthorSignature"><dsp:Profile URI="http://www.w3.org/ns/widgets-digsig#profile"></dsp:Profile></SignatureProperty><SignatureProperty Id="role" Target="#AuthorSignature"><dsp:Role URI="http://www.w3.org/ns/widgets-digsig#role-author"></dsp:Role></SignatureProperty><SignatureProperty Id="identifier" Target="#AuthorSignature"><dsp:Identifier></dsp:Identifier></SignatureProperty></SignatureProperties></Object>
+</Signature>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<widget xmlns="http://www.w3.org/ns/widgets" xmlns:tizen="http://tizen.org/ns/widgets" id="http://yourdomain/AppInstallersTest" version="1.0.0" viewmodes="maximized">
+ <tizen:application id="ZK6wgb4nwt.AppInstallersTest" package="ZK6wgb4nwt" required_version="2.3"/>
+ <content src="index.html"/>
+ <feature name="http://tizen.org/feature/screen.size.all"/>
+ <icon src="icon.png"/>
+ <name>AppInstallersTest</name>
+ <tizen:profile name="mobile"/>
+</widget>
--- /dev/null
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
+ <meta name="description" content="Tizen basic template generated by Tizen Web IDE"/>
+
+ <title>Tizen Web IDE - Tizen - Tizen basic Application</title>
+</head>
+
+<body>
+ <header>
+ <hgroup>
+ <h1>Tizen app</h1>
+ <h2>An empty template of tizen</h2>
+ </hgroup>
+ </header>
+
+ <nav>
+ <ul>
+ <li><a href="#">Home</a></li>
+ <li><a href="#">About Us</a></li>
+ <li><a href="#">Contact Us</a></li>
+ </ul>
+ </nav>
+
+ <article>
+ <p>This is an empty template of Tizen Web Application. Tizen will support multiple device categories:</p>
+ <ul>
+ <li>smartphones, tablets and smart TVs
+ <li>netbooks, in-vehicle infotainment devices
+ </ul>
+ <section>
+ <p>This is a basic section of a document.</p>
+ <p>The following button displays a time using JavaScript.</p>
+ <div id="divbutton1">
+ <button>Clock</button>
+ </div>
+ </section>
+ </article>
+
+ <footer>
+ <p>© 2012 Company Name. All rights reserved.</p>
+ </footer>
+</body>
+</html>
--- /dev/null
+<Signature xmlns="http://www.w3.org/2000/09/xmldsig#" Id="DistributorSignature">
+<SignedInfo>
+<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></CanonicalizationMethod>
+<SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"></SignatureMethod>
+<Reference URI="author-signature.xml">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>opfWp60FUsKzpdQBgTp3x31PB1GzC9mS6M7B6n2m63c=</DigestValue>
+</Reference>
+<Reference URI="config.xml">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>iEX0LuZs81Q6Du/SkXgbMd+Qa6puMxgyRUCLqhrfpJ8=</DigestValue>
+</Reference>
+<Reference URI="icon.png">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>1d0oEZHqPn+QzNzGIHwj9ODby6x9ggFs9uOsav6jPNs=</DigestValue>
+</Reference>
+<Reference URI="index.html">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>rJOIi81O4OG/Gar/hwrjvD623MpScv6TMdurRZgzDf0=</DigestValue>
+</Reference>
+<Reference URI="version.txt">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>MjYb9c/C/J56bHY6rlIjfDqkpjFtsUBjLLkco/rcfFY=</DigestValue>
+</Reference>
+<Reference URI="#prop">
+<Transforms>
+<Transform Algorithm="http://www.w3.org/2006/12/xml-c14n11"></Transform>
+</Transforms>
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>u/jU3U4Zm5ihTMSjKGlGYbWzDfRkGphPPHx3gJIYEJ4=</DigestValue>
+</Reference>
+</SignedInfo>
+<SignatureValue>
+O6yHkXzPKe+8nGxjh06ivDImxKSKygVOgvZzmKKHVWn879K2K8vY08/f7FXKG+zRXEouXbZd7aip
+IGyOCpulXUzESCQMIiffzMVgTV0Ho+kXx44xbME/XKy7DJYpZOvZFXX1S9ZXvU2BmmgHtWWLS/gc
+sFiYVHpRxLnify3npXE=
+</SignatureValue>
+<KeyInfo>
+<X509Data>
+<X509Certificate>
+MIICmzCCAgQCCQDXI7WLdVZwiTANBgkqhkiG9w0BAQUFADCBjzELMAkGA1UEBhMCS1IxDjAMBgNV
+BAgMBVN1d29uMQ4wDAYDVQQHDAVTdXdvbjEWMBQGA1UECgwNVGl6ZW4gVGVzdCBDQTEiMCAGA1UE
+CwwZVGl6ZW4gRGlzdHJpYnV0b3IgVGVzdCBDQTEkMCIGA1UEAwwbVGl6ZW4gUHVibGljIERpc3Ry
+aWJ1dG9yIENBMB4XDTEyMTAyOTEzMDMwNFoXDTIyMTAyNzEzMDMwNFowgZMxCzAJBgNVBAYTAktS
+MQ4wDAYDVQQIDAVTdXdvbjEOMAwGA1UEBwwFU3V3b24xFjAUBgNVBAoMDVRpemVuIFRlc3QgQ0Ex
+IjAgBgNVBAsMGVRpemVuIERpc3RyaWJ1dG9yIFRlc3QgQ0ExKDAmBgNVBAMMH1RpemVuIFB1Ymxp
+YyBEaXN0cmlidXRvciBTaWduZXIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALtMvlc5hENK
+90ZdA+y66+Sy0enD1gpZDBh5T9RP0oRsptJv5jjNTseQbQi0SZOdOXb6J7iQdlBCtR343RpIEz8H
+mrBy7mSY7mgwoU4EPpp4CTSUeAuKcmvrNOngTp5Hv7Ngf02TTHOLK3hZLpGayaDviyNZB5PdqQdB
+hokKjzAzAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAvGp1gxxAIlFfhJH1efjb9BJK/rtRkbYn9+Ez
+GEbEULg1svsgnyWisFimI3uFvgI/swzr1eKVY3Sc8MQ3+Fdy3EkbDZ2+WAubhcEkorTWjzWz2fL1
+vKaYjeIsuEX6TVRUugHWudPzcEuQRLQf8ibZWjbQdBmpeQYBMg5x+xKLCJc=
+</X509Certificate>
+<X509Certificate>
+MIICtDCCAh2gAwIBAgIJAMDbehElPNKvMA0GCSqGSIb3DQEBBQUAMIGVMQswCQYDVQQGEwJLUjEO
+MAwGA1UECAwFU3V3b24xDjAMBgNVBAcMBVN1d29uMRYwFAYDVQQKDA1UaXplbiBUZXN0IENBMSMw
+IQYDVQQLDBpUVGl6ZW4gRGlzdHJpYnV0b3IgVGVzdCBDQTEpMCcGA1UEAwwgVGl6ZW4gUHVibGlj
+IERpc3RyaWJ1dG9yIFJvb3QgQ0EwHhcNMTIxMDI5MTMwMjUwWhcNMjIxMDI3MTMwMjUwWjCBjzEL
+MAkGA1UEBhMCS1IxDjAMBgNVBAgMBVN1d29uMQ4wDAYDVQQHDAVTdXdvbjEWMBQGA1UECgwNVGl6
+ZW4gVGVzdCBDQTEiMCAGA1UECwwZVGl6ZW4gRGlzdHJpYnV0b3IgVGVzdCBDQTEkMCIGA1UEAwwb
+VGl6ZW4gUHVibGljIERpc3RyaWJ1dG9yIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDe
+OTS/3nXvkDEmsFCJIvRlQ3RKDcxdWJJp625pFqHdmoJBdV+x6jl1raGK2Y1sp2Gdvpjc/z92yzAp
+bE/UVLPh/tRNZPeGhzU4ejDDm7kzdr2f7Ia0U98K+OoY12ucwg7TYNItj9is7Cj4blGfuMDzd2ah
+2AgnCGlwNwV/pv+uVQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBACqJ
+KO33YdoGudwanZIxMdXuxnnD9R6u72ltKk1S4zPfMJJv482CRGCI4FK6djhlsI4i0Lt1SVIJEed+
+yc3qckGm19dW+4xdlkekon7pViEBWuyHw8OWv3RXtTum1+PGHjBJ2eYY4ZKIpz73U/1NC16sTB/0
+VhfnkHwPltmrpYVe
+</X509Certificate>
+</X509Data>
+</KeyInfo>
+<Object Id="prop"><SignatureProperties xmlns:dsp="http://www.w3.org/2009/xmldsig-properties"><SignatureProperty Id="profile" Target="#DistributorSignature"><dsp:Profile URI="http://www.w3.org/ns/widgets-digsig#profile"></dsp:Profile></SignatureProperty><SignatureProperty Id="role" Target="#DistributorSignature"><dsp:Role URI="http://www.w3.org/ns/widgets-digsig#role-distributor"></dsp:Role></SignatureProperty><SignatureProperty Id="identifier" Target="#DistributorSignature"><dsp:Identifier></dsp:Identifier></SignatureProperty></SignatureProperties></Object>
+</Signature>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<manifest xmlns="http://tizen.org/ns/packages" api-version="2.3" package="org.tizen.testapp" version="1.0.0">
+ <author email="tester@samsung.com" href="www.tizen.org">tester</author>
+ <description>This is default description</description>
+ <description xml:lang="en-us">This is test description</description>
+ <ui-application appid="org.tizen.testapp.main" exec="testapp" multiple="false" nodisplay="false" taskmanage="true" type="capp">
+ <label>testapp</label>
+ <label xml:lang="en-us">Test</label>
+ <icon>testapp.png</icon>
+ <app-control>
+ <mime name="EditMime"/>
+ <operation name="http://tizen.org/appcontrol/operation/edit"/>
+ <uri name="EditUri"/>
+ </app-control>
+ <app-control>
+ <operation name="http://tizen.org/appcontrol/operation/view"/>
+ <uri name="ViewUri"/>
+ <mime name="ViewMime"/>
+ </app-control>
+ <datacontrol access="ReadOnly" providerid="http://testapp.com/datacontrol/provider/testapp" type="Sql"/>
+ <datacontrol access="ReadOnly" providerid="http://testapp.com/datacontrol/provider/testapp" type="Map"/>
+ <category name="http://tizen.org/category/test_category" />
+ <category name="http://tizen.org/category/test_category/value_a" />
+ <category name="http://tizen.org/category/test_category/value_b" />
+ </ui-application>
+</manifest>
--- /dev/null
+type="tag";name="test";path="/usr/share/app-installers-ut/test_samples/plugins/libtest-tag-plugin.so"
+type="category";;;;;;name="http://tizen.org/category/test_category";path="/usr/share/app-installers-ut/test_samples/plugins/libtest-category-plugin.so"
+type="metadata";name="http://developer.samsung.com/tizen/metadata/test_metadata";path="/usr/share/app-installers-ut/test_samples/plugins/libtest-metadata-plugin.so"
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<manifest xmlns="http://tizen.org/ns/packages" api-version="2.3" package="org.tizen.testapp" version="1.0.0">
+ <broken_xml
+</manifest>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<manifest xmlns="http://tizen.org/ns/packages" api-version="2.3" package="org.tizen.testapp" version="1.0.0">
+ <author email="tester@samsung.com" href="www.tizen.org">tester</author>
+ <description>This is default description</description>
+ <description xml:lang="en-us">This is test description</description>
+ <ui-application appid="org.tizen.testapp.main" exec="testapp" multiple="false" nodisplay="false" taskmanage="true" type="capp">
+ <label>testapp</label>
+ <label xml:lang="en-us">Test</label>
+ <icon>testapp.png</icon>
+ <app-control>
+ <mime name="EditMime"/>
+ <operation name="http://tizen.org/appcontrol/operation/edit"/>
+ <uri name="EditUri"/>
+ </app-control>
+ <app-control>
+ <operation name="http://tizen.org/appcontrol/operation/view"/>
+ <uri name="ViewUri"/>
+ <mime name="ViewMime"/>
+ </app-control>
+ <metadata key="metakey1" value="metaval1"/>
+ <metadata key="metakey2" value="metaval2"/>
+ <metadata key="http://developer.samsung.com/tizen/metadata/test_metadata/key_a" value="value_a"/>
+ <metadata key="http://developer.samsung.com/tizen/metadata/test_metadata/key_b" value="value_b"/>
+ <metadata key="http://developer.samsung.com/tizen/metadata/test_metadata/key_c" value="value_c"/>
+ <datacontrol access="ReadOnly" providerid="http://testapp.com/datacontrol/provider/testapp" type="Sql"/>
+ <datacontrol access="ReadOnly" providerid="http://testapp.com/datacontrol/provider/testapp" type="Map"/>
+ </ui-application>
+</manifest>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<manifest xmlns="http://tizen.org/ns/packages" api-version="2.3" package="org.tizen.testapp" version="1.0.0">
+ <author email="tester@samsung.com" href="www.tizen.org">tester</author>
+ <description>This is default description</description>
+ <description xml:lang="en-us">This is test description</description>
+ <ui-application appid="org.tizen.testapp.main" exec="testapp" multiple="false" nodisplay="false" taskmanage="true" type="capp">
+ <label>testapp</label>
+ <label xml:lang="en-us">Test</label>
+ <icon>testapp.png</icon>
+ <app-control>
+ <mime name="EditMime"/>
+ <operation name="http://tizen.org/appcontrol/operation/edit"/>
+ <uri name="EditUri"/>
+ </app-control>
+ <app-control>
+ <operation name="http://tizen.org/appcontrol/operation/view"/>
+ <uri name="ViewUri"/>
+ <mime name="ViewMime"/>
+ </app-control>
+ <datacontrol access="ReadOnly" providerid="http://testapp.com/datacontrol/provider/testapp" type="Sql"/>
+ <datacontrol access="ReadOnly" providerid="http://testapp.com/datacontrol/provider/testapp" type="Map"/>
+ </ui-application>
+ <test>
+ </test>
+</manifest>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<manifest xmlns="http://tizen.org/ns/packages" api-version="2.3" package="org.tizen.testapp" version="1.0.0">
+ <author email="tester@samsung.com" href="www.tizen.org">tester</author>
+ <description>This is default description</description>
+ <description xml:lang="en-us">This is test description</description>
+ <ui-application appid="org.tizen.testapp.main" exec="testapp" multiple="false" nodisplay="false" taskmanage="true" type="capp">
+ <label>testapp</label>
+ <label xml:lang="en-us">Test</label>
+ <icon>testapp.png</icon>
+ <app-control>
+ <mime name="EditMime"/>
+ <operation name="http://tizen.org/appcontrol/operation/edit"/>
+ <uri name="EditUri"/>
+ </app-control>
+ <app-control>
+ <operation name="http://tizen.org/appcontrol/operation/view"/>
+ <uri name="ViewUri"/>
+ <mime name="ViewMime"/>
+ </app-control>
+ <metadata key="metakey1" value="metaval1"/>
+ <metadata key="metakey2" value="metaval2"/>
+ <metadata key="http://developer.samsung.com/tizen/metadata/test_metadata/key_a" value="value_a"/>
+ <metadata key="http://developer.samsung.com/tizen/metadata/test_metadata/key_b" value="value_b"/>
+ <metadata key="http://developer.samsung.com/tizen/metadata/test_metadata/key_c" value="value_c"/>
+ <datacontrol access="ReadOnly" providerid="http://testapp.com/datacontrol/provider/testapp" type="Sql"/>
+ <datacontrol access="ReadOnly" providerid="http://testapp.com/datacontrol/provider/testapp" type="Map"/>
+ <category name="http://tizen.org/category/test_category" />
+ <category name="http://tizen.org/category/test_category/value_a" />
+ <category name="http://tizen.org/category/test_category/value_b" />
+ </ui-application>
+ <test>
+ </test>
+</manifest>
--- /dev/null
+type="metadata";name="http://developer.samsung.com/tizen/metadata/test_metadata";path="/usr/share/app-installers-ut/test_samples/plugins/libtest-metadata-fail-plugin.so";vitalness="true"
--- /dev/null
+type="tag";name="test";path="/usr/share/app-installers-ut/test_samples/plugins/libtest-tag-fail-plugin.so";vitalness="true"
+type="category";name="http://tizen.org/category/test_category";path="/usr/share/app-installers-ut/test_samples/plugins/libtest-category-fail-plugin.so";vitalness="true"
--- /dev/null
+type="metadata";name="http://developer.samsung.com/tizen/metadata/test_metadata";path="/usr/share/app-installers-ut/test_samples/plugins/libtest-metadata-plugin.so"
--- /dev/null
+type="tag";name="test";path="/usr/share/app-installers-ut/test_samples/plugins/libtest-tag-plugin.so"
+type="category";name="http://tizen.org/category/test_category";path="/usr/share/app-installers-ut/test_samples/plugins/libtest-category-plugin.so"
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<manifest xmlns="http://tizen.org/ns/packages" api-version="2.3" package="org.tizen.testapp" version="1.0.0">
+ <author email="tester@samsung.com" href="www.tizen.org">tester</author>
+ <description>This is default description</description>
+ <description xml:lang="en-us">This is test description</description>
+ <ui-application appid="org.tizen.testapp" exec="testapp" multiple="false" nodisplay="false" taskmanage="true" type="capp">
+ <label>testapp</label>
+ <label xml:lang="en-us">Test</label>
+ <icon>testapp.png</icon>
+ <app-control>
+ <mime name="EditMime"/>
+ <operation name="http://tizen.org/appcontrol/operation/edit"/>
+ <uri name="EditUri"/>
+ </app-control>
+ <app-control>
+ <operation name="http://tizen.org/appcontrol/operation/view"/>
+ <uri name="ViewUri"/>
+ <mime name="ViewMime"/>
+ </app-control>
+ <metadata key="metakey1" value="metaval1"/>
+ <metadata key="metakey2" value="metaval2"/>
+ <datacontrol access="ReadOnly" providerid="http://testapp.com/datacontrol/provider/testapp" type="Sql"/>
+ <datacontrol access="ReadOnly" providerid="http://testapp.com/datacontrol/provider/testapp" type="Map"/>
+ </ui-application>
+ <account>
+ <account-provider appid="org.tizen.testapp" multiple-accounts-support="false" providerid="com.samsung">
+ <icon section="account">testapp.png</icon>
+ <icon section="account-small">testapp.png</icon>
+ <label xml:lang="en-gb">account icon</label>
+ <label>Samsung</label>
+ <capability>http://tizen.org/account/capability/calendar</capability>
+ <capability>http://tizen.org/account/capability/photo</capability>
+ </account-provider>
+ </account>
+ <privileges>
+ <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
+ <privilege>http://tizen.org/privilege/packagemanager.info</privilege>
+ </privileges>
+ <feature name="http://tizen.org/feature/camera.front.flash">true</feature>
+ <feature name="http://tizen.org/feature/camera">true</feature>
+ <feature name="http://tizen.org/feature/camera.back.flash">true</feature>
+ <feature name="http://tizen.org/feature/camera.front">true</feature>
+</manifest>