-#include <pkgmgr-info.h>
-#include <signal.h>
-#include <unistd.h>
-#include <tzplatform_config.h>
-#include <vconf.h>
-#include <vconf-internal-keys.h>
-
-#include <array>
-#include <cstdio>
-#include <cstdlib>
-#include <vector>
-
-#include "hybrid/hybrid_installer.h"
-#include "wgt/wgt_app_query_interface.h"
-#include "wgt/wgt_installer.h"
-
-#define SIZEOFARRAY(ARR) \
- sizeof(ARR) / sizeof(ARR[0]) \
-
-namespace bf = boost::filesystem;
-namespace bs = boost::system;
-namespace ci = common_installer;
-
-namespace {
-
-const uid_t kGlobalUserUid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
-const uid_t kGlobalUserGid = tzplatform_getgid(TZ_SYS_GLOBALAPP_USER);
-const uid_t kDefaultUserUid = tzplatform_getuid(TZ_SYS_DEFAULT_USER);
-const uid_t kTestUserId = kGlobalUserUid;
-const gid_t kTestGroupId = kGlobalUserGid;
-const char kSystemShareGroupName[] = "system_share";
-const std::string& kTestUserIdStr =
- std::to_string(kTestUserId);
-const std::string& kDefaultUserIdStr = std::to_string(kDefaultUserUid);
-const char kLegacyExtImageDir[] = "legacy_extimage_dir";
-const char kMigrateTestDBName[] = "app2sd_migrate.db";
-
-const bf::path kSmokePackagesDirectory =
- "/usr/share/wgt-backend-ut/test_samples/smoke/";
-
-// common entries
-const std::vector<std::string> kDBEntries = {
- {".pkgmgr_parser.db"},
- {".pkgmgr_parser.db-journal"},
- {".pkgmgr_cert.db"},
- {".pkgmgr_cert.db-journal"},
- {".app2sd.db"},
- {".app2sd.db-journal"},
-};
-// globaluser entries
-const char kGlobalManifestDir[] = "/opt/share/packages";
-const char kSkelDir[] = "/etc/skel/apps_rw";
-const char kPreloadApps[] = "/usr/apps";
-const char kPreloadManifestDir[] = "/usr/share/packages";
-const char kPreloadIcons[] = "/usr/share/icons";
-
-enum class RequestResult {
- NORMAL,
- FAIL
-};
-
-class ScopedTzipInterface {
- public:
- explicit ScopedTzipInterface(const std::string& pkgid)
- : pkg_path_(bf::path(ci::GetRootAppPath(false,
- kTestUserId)) / pkgid),
- interface_(ci::GetMountLocation(pkg_path_)),
- mounted_(true) {
- interface_.MountZip(ci::GetZipPackageLocation(pkg_path_, pkgid));
- }
-
- void Release() {
- if (mounted_) {
- interface_.UnmountZip();
- mounted_ = false;
- }
- }
-
- ~ScopedTzipInterface() {
- Release();
- }
-
- private:
- bf::path pkg_path_;
- ci::TzipInterface interface_;
- bool mounted_;
-};
-
-class TestPkgmgrInstaller : public ci::PkgmgrInstallerInterface {
- public:
- bool CreatePkgMgrInstaller(pkgmgr_installer** installer,
- ci::InstallationMode* mode) {
- *installer = pkgmgr_installer_offline_new();
- if (!*installer)
- return false;
- *mode = ci::InstallationMode::ONLINE;
- return true;
- }
-
- bool ShouldCreateSignal() const {
- return false;
- }
-};
-
-enum class PackageType {
- WGT,
- HYBRID
-};
-
-bool TouchFile(const bf::path& path) {
- FILE* f = fopen(path.c_str(), "w+");
- if (!f)
- return false;
- fclose(f);
- return true;
-}
-
-void RemoveAllRecoveryFiles() {
- bf::path root_path = ci::GetRootAppPath(false,
- kTestUserId);
- if (!bf::exists(root_path))
- return;
- for (auto& dir_entry : boost::make_iterator_range(
- bf::directory_iterator(root_path), bf::directory_iterator())) {
- if (bf::is_regular_file(dir_entry)) {
- if (dir_entry.path().string().find("/recovery") != std::string::npos) {
- bs::error_code error;
- bf::remove(dir_entry.path(), error);
- }
- }
- }
-}
-
-bf::path FindRecoveryFile() {
- bf::path root_path = ci::GetRootAppPath(false,
- kTestUserId);
- for (auto& dir_entry : boost::make_iterator_range(
- bf::directory_iterator(root_path), bf::directory_iterator())) {
- if (bf::is_regular_file(dir_entry)) {
- if (dir_entry.path().string().find("/recovery") != std::string::npos) {
- return dir_entry.path();
- }
- }
- }
- return {};
-}
-
-bf::path GetPackageRoot(const std::string& pkgid, uid_t uid) {
- bf::path root_path = ci::GetRootAppPath(false, uid);
- return root_path / pkgid;
-}
-
-bool ValidateFileContentInPackage(const std::string& pkgid,
- const std::string& relative,
- const std::string& expected,
- bool is_readonly = false) {
- bf::path file_path = ci::GetRootAppPath(is_readonly, kTestUserId);
- file_path = file_path / pkgid / relative;
- if (!bf::exists(file_path)) {
- LOG(ERROR) << file_path << " doesn't exist";
- return false;
- }
- FILE* handle = fopen(file_path.c_str(), "r");
- if (!handle) {
- LOG(ERROR) << file_path << " cannot be open";
- return false;
- }
- std::string content;
- std::array<char, 200> buffer;
- while (fgets(buffer.data(), buffer.size(), handle)) {
- content += buffer.data();
- }
- fclose(handle);
- return content == expected;
-}
-
-void AddDataFiles(const std::string& pkgid, uid_t uid) {
- if (uid == kGlobalUserUid) {
- ci::UserList list = ci::GetUserList();
- for (auto l : list) {
- auto pkg_path = GetPackageRoot(pkgid, std::get<0>(l));
- ASSERT_TRUE(TouchFile(pkg_path / "data" / "file1.txt"));
- ASSERT_TRUE(TouchFile(pkg_path / "data" / "file2.txt"));
- }
- } else {
- auto pkg_path = GetPackageRoot(pkgid, uid);
- ASSERT_TRUE(TouchFile(pkg_path / "data" / "file1.txt"));
- ASSERT_TRUE(TouchFile(pkg_path / "data" / "file2.txt"));
- }
-}
-
-void ValidateDataFiles(const std::string& pkgid, uid_t uid) {
- if (uid == kGlobalUserUid) {
- ci::UserList list = ci::GetUserList();
- for (auto l : list) {
- auto pkg_path = GetPackageRoot(pkgid, std::get<0>(l));
- ASSERT_TRUE(bf::exists(pkg_path / "data" / "file1.txt"));
- ASSERT_TRUE(bf::exists(pkg_path / "data" / "file2.txt"));
- }
- } else {
- auto pkg_path = GetPackageRoot(pkgid, uid);
- ASSERT_TRUE(bf::exists(pkg_path / "data" / "file1.txt"));
- ASSERT_TRUE(bf::exists(pkg_path / "data" / "file2.txt"));
- }
-}
-
-void ValidatePackageRWFS(const std::string& pkgid, uid_t uid) {
- bf::path root_path = ci::GetRootAppPath(false, uid);
- bf::path package_path = root_path / pkgid;
- bf::path data_path = package_path / "data";
- bf::path cache_path = package_path / "cache";
- bf::path shared_data_path = package_path / "shared" / "data";
-
- ASSERT_TRUE(bf::exists(data_path));
- ASSERT_TRUE(bf::exists(cache_path));
-
- struct stat stats;
- stat(data_path.c_str(), &stats);
- // gid of RW dirs should be system_share
- boost::optional<gid_t> system_share =
- ci::GetGidByGroupName(kSystemShareGroupName);
- ASSERT_EQ(uid, stats.st_uid) << "Invalid gid: " << data_path;
- ASSERT_EQ(*system_share, stats.st_gid) << "Invalid gid: " << data_path;
- if (bf::exists(shared_data_path)) {
- stat(shared_data_path.c_str(), &stats);
- ASSERT_EQ(uid, stats.st_uid) << "Invalid gid: " << shared_data_path;
- ASSERT_EQ(*system_share, stats.st_gid) << "Invalid gid: "
- << shared_data_path;
- }
-
- stat(cache_path.c_str(), &stats);
- ASSERT_EQ(uid, stats.st_uid) << "Invalid gid: " << cache_path;
- ASSERT_EQ(*system_share, stats.st_gid) << "Invalid gid: " << cache_path;
-}
-
-void ValidatePackageFS(const std::string& pkgid,
- const std::vector<std::string>& appids,
- uid_t uid, gid_t gid, bool is_readonly) {
- bf::path root_path = ci::GetRootAppPath(is_readonly, uid);
- bf::path package_path = root_path / pkgid;
- bf::path shared_path = package_path / "shared";
- ASSERT_TRUE(bf::exists(root_path));
- ASSERT_TRUE(bf::exists(package_path));
- ASSERT_TRUE(bf::exists(shared_path));
-
- bf::path manifest_path =
- bf::path(getUserManifestPath(uid, is_readonly)) / (pkgid + ".xml");
- ASSERT_TRUE(bf::exists(manifest_path));
-
- for (auto& appid : appids) {
- bf::path binary_path = package_path / "bin" / appid;
- ASSERT_TRUE(bf::exists(binary_path));
- }
-
- bf::path widget_root_path = package_path / "res" / "wgt";
- bf::path config_path = widget_root_path / "config.xml";
- ASSERT_TRUE(bf::exists(widget_root_path));
- ASSERT_TRUE(bf::exists(config_path));
-
- bf::path private_tmp_path = package_path / "tmp";
- ASSERT_TRUE(bf::exists(private_tmp_path));
-
- // backups should not exist
- bf::path package_backup = ci::GetBackupPathForPackagePath(package_path);
- bf::path manifest_backup = ci::GetBackupPathForManifestFile(manifest_path);
- ASSERT_FALSE(bf::exists(package_backup));
- ASSERT_FALSE(bf::exists(manifest_backup));
-
- for (bf::recursive_directory_iterator iter(package_path);
- iter != bf::recursive_directory_iterator(); ++iter) {
- if (bf::is_symlink(symlink_status(iter->path())))
- continue;
- if (iter->path().filename() == "data" ||
- iter->path().filename() == ".mmc")
- continue;
- struct stat stats;
- stat(iter->path().c_str(), &stats);
- ASSERT_EQ(uid, stats.st_uid) << "Invalid uid: " << iter->path();
- ASSERT_EQ(gid, stats.st_gid) << "Invalid gid: " << iter->path();
- }
-}
-
-void PackageCheckCleanup(const std::string& pkgid,
- const std::vector<std::string>&, bool is_readonly = false) {
- bf::path root_path = ci::GetRootAppPath(is_readonly, kTestUserId);
- bf::path package_path = root_path / pkgid;
- ASSERT_FALSE(bf::exists(package_path));
-
- bf::path manifest_path = bf::path(getUserManifestPath(kTestUserId,
- is_readonly)) / (pkgid + ".xml");
- ASSERT_FALSE(bf::exists(manifest_path));
-
- // backups should not exist
- bf::path package_backup = ci::GetBackupPathForPackagePath(package_path);
- bf::path manifest_backup = ci::GetBackupPathForManifestFile(manifest_path);
- ASSERT_FALSE(bf::exists(package_backup));
- ASSERT_FALSE(bf::exists(manifest_backup));
-}
-
-void ValidatePackage(const std::string& pkgid,
- const std::vector<std::string>& appids, bool is_readonly = false) {
- ASSERT_TRUE(ci::QueryIsPackageInstalled(
- pkgid, ci::GetRequestMode(kTestUserId), kTestUserId));
- ValidatePackageFS(pkgid, appids, kTestUserId, kTestGroupId, is_readonly);
- if (kTestUserId == kGlobalUserUid) {
- ci::UserList list = ci::GetUserList();
- for (auto& l : list)
- ValidatePackageRWFS(pkgid, std::get<0>(l));
- } else {
- ValidatePackageRWFS(pkgid, kTestUserId);
- }
-}
-
-void ValidateExternalPackageFS(const std::string& pkgid,
- const std::vector<std::string>& appids,
- uid_t uid, gid_t gid) {
- ASSERT_EQ(app2ext_usr_enable_external_pkg(pkgid.c_str(), uid), 0);
- bf::path root_path = ci::GetRootAppPath(false, uid);
- ASSERT_TRUE(bf::exists(root_path / pkgid / ".mmc" / "res"));
- ValidatePackageFS(pkgid, appids, uid, gid, false);
- ASSERT_EQ(app2ext_usr_disable_external_pkg(pkgid.c_str(), uid), 0);
-}
-
-void ValidateExternalPackage(const std::string& pkgid,
- const std::vector<std::string>& appids) {
- ASSERT_TRUE(ci::QueryIsPackageInstalled(
- pkgid, ci::GetRequestMode(kTestUserId),
- kTestUserId));
- std::string storage = ci::QueryStorageForPkgId(pkgid, kTestUserId);
- bf::path ext_mount_path = ci::GetExternalCardPath();
- if (bf::is_empty(ext_mount_path)) {
- LOG(INFO) << "Sdcard not exists!";
- ASSERT_EQ(storage, "installed_internal");
- } else {
- ASSERT_EQ(storage, "installed_external");
- }
- ValidateExternalPackageFS(pkgid, appids, kTestUserId, kTestGroupId);
- if (kTestUserId == kGlobalUserUid) {
- ci::UserList list = ci::GetUserList();
- for (auto& l : list)
- ValidatePackageRWFS(pkgid, std::get<0>(l));
- } else {
- ValidatePackageRWFS(pkgid, kTestUserId);
- }
-}
-
-void CheckPackageNonExistance(const std::string& pkgid,
- const std::vector<std::string>& appids) {
- ASSERT_FALSE(ci::QueryIsPackageInstalled(
- pkgid, ci::GetRequestMode(kTestUserId),
- kTestUserId));
- PackageCheckCleanup(pkgid, appids);
-}
-
-void CheckPackageReadonlyNonExistance(const std::string& pkgid,
- const std::vector<std::string>& appids) {
- ASSERT_FALSE(ci::QueryIsPackageInstalled(
- pkgid, ci::GetRequestMode(kTestUserId), kTestUserId));
- PackageCheckCleanup(pkgid, appids, true);
-}
-
-std::unique_ptr<ci::AppQueryInterface> CreateQueryInterface() {
- std::unique_ptr<ci::AppQueryInterface> query_interface(
- new wgt::WgtAppQueryInterface());
- return query_interface;
-}
-
-std::unique_ptr<ci::AppInstaller> CreateInstaller(ci::PkgMgrPtr pkgmgr,
- PackageType type) {
- switch (type) {
- case PackageType::WGT:
- return std::unique_ptr<ci::AppInstaller>(new wgt::WgtInstaller(pkgmgr));
- case PackageType::HYBRID:
- return std::unique_ptr<ci::AppInstaller>(
- new hybrid::HybridInstaller(pkgmgr));
- default:
- LOG(ERROR) << "Unknown installer type";
- return nullptr;
- }
-}
-
-ci::AppInstaller::Result RunInstallerWithPkgrmgr(ci::PkgMgrPtr pkgmgr,
- PackageType type,
- RequestResult mode) {
- std::unique_ptr<ci::AppInstaller> installer = CreateInstaller(pkgmgr, type);
- switch (mode) {
- case RequestResult::FAIL:
- installer->AddStep<ci::configuration::StepFail>();
- break;
- default:
- break;
- }
- return installer->Run();
-}
-ci::AppInstaller::Result CallBackend(int argc,
- const char* argv[],
- PackageType type,
- RequestResult mode = RequestResult::NORMAL
- ) {
- TestPkgmgrInstaller pkgmgr_installer;
- std::unique_ptr<ci::AppQueryInterface> query_interface =
- CreateQueryInterface();
- auto pkgmgr =
- ci::PkgMgrInterface::Create(argc, const_cast<char**>(argv),
- &pkgmgr_installer, query_interface.get());
- if (!pkgmgr) {
- LOG(ERROR) << "Failed to initialize pkgmgr interface";
- return ci::AppInstaller::Result::UNKNOWN;
- }
- return RunInstallerWithPkgrmgr(pkgmgr, type, mode);
-}
-
-ci::AppInstaller::Result Install(const bf::path& path,
- PackageType type,
- RequestResult mode = RequestResult::NORMAL) {
- const char* argv[] = {"", "-i", path.c_str(), "-u", kTestUserIdStr.c_str()};
- return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
-}