1 // Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
2 // Use of this source code is governed by an apache-2.0 license that can be
3 // found in the LICENSE file.
5 #include <boost/filesystem/operations.hpp>
6 #include <boost/range/iterator_range.hpp>
7 #include <boost/format.hpp>
8 #include <boost/program_options.hpp>
9 #include <boost/system/error_code.hpp>
11 #include <common/utils/subprocess.h>
12 #include <common/step/configuration/step_fail.h>
13 #include <common/utils/user_util.h>
14 #include <common/utils/file_util.h>
15 #include <common/request.h>
17 #include <gtest/gtest.h>
18 #include <gtest/gtest-death-test.h>
20 #include <manifest_parser/utils/version_number.h>
22 #include <pkgmgr-info.h>
25 #include <tzplatform_config.h>
27 #include <vconf-internal-keys.h>
34 #include "wgt/wgt_installer.h"
36 #include "unit_tests/smoke_utils.h"
38 namespace bo = boost::program_options;
40 const uid_t kGlobalUserUid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
41 const uid_t kGlobalUserGid = tzplatform_getgid(TZ_SYS_GLOBALAPP_USER);
42 const uid_t kDefaultUserUid = tzplatform_getuid(TZ_SYS_DEFAULT_USER);
43 uid_t kTestUserId = kGlobalUserUid;
44 gid_t kTestGroupId = kGlobalUserGid;
45 const char kNormalUserName[] = "smokeuser";
46 const char kSystemShareGroupName[] = "system_share";
47 std::string kTestUserIdStr = std::to_string(kTestUserId);
48 const std::string& kDefaultUserIdStr = std::to_string(kDefaultUserUid);
49 const char kLegacyExtImageDir[] = "legacy_extimage_dir";
50 const char kMigrateTestDBName[] = "app2sd_migrate.db";
52 const bf::path kSmokePackagesDirectory =
53 "/usr/share/wgt-backend-ut/test_samples/smoke/";
56 const char* rwDirectories[] = {
65 const std::vector<std::string> kDBEntries = {
66 {".pkgmgr_parser.db"},
67 {".pkgmgr_parser.db-journal"},
69 {".pkgmgr_cert.db-journal"},
71 {".app2sd.db-journal"},
74 const char kGlobalManifestDir[] = "/opt/share/packages";
75 const char kSkelDir[] = "/etc/skel/apps_rw";
76 const char kPreloadApps[] = "/usr/apps";
77 const char kPreloadManifestDir[] = "/usr/share/packages";
78 const char kPreloadIcons[] = "/usr/share/icons";
80 testing::Environment *env = nullptr;
81 void signalHandler(int signum) {
86 ci::RequestMode ParseRequestMode(int argc, char** argv) {
87 bo::options_description desc("Available options");
89 ("request-mode", bo::value<std::string>(), "set request mode")
90 ("global-request,g", "set request mode to global")
91 ("user-request,u", "set request mode to user");
94 bo::store(bo::command_line_parser(argc, argv).
95 options(desc).allow_unregistered().run(), vm);
98 if (vm.count("global-request")) {
99 std::cout << "Request mode was set to global." << std::endl;
100 return ci::RequestMode::GLOBAL;
102 if (vm.count("user-request")) {
103 std::cout << "Request mode was set to user." << std::endl;
104 return ci::RequestMode::USER;
106 if (vm.count("request-mode")) {
107 if (vm["request-mode"].as<std::string>() == "global") {
108 std::cout << "Request mode was set to global." << std::endl;
109 return ci::RequestMode::GLOBAL;
111 if (vm["request-mode"].as<std::string>() == "user") {
112 std::cout << "Request mode was set to user." << std::endl;
113 return ci::RequestMode::USER;
115 std::cout << "Cannot set request mode to "
116 << vm["request-mode"].as<std::string>() << std::endl;
118 std::cout << "Request mode was set to global." << std::endl;
119 return ci::RequestMode::GLOBAL;
122 bool TouchFile(const bf::path& path) {
123 FILE* f = fopen(path.c_str(), "w+");
130 bool AddUser(const char *user_name) {
131 GumUser* user = nullptr;
132 user = gum_user_create_sync(FALSE);
134 LOG(WARNING) << "Failed to create gum user! (user name: "
136 g_object_set(G_OBJECT(user), "username", user_name, "usertype",
137 GUM_USERTYPE_NORMAL, NULL);
138 gboolean rval = FALSE;
139 rval = gum_user_add_sync(user);
140 g_object_unref(user);
144 bool DeleteUser(const char *user_name, bool rem_home_dir) {
146 GumUser* guser = gum_user_get_by_name_sync(user_name, FALSE);
148 rval = gum_user_delete_sync(guser, rem_home_dir);
152 bool AddTestUser(const char *user_name) {
153 std::cout << "Adding test user: " << user_name << std::endl;
155 if (boost::optional<uid_t> uid = ci::GetUidByUserName(user_name)) {
157 kTestUserIdStr = std::to_string(kTestUserId);
158 std::cout << "User created properly: uid=" << *uid;
159 if (boost::optional<gid_t> gid = ci::GetGidByUid(*uid)) {
161 std::cout << " gid=" << *gid;
163 std::cout << std::endl;
166 LOG(ERROR) << "Adding test user failed";
170 bool DeleteTestUser(const char *user_name) {
171 std::cout << "Deleting test user: " << user_name << std::endl;
173 if (boost::optional<uid_t> uid = ci::GetUidByUserName(user_name))
175 DeleteUser(user_name, true);
176 if (!ci::GetUidByUserName(user_name)) {
177 std::cout << "User deleted properly: user_name=" << user_name
178 << " uid=" << test_uid << std::endl;
181 LOG(ERROR) << "Deleting test user failed";
185 void RemoveAllRecoveryFiles() {
186 bf::path root_path = ci::GetRootAppPath(false,
188 if (!bf::exists(root_path))
190 for (auto& dir_entry : boost::make_iterator_range(
191 bf::directory_iterator(root_path), bf::directory_iterator())) {
192 if (bf::is_regular_file(dir_entry)) {
193 if (dir_entry.path().string().find("/wgt-recovery")
194 != std::string::npos) {
195 bs::error_code error;
196 bf::remove(dir_entry.path(), error);
202 bf::path FindRecoveryFile() {
203 bf::path root_path = ci::GetRootAppPath(false,
205 for (auto& dir_entry : boost::make_iterator_range(
206 bf::directory_iterator(root_path), bf::directory_iterator())) {
207 if (bf::is_regular_file(dir_entry)) {
208 if (dir_entry.path().string().find("/wgt-recovery")
209 != std::string::npos) {
210 return dir_entry.path();
217 bf::path GetPackageRoot(const std::string& pkgid, uid_t uid) {
218 bf::path root_path = ci::GetRootAppPath(false, uid);
219 return root_path / pkgid;
222 bool ValidateFileContentInPackage(const std::string& pkgid,
223 const std::string& relative,
224 const std::string& expected,
226 bf::path file_path = ci::GetRootAppPath(is_readonly, kTestUserId);
227 file_path = file_path / pkgid / relative;
228 if (!bf::exists(file_path)) {
229 LOG(ERROR) << file_path << " doesn't exist";
232 FILE* handle = fopen(file_path.c_str(), "r");
234 LOG(ERROR) << file_path << " cannot be open";
238 std::array<char, 200> buffer;
239 while (fgets(buffer.data(), buffer.size(), handle)) {
240 content += buffer.data();
243 return content == expected;
246 void AddDataFiles(const std::string& pkgid, uid_t uid) {
247 if (uid == kGlobalUserUid) {
248 ci::UserList list = ci::GetUserList();
249 for (auto l : list) {
250 auto pkg_path = GetPackageRoot(pkgid, std::get<0>(l));
251 ASSERT_TRUE(TouchFile(pkg_path / "data" / "file1.txt"));
252 ASSERT_TRUE(TouchFile(pkg_path / "data" / "file2.txt"));
255 auto pkg_path = GetPackageRoot(pkgid, uid);
256 ASSERT_TRUE(TouchFile(pkg_path / "data" / "file1.txt"));
257 ASSERT_TRUE(TouchFile(pkg_path / "data" / "file2.txt"));
261 bool ValidateDataFiles(const std::string& pkgid, uid_t uid) {
262 if (uid == kGlobalUserUid) {
263 ci::UserList list = ci::GetUserList();
264 for (auto l : list) {
265 auto pkg_path = GetPackageRoot(pkgid, std::get<0>(l));
266 EXTENDED_ASSERT_TRUE(bf::exists(pkg_path / "data" / "file1.txt"));
267 EXTENDED_ASSERT_TRUE(bf::exists(pkg_path / "data" / "file2.txt"));
270 auto pkg_path = GetPackageRoot(pkgid, uid);
271 EXTENDED_ASSERT_TRUE(bf::exists(pkg_path / "data" / "file1.txt"));
272 EXTENDED_ASSERT_TRUE(bf::exists(pkg_path / "data" / "file2.txt"));
277 bool ValidatePackageRWFS(const std::string& pkgid, uid_t uid) {
278 bf::path root_path = ci::GetRootAppPath(false, uid);
279 bf::path package_path = root_path / pkgid;
280 bf::path data_path = package_path / rwDirectories[DATA];
281 bf::path cache_path = package_path / rwDirectories[CACHE];
282 bf::path shared_data_path = package_path / rwDirectories[SHARED_DATA];
284 EXTENDED_ASSERT_TRUE(bf::exists(data_path));
285 EXTENDED_ASSERT_TRUE(bf::exists(cache_path));
288 stat(data_path.c_str(), &stats);
289 // gid of RW dirs should be system_share
290 boost::optional<gid_t> system_share =
291 ci::GetGidByGroupName(kSystemShareGroupName);
292 EXTENDED_ASSERT_EQ(uid, stats.st_uid);
293 EXTENDED_ASSERT_EQ(*system_share, stats.st_gid);
294 if (bf::exists(shared_data_path)) {
295 stat(shared_data_path.c_str(), &stats);
296 EXTENDED_ASSERT_EQ(uid, stats.st_uid);
297 EXTENDED_ASSERT_EQ(*system_share, stats.st_gid);
300 stat(cache_path.c_str(), &stats);
301 EXTENDED_ASSERT_EQ(uid, stats.st_uid);
302 EXTENDED_ASSERT_EQ(*system_share, stats.st_gid);
306 bool ValidatePackageFS(const std::string& pkgid,
307 const std::vector<std::string>& appids,
308 uid_t uid, gid_t gid, bool is_readonly) {
309 bf::path root_path = ci::GetRootAppPath(is_readonly, uid);
310 bf::path package_path = root_path / pkgid;
311 bf::path shared_path = package_path / "shared";
312 EXTENDED_ASSERT_TRUE(bf::exists(root_path));
313 EXTENDED_ASSERT_TRUE(bf::exists(package_path));
314 EXTENDED_ASSERT_TRUE(bf::exists(shared_path));
316 bf::path manifest_path =
317 bf::path(getUserManifestPath(uid, is_readonly)) / (pkgid + ".xml");
318 EXTENDED_ASSERT_TRUE(bf::exists(manifest_path));
320 for (auto& appid : appids) {
321 bf::path binary_path = package_path / "bin" / appid;
322 EXTENDED_ASSERT_TRUE(bf::exists(binary_path));
325 bf::path widget_root_path = package_path / "res" / "wgt";
326 bf::path config_path = widget_root_path / "config.xml";
327 EXTENDED_ASSERT_TRUE(bf::exists(widget_root_path));
328 EXTENDED_ASSERT_TRUE(bf::exists(config_path));
330 bf::path private_tmp_path = package_path / "tmp";
331 EXTENDED_ASSERT_TRUE(bf::exists(private_tmp_path));
333 // backups should not exist
334 bf::path package_backup = ci::GetBackupPathForPackagePath(package_path);
335 bf::path manifest_backup = ci::GetBackupPathForManifestFile(manifest_path);
336 EXTENDED_ASSERT_FALSE(bf::exists(package_backup));
337 EXTENDED_ASSERT_FALSE(bf::exists(manifest_backup));
339 for (bf::recursive_directory_iterator iter(package_path);
340 iter != bf::recursive_directory_iterator(); ++iter) {
341 if (bf::is_symlink(symlink_status(iter->path())))
343 bool is_rw_dir = false;
344 for (const auto rw_dir : rwDirectories) {
345 bf::path rw_dir_path = rw_dir;
346 is_rw_dir |= ci::MakeRelativePath(iter->path(), package_path)
349 if (is_rw_dir || iter->path().filename() == ".mmc") {
354 stat(iter->path().c_str(), &stats);
355 EXTENDED_ASSERT_EQ(uid, stats.st_uid);
356 EXTENDED_ASSERT_EQ(gid, stats.st_gid);
361 void PackageCheckCleanup(const std::string& pkgid,
362 const std::vector<std::string>&, bool is_readonly) {
363 bf::path root_path = ci::GetRootAppPath(is_readonly, kTestUserId);
364 bf::path package_path = root_path / pkgid;
365 ASSERT_FALSE(bf::exists(package_path));
367 bf::path manifest_path = bf::path(getUserManifestPath(kTestUserId,
368 is_readonly)) / (pkgid + ".xml");
369 ASSERT_FALSE(bf::exists(manifest_path));
371 // backups should not exist
372 bf::path package_backup = ci::GetBackupPathForPackagePath(package_path);
373 bf::path manifest_backup = ci::GetBackupPathForManifestFile(manifest_path);
374 ASSERT_FALSE(bf::exists(package_backup));
375 ASSERT_FALSE(bf::exists(manifest_backup));
378 bool ValidatePackage(const std::string& pkgid,
379 const std::vector<std::string>& appids, bool is_readonly) {
380 EXTENDED_ASSERT_TRUE(ci::QueryIsPackageInstalled(
381 pkgid, ci::GetRequestMode(kTestUserId), kTestUserId));
382 EXTENDED_ASSERT_TRUE(ValidatePackageFS(
383 pkgid, appids, kTestUserId, kTestGroupId, is_readonly));
384 if (kTestUserId == kGlobalUserUid) {
385 ci::UserList list = ci::GetUserList();
387 EXTENDED_ASSERT_TRUE(ValidatePackageRWFS(pkgid, std::get<0>(l)));
389 EXTENDED_ASSERT_TRUE(ValidatePackageRWFS(pkgid, kTestUserId));
394 void ValidateExternalPackageFS(const std::string& pkgid,
395 const std::vector<std::string>& appids,
396 uid_t uid, gid_t gid) {
397 ASSERT_EQ(app2ext_usr_enable_external_pkg(pkgid.c_str(), uid), 0);
398 bf::path root_path = ci::GetRootAppPath(false, uid);
399 ASSERT_TRUE(bf::exists(root_path / pkgid / ".mmc" / "res"));
400 ValidatePackageFS(pkgid, appids, uid, gid, false);
401 ASSERT_EQ(app2ext_usr_disable_external_pkg(pkgid.c_str(), uid), 0);
404 void ValidateExternalPackage(const std::string& pkgid,
405 const std::vector<std::string>& appids) {
406 ASSERT_TRUE(ci::QueryIsPackageInstalled(
407 pkgid, ci::GetRequestMode(kTestUserId),
409 std::string storage = ci::QueryStorageForPkgId(pkgid, kTestUserId);
410 bf::path ext_mount_path = ci::GetExternalCardPath();
411 if (bf::is_empty(ext_mount_path)) {
412 LOG(INFO) << "Sdcard not exists!";
413 ASSERT_EQ(storage, "installed_internal");
415 ASSERT_EQ(storage, "installed_external");
417 ValidateExternalPackageFS(pkgid, appids, kTestUserId, kTestGroupId);
418 if (kTestUserId == kGlobalUserUid) {
419 ci::UserList list = ci::GetUserList();
421 ValidatePackageRWFS(pkgid, std::get<0>(l));
423 ValidatePackageRWFS(pkgid, kTestUserId);
427 bool CheckPackageNonExistance(const std::string& pkgid,
428 const std::vector<std::string>& appids) {
429 EXTENDED_ASSERT_FALSE(ci::QueryIsPackageInstalled(
430 pkgid, ci::GetRequestMode(kTestUserId),
432 PackageCheckCleanup(pkgid, appids);
433 if (kTestUserId == kGlobalUserUid) {
434 ci::UserList list = ci::GetUserList();
435 bf::path skel_path(kSkelDir);
436 EXTENDED_ASSERT_FALSE(bf::exists(skel_path / pkgid));
437 for (auto& l : list) {
438 bf::path root_path = ci::GetRootAppPath(false, std::get<0>(l));
439 bf::path package_path = root_path / pkgid;
440 EXTENDED_ASSERT_FALSE(bf::exists(package_path));
446 void CheckPackageReadonlyNonExistance(const std::string& pkgid,
447 const std::vector<std::string>& appids) {
448 ASSERT_FALSE(ci::QueryIsPackageInstalled(
449 pkgid, ci::GetRequestMode(kTestUserId), kTestUserId));
450 PackageCheckCleanup(pkgid, appids, true);
453 std::unique_ptr<ci::AppQueryInterface> CreateQueryInterface() {
454 std::unique_ptr<ci::AppQueryInterface> query_interface(
455 new wgt::WgtAppQueryInterface());
456 return query_interface;
459 std::unique_ptr<ci::AppInstaller> CreateInstaller(ci::PkgMgrPtr pkgmgr,
462 case PackageType::WGT:
463 return std::unique_ptr<ci::AppInstaller>(new wgt::WgtInstaller(pkgmgr));
464 case PackageType::HYBRID:
465 return std::unique_ptr<ci::AppInstaller>(
466 new hybrid::HybridInstaller(pkgmgr));
468 LOG(ERROR) << "Unknown installer type";
473 void TestRollbackAfterEachStep(int argc, const char*argv[],
474 std::function<bool()> validator,
476 TestPkgmgrInstaller pkgmgr_installer;
477 std::unique_ptr<ci::AppQueryInterface> query_interface =
478 CreateQueryInterface();
480 ci::PkgMgrInterface::Create(argc, const_cast<char**>(argv),
482 query_interface.get());
484 LOG(ERROR) << "Failed to initialize pkgmgr interface";
487 std::unique_ptr<ci::AppInstaller> backend = CreateInstaller(pkgmgr, type);
489 for (i = backend->StepCount()-1; i >= 0; i--) {
490 backend->AddStepAtIndex<ci::configuration::StepFail>(i);
491 LOG(DEBUG) << "StepFail is inserted at: " << i;
492 ASSERT_EQ(ci::AppInstaller::Result::ERROR,
500 void CrashAfterEachStep(std::vector<std::string> args,
501 std::function<bool(int iter)> validator,
503 std::unique_ptr<const char*[]> argv(new const char*[args.size()]);
504 for (size_t i = 0; i < args.size(); ++i) {
505 argv[i] = args[i].c_str();
507 TestPkgmgrInstaller pkgmgr_installer;
508 std::unique_ptr<ci::AppQueryInterface> query_interface =
509 CreateQueryInterface();
511 ci::PkgMgrInterface::Create(args.size(), const_cast<char**>(argv.get()),
513 query_interface.get());
515 LOG(ERROR) << "Failed to initialize pkgmgr interface";
518 std::unique_ptr<ci::AppInstaller> backend = CreateInstaller(pkgmgr, type);
519 int stepCount = backend->StepCount();
521 args.push_back("-idx");
522 args.push_back(std::to_string(stepCount));
524 for (i = 0; i < stepCount; i++) {
525 ci::Subprocess backend_crash("/usr/bin/wgt-backend-ut/smoke-test-helper");
526 args.back() = std::to_string(i);
527 backend_crash.Run(args);
528 ASSERT_NE(backend_crash.Wait(), 0);
532 ASSERT_EQ(stepCount, i);
535 ci::AppInstaller::Result RunInstallerWithPkgrmgr(ci::PkgMgrPtr pkgmgr,
537 RequestResult mode) {
538 std::unique_ptr<ci::AppInstaller> installer = CreateInstaller(pkgmgr, type);
540 case RequestResult::FAIL:
541 installer->AddStep<ci::configuration::StepFail>();
546 return installer->Run();
548 ci::AppInstaller::Result CallBackend(int argc,
551 RequestResult mode) {
552 TestPkgmgrInstaller pkgmgr_installer;
553 std::unique_ptr<ci::AppQueryInterface> query_interface =
554 CreateQueryInterface();
556 ci::PkgMgrInterface::Create(argc, const_cast<char**>(argv),
557 &pkgmgr_installer, query_interface.get());
559 LOG(ERROR) << "Failed to initialize pkgmgr interface";
560 return ci::AppInstaller::Result::UNKNOWN;
562 return RunInstallerWithPkgrmgr(pkgmgr, type, mode);
565 ci::AppInstaller::Result Install(const bf::path& path,
567 RequestResult mode) {
568 const char* argv[] = {"", "-i", path.c_str(), "-u", kTestUserIdStr.c_str()};
569 return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
572 ci::AppInstaller::Result InstallPreload(const bf::path& path, PackageType type,
573 RequestResult mode) {
574 const char* argv[] = {"", "-i", path.c_str(), "--preload"};
575 return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
578 bool CheckAvailableExternalPath() {
579 bf::path ext_mount_path = ci::GetExternalCardPath();
580 LOG(DEBUG) << "ext_mount_path :" << ext_mount_path;
581 if (ext_mount_path.empty()) {
582 LOG(ERROR) << "Sdcard not exists!";
588 ci::AppInstaller::Result InstallExternal(const bf::path& path,
590 RequestResult mode) {
591 int default_storage = 0;
592 vconf_get_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT,
594 vconf_set_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT, 1);
596 const char* argv[] = {"", "-i", path.c_str(), "-u", kTestUserIdStr.c_str()};
597 ci::AppInstaller::Result result =
598 CallBackend(SIZEOFARRAY(argv), argv, type, mode);
600 vconf_set_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT,
605 ci::AppInstaller::Result MigrateLegacyExternalImage(const std::string& pkgid,
606 const bf::path& path,
607 const bf::path& legacy_path,
609 RequestResult mode) {
610 if (InstallExternal(path, type) != ci::AppInstaller::Result::OK) {
611 LOG(ERROR) << "Failed to install application. Cannot perform Migrate";
612 return ci::AppInstaller::Result::ERROR;
615 bf::path ext_mount_path = ci::GetExternalCardPath();
616 if (bf::is_empty(ext_mount_path)) {
617 LOG(ERROR) << "Sdcard not exists!";
618 return ci::AppInstaller::Result::ERROR;
620 bf::path app2sd_path = ext_mount_path / "app2sd";
622 char* image_name = app2ext_usr_getname_image(pkgid.c_str(),
625 LOG(ERROR) << "Failed to get external image name";
626 return ci::AppInstaller::Result::ERROR;
628 bf::path org_image = app2sd_path / image_name;
631 bs::error_code error;
632 bf::remove(org_image, error);
634 LOG(ERROR) << "Failed to remove org image";
635 return ci::AppInstaller::Result::ERROR;
638 bf::path db_path = tzplatform_getenv(TZ_SYS_DB);
639 bf::path app2sd_db = db_path / ".app2sd.db";
640 bf::path app2sd_db_journal = db_path / ".app2sd.db-journal";
641 bf::remove(app2sd_db, error);
643 LOG(ERROR) << "Failed to remove app2sd db";
644 return ci::AppInstaller::Result::ERROR;
646 bf::remove(app2sd_db_journal, error);
648 LOG(ERROR) << "Failed to remove app2sd journal db";
649 return ci::AppInstaller::Result::ERROR;
652 bf::path app2sd_migrate_db = legacy_path / kMigrateTestDBName;
653 if (!ci::CopyFile(app2sd_migrate_db, app2sd_db)) {
654 LOG(ERROR) << "Failed to copy test db";
655 return ci::AppInstaller::Result::ERROR;
658 bf::path legacy_src = legacy_path / pkgid;
659 bf::path legacy_dst = app2sd_path / pkgid;
660 if (!ci::CopyFile(legacy_src, legacy_dst)) {
661 LOG(ERROR) << "Failed to copy test image";
662 return ci::AppInstaller::Result::ERROR;
664 const char* argv[] = {"", "--migrate-extimg", pkgid.c_str(),
665 "-u", kTestUserIdStr.c_str()};
666 return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
669 ci::AppInstaller::Result MountInstall(const bf::path& path,
670 PackageType type, RequestResult mode) {
671 const char* argv[] = {"", "-w", path.c_str(), "-u", kTestUserIdStr.c_str()};
672 return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
675 ci::AppInstaller::Result Uninstall(const std::string& pkgid,
678 RequestResult mode) {
680 const char* argv[] = {"", "-d", pkgid.c_str(), "--preload",
682 return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
684 const char* argv[] = {"", "-d", pkgid.c_str(), "-u",
685 kTestUserIdStr.c_str()};
686 return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
690 ci::AppInstaller::Result RDSUpdate(const bf::path& path,
691 const std::string& pkgid,
693 RequestResult mode) {
694 if (Install(path, type) != ci::AppInstaller::Result::OK) {
695 LOG(ERROR) << "Failed to install application. Cannot perform RDS";
696 return ci::AppInstaller::Result::UNKNOWN;
698 const char* argv[] = {"", "-r", pkgid.c_str(), "-u",
699 kTestUserIdStr.c_str()};
700 return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
703 ci::AppInstaller::Result DeltaInstall(const bf::path& path,
704 const bf::path& delta_package, PackageType type) {
705 if (Install(path, type) != ci::AppInstaller::Result::OK) {
706 LOG(ERROR) << "Failed to install application. Cannot perform delta update";
707 return ci::AppInstaller::Result::UNKNOWN;
709 return Install(delta_package, type);
712 ci::AppInstaller::Result EnablePackage(const std::string& pkgid,
714 RequestResult mode) {
715 const char* argv[] = {"", "-A", pkgid.c_str(), "-u", kTestUserIdStr.c_str()};
716 return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
719 ci::AppInstaller::Result DisablePackage(const std::string& pkgid,
721 RequestResult mode) {
722 const char* argv[] = {"", "-D", pkgid.c_str(), "-u", kTestUserIdStr.c_str()};
723 return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
726 ci::AppInstaller::Result Recover(const bf::path& recovery_file,
728 RequestResult mode) {
729 const char* argv[] = {"", "-b", recovery_file.c_str(), "-u",
730 kTestUserIdStr.c_str()};
731 return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
734 ci::AppInstaller::Result ManifestDirectInstall(const std::string& pkgid,
736 RequestResult mode) {
737 const char* argv[] = {"", "-y", pkgid.c_str(), "-u", kTestUserIdStr.c_str()};
738 return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
743 boost::filesystem::path GetTrashPath(const boost::filesystem::path& path) {
744 return path.string() + ".trash";
749 bool BackupPath(const bf::path& path) {
750 bf::path trash_path = GetTrashPath(path);
751 if (bf::exists(trash_path)) {
752 LOG(ERROR) << trash_path << " exists. Please remove "
753 << trash_path << " manually!";
756 bf::path backup_path = path.string() + ".bck";
757 std::cout << "Backup path: " << path << " to " << backup_path << std::endl;
758 bs::error_code error;
759 bf::remove_all(backup_path, error);
761 LOG(ERROR) << "Remove failed: " << backup_path
762 << " (" << error.message() << ")";
763 if (bf::exists(path)) {
764 bf::rename(path, backup_path, error);
766 LOG(ERROR) << "Failed to setup test environment. Does some previous"
767 << " test crashed? Path: "
768 << backup_path << " should not exist.";
776 bool RestorePath(const bf::path& path) {
777 bf::path backup_path = path.string() + ".bck";
778 std::cout << "Restore path: " << path << " from " << backup_path << std::endl;
779 bs::error_code error;
780 bf::remove_all(path, error);
782 bf::path trash_path = GetTrashPath(path);
783 LOG(ERROR) << "Remove failed: " << path << " (" << error.message() << ")";
784 std::cout << "Moving " << path << " to " << trash_path << std::endl;
785 bf::rename(path, trash_path, error);
787 LOG(ERROR) << "Failed to move " << path << " to " << trash_path
788 << " (" << error.message() << ")";
790 LOG(ERROR) << trash_path << " should be removed manually!";
792 if (bf::exists(backup_path)) {
793 bf::rename(backup_path, path, error);
795 LOG(ERROR) << "Failed to restore backup path: " << backup_path
796 << " (" << error.message() << ")";
803 std::vector<bf::path> SetupBackupDirectories() {
804 std::vector<bf::path> entries;
805 bf::path db_dir = bf::path(tzplatform_getenv(TZ_SYS_DB));
806 if (kTestUserId != kGlobalUserUid)
807 db_dir = db_dir / "user" / std::to_string(kTestUserId);
808 for (auto e : kDBEntries) {
809 bf::path path = db_dir / e;
810 entries.emplace_back(path);
814 entries.emplace_back(kPreloadApps);
815 entries.emplace_back(kPreloadManifestDir);
816 entries.emplace_back(kPreloadIcons);
819 if (kTestUserId == kGlobalUserUid) {
820 entries.emplace_back(kSkelDir);
821 entries.emplace_back(kGlobalManifestDir);
822 ci::UserList list = ci::GetUserList();
823 for (auto l : list) {
824 bf::path apps = std::get<2>(l) / "apps_rw";
825 entries.emplace_back(apps);
828 tzplatform_set_user(kTestUserId);
829 bf::path approot = tzplatform_getenv(TZ_USER_APPROOT);
830 tzplatform_reset_user();
831 entries.emplace_back(approot);
834 bf::path apps_rw = ci::GetRootAppPath(false, kTestUserId);
835 entries.emplace_back(apps_rw);
840 void UninstallAllAppsInDirectory(bf::path dir, bool is_preload) {
841 if (bf::exists(dir)) {
842 for (auto& dir_entry : boost::make_iterator_range(
843 bf::directory_iterator(dir), bf::directory_iterator())) {
844 if (dir_entry.path().string().find("smoke") != std::string::npos &&
845 bf::is_directory(dir_entry)) {
846 std::string package = dir_entry.path().filename().string();
847 std::regex pkg_regex("smoke[a-zA-Z0-9]{5,}");
848 if (std::regex_match(package, pkg_regex)) {
849 if (Uninstall(dir_entry.path().filename().string(), PackageType::WGT,
850 is_preload, RequestResult::NORMAL) !=
851 ci::AppInstaller::Result::OK) {
852 LOG(ERROR) << "Cannot uninstall smoke test app: "
853 << dir_entry.path().filename().string();
861 void UninstallAllSmokeApps(ci::RequestMode request_mode) {
862 std::cout << "Uninstalling all smoke apps" << std::endl;
863 bf::path apps_rw = ci::GetRootAppPath(false, kTestUserId);
864 UninstallAllAppsInDirectory(apps_rw, false);
865 if (getuid() == 0 && request_mode == ci::RequestMode::GLOBAL) {
866 bf::path root_path = kPreloadApps;
867 UninstallAllAppsInDirectory(root_path, true);
871 int GetAppInstalledTime(const char *appid, uid_t uid)
874 int installed_time = 0;
875 pkgmgrinfo_appinfo_h handle = NULL;
876 ret = pkgmgrinfo_appinfo_get_usr_appinfo(appid, uid, &handle);
877 if (ret != PMINFO_R_OK)
879 ret = pkgmgrinfo_appinfo_get_installed_time(handle, &installed_time);
880 if (ret != PMINFO_R_OK) {
881 pkgmgrinfo_appinfo_destroy_appinfo(handle);
884 pkgmgrinfo_appinfo_destroy_appinfo(handle);
885 return installed_time;