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 <pkgmgr-info.h>
23 #include <tzplatform_config.h>
25 #include <vconf-internal-keys.h>
32 #include "wgt/wgt_installer.h"
34 #include "unit_tests/smoke_utils.h"
36 namespace bo = boost::program_options;
38 const uid_t kGlobalUserUid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
39 const uid_t kGlobalUserGid = tzplatform_getgid(TZ_SYS_GLOBALAPP_USER);
40 const uid_t kDefaultUserUid = tzplatform_getuid(TZ_SYS_DEFAULT_USER);
41 uid_t kTestUserId = kGlobalUserUid;
42 gid_t kTestGroupId = kGlobalUserGid;
43 const char kNormalUserName[] = "smokeuser";
44 const char kSystemShareGroupName[] = "system_share";
45 std::string kTestUserIdStr = std::to_string(kTestUserId);
46 const std::string& kDefaultUserIdStr = std::to_string(kDefaultUserUid);
47 const char kLegacyExtImageDir[] = "legacy_extimage_dir";
48 const char kMigrateTestDBName[] = "app2sd_migrate.db";
50 const bf::path kSmokePackagesDirectory =
51 "/usr/share/wgt-backend-ut/test_samples/smoke/";
54 const char* rwDirectories[] = {
63 const std::vector<std::string> kDBEntries = {
64 {".pkgmgr_parser.db"},
65 {".pkgmgr_parser.db-journal"},
67 {".pkgmgr_cert.db-journal"},
69 {".app2sd.db-journal"},
72 const char kGlobalManifestDir[] = "/opt/share/packages";
73 const char kSkelDir[] = "/etc/skel/apps_rw";
74 const char kPreloadApps[] = "/usr/apps";
75 const char kPreloadManifestDir[] = "/usr/share/packages";
76 const char kPreloadIcons[] = "/usr/share/icons";
78 testing::Environment *env = nullptr;
79 void signalHandler(int signum) {
84 ci::RequestMode ParseRequestMode(int argc, char** argv) {
85 bo::options_description desc("Available options");
87 ("request-mode", bo::value<std::string>(), "set request mode")
88 ("global-request,g", "set request mode to global")
89 ("user-request,u", "set request mode to user");
92 bo::store(bo::command_line_parser(argc, argv).
93 options(desc).allow_unregistered().run(), vm);
96 if (vm.count("global-request")) {
97 std::cout << "Request mode was set to global." << std::endl;
98 return ci::RequestMode::GLOBAL;
100 if (vm.count("user-request")) {
101 std::cout << "Request mode was set to user." << std::endl;
102 return ci::RequestMode::USER;
104 if (vm.count("request-mode")) {
105 if (vm["request-mode"].as<std::string>() == "global") {
106 std::cout << "Request mode was set to global." << std::endl;
107 return ci::RequestMode::GLOBAL;
109 if (vm["request-mode"].as<std::string>() == "user") {
110 std::cout << "Request mode was set to user." << std::endl;
111 return ci::RequestMode::USER;
113 std::cout << "Cannot set request mode to "
114 << vm["request-mode"].as<std::string>() << std::endl;
116 std::cout << "Request mode was set to global." << std::endl;
117 return ci::RequestMode::GLOBAL;
120 bool TouchFile(const bf::path& path) {
121 FILE* f = fopen(path.c_str(), "w+");
128 bool AddUser(const char *user_name) {
129 GumUser* user = nullptr;
130 user = gum_user_create_sync(FALSE);
132 LOG(WARNING) << "Failed to create gum user! (user name: "
134 g_object_set(G_OBJECT(user), "username", user_name, "usertype",
135 GUM_USERTYPE_NORMAL, NULL);
136 gboolean rval = FALSE;
137 rval = gum_user_add_sync(user);
138 g_object_unref(user);
142 bool DeleteUser(const char *user_name, bool rem_home_dir) {
144 GumUser* guser = gum_user_get_by_name_sync(user_name, FALSE);
146 rval = gum_user_delete_sync(guser, rem_home_dir);
150 bool AddTestUser(const char *user_name) {
151 std::cout << "Adding test user: " << user_name << std::endl;
153 if (boost::optional<uid_t> uid = ci::GetUidByUserName(user_name)) {
155 kTestUserIdStr = std::to_string(kTestUserId);
156 std::cout << "User created properly: uid=" << *uid;
157 if (boost::optional<gid_t> gid = ci::GetGidByUid(*uid)) {
159 std::cout << " gid=" << *gid;
161 std::cout << std::endl;
164 LOG(ERROR) << "Adding test user failed";
168 bool DeleteTestUser(const char *user_name) {
169 std::cout << "Deleting test user: " << user_name << std::endl;
171 if (boost::optional<uid_t> uid = ci::GetUidByUserName(user_name))
173 DeleteUser(user_name, true);
174 if (!ci::GetUidByUserName(user_name)) {
175 std::cout << "User deleted properly: user_name=" << user_name
176 << " uid=" << test_uid << std::endl;
179 LOG(ERROR) << "Deleting test user failed";
183 void RemoveAllRecoveryFiles() {
184 bf::path root_path = ci::GetRootAppPath(false,
186 if (!bf::exists(root_path))
188 for (auto& dir_entry : boost::make_iterator_range(
189 bf::directory_iterator(root_path), bf::directory_iterator())) {
190 if (bf::is_regular_file(dir_entry)) {
191 if (dir_entry.path().string().find("/wgt-recovery")
192 != std::string::npos) {
193 bs::error_code error;
194 bf::remove(dir_entry.path(), error);
200 bf::path FindRecoveryFile() {
201 bf::path root_path = ci::GetRootAppPath(false,
203 for (auto& dir_entry : boost::make_iterator_range(
204 bf::directory_iterator(root_path), bf::directory_iterator())) {
205 if (bf::is_regular_file(dir_entry)) {
206 if (dir_entry.path().string().find("/wgt-recovery")
207 != std::string::npos) {
208 return dir_entry.path();
215 bf::path GetPackageRoot(const std::string& pkgid, uid_t uid) {
216 bf::path root_path = ci::GetRootAppPath(false, uid);
217 return root_path / pkgid;
220 bool ValidateFileContentInPackage(const std::string& pkgid,
221 const std::string& relative,
222 const std::string& expected,
224 bf::path file_path = ci::GetRootAppPath(is_readonly, kTestUserId);
225 file_path = file_path / pkgid / relative;
226 if (!bf::exists(file_path)) {
227 LOG(ERROR) << file_path << " doesn't exist";
230 FILE* handle = fopen(file_path.c_str(), "r");
232 LOG(ERROR) << file_path << " cannot be open";
236 std::array<char, 200> buffer;
237 while (fgets(buffer.data(), buffer.size(), handle)) {
238 content += buffer.data();
241 return content == expected;
244 void AddDataFiles(const std::string& pkgid, uid_t uid) {
245 if (uid == kGlobalUserUid) {
246 ci::UserList list = ci::GetUserList();
247 for (auto l : list) {
248 auto pkg_path = GetPackageRoot(pkgid, std::get<0>(l));
249 ASSERT_TRUE(TouchFile(pkg_path / "data" / "file1.txt"));
250 ASSERT_TRUE(TouchFile(pkg_path / "data" / "file2.txt"));
253 auto pkg_path = GetPackageRoot(pkgid, uid);
254 ASSERT_TRUE(TouchFile(pkg_path / "data" / "file1.txt"));
255 ASSERT_TRUE(TouchFile(pkg_path / "data" / "file2.txt"));
259 bool ValidateDataFiles(const std::string& pkgid, uid_t uid) {
260 if (uid == kGlobalUserUid) {
261 ci::UserList list = ci::GetUserList();
262 for (auto l : list) {
263 auto pkg_path = GetPackageRoot(pkgid, std::get<0>(l));
264 EXTENDED_ASSERT_TRUE(bf::exists(pkg_path / "data" / "file1.txt"));
265 EXTENDED_ASSERT_TRUE(bf::exists(pkg_path / "data" / "file2.txt"));
268 auto pkg_path = GetPackageRoot(pkgid, uid);
269 EXTENDED_ASSERT_TRUE(bf::exists(pkg_path / "data" / "file1.txt"));
270 EXTENDED_ASSERT_TRUE(bf::exists(pkg_path / "data" / "file2.txt"));
275 bool ValidatePackageRWFS(const std::string& pkgid, uid_t uid) {
276 bf::path root_path = ci::GetRootAppPath(false, uid);
277 bf::path package_path = root_path / pkgid;
278 bf::path data_path = package_path / rwDirectories[DATA];
279 bf::path cache_path = package_path / rwDirectories[CACHE];
280 bf::path shared_data_path = package_path / rwDirectories[SHARED_DATA];
282 EXTENDED_ASSERT_TRUE(bf::exists(data_path));
283 EXTENDED_ASSERT_TRUE(bf::exists(cache_path));
286 stat(data_path.c_str(), &stats);
287 // gid of RW dirs should be system_share
288 boost::optional<gid_t> system_share =
289 ci::GetGidByGroupName(kSystemShareGroupName);
290 EXTENDED_ASSERT_EQ(uid, stats.st_uid);
291 EXTENDED_ASSERT_EQ(*system_share, stats.st_gid);
292 if (bf::exists(shared_data_path)) {
293 stat(shared_data_path.c_str(), &stats);
294 EXTENDED_ASSERT_EQ(uid, stats.st_uid);
295 EXTENDED_ASSERT_EQ(*system_share, stats.st_gid);
298 stat(cache_path.c_str(), &stats);
299 EXTENDED_ASSERT_EQ(uid, stats.st_uid);
300 EXTENDED_ASSERT_EQ(*system_share, stats.st_gid);
304 bool ValidatePackageFS(const std::string& pkgid,
305 const std::vector<std::string>& appids,
306 uid_t uid, gid_t gid, bool is_readonly) {
307 bf::path root_path = ci::GetRootAppPath(is_readonly, uid);
308 bf::path package_path = root_path / pkgid;
309 bf::path shared_path = package_path / "shared";
310 EXTENDED_ASSERT_TRUE(bf::exists(root_path));
311 EXTENDED_ASSERT_TRUE(bf::exists(package_path));
312 EXTENDED_ASSERT_TRUE(bf::exists(shared_path));
314 bf::path manifest_path =
315 bf::path(getUserManifestPath(uid, is_readonly)) / (pkgid + ".xml");
316 EXTENDED_ASSERT_TRUE(bf::exists(manifest_path));
318 for (auto& appid : appids) {
319 bf::path binary_path = package_path / "bin" / appid;
320 EXTENDED_ASSERT_TRUE(bf::exists(binary_path));
323 bf::path widget_root_path = package_path / "res" / "wgt";
324 bf::path config_path = widget_root_path / "config.xml";
325 EXTENDED_ASSERT_TRUE(bf::exists(widget_root_path));
326 EXTENDED_ASSERT_TRUE(bf::exists(config_path));
328 bf::path private_tmp_path = package_path / "tmp";
329 EXTENDED_ASSERT_TRUE(bf::exists(private_tmp_path));
331 // backups should not exist
332 bf::path package_backup = ci::GetBackupPathForPackagePath(package_path);
333 bf::path manifest_backup = ci::GetBackupPathForManifestFile(manifest_path);
334 EXTENDED_ASSERT_FALSE(bf::exists(package_backup));
335 EXTENDED_ASSERT_FALSE(bf::exists(manifest_backup));
337 for (bf::recursive_directory_iterator iter(package_path);
338 iter != bf::recursive_directory_iterator(); ++iter) {
339 if (bf::is_symlink(symlink_status(iter->path())))
341 bool is_rw_dir = false;
342 for (const auto rw_dir : rwDirectories) {
343 bf::path rw_dir_path = rw_dir;
344 is_rw_dir |= ci::MakeRelativePath(iter->path(), package_path)
347 if (is_rw_dir || iter->path().filename() == ".mmc") {
352 stat(iter->path().c_str(), &stats);
353 EXTENDED_ASSERT_EQ(uid, stats.st_uid);
354 EXTENDED_ASSERT_EQ(gid, stats.st_gid);
359 void PackageCheckCleanup(const std::string& pkgid,
360 const std::vector<std::string>&, bool is_readonly) {
361 bf::path root_path = ci::GetRootAppPath(is_readonly, kTestUserId);
362 bf::path package_path = root_path / pkgid;
363 ASSERT_FALSE(bf::exists(package_path));
365 bf::path manifest_path = bf::path(getUserManifestPath(kTestUserId,
366 is_readonly)) / (pkgid + ".xml");
367 ASSERT_FALSE(bf::exists(manifest_path));
369 // backups should not exist
370 bf::path package_backup = ci::GetBackupPathForPackagePath(package_path);
371 bf::path manifest_backup = ci::GetBackupPathForManifestFile(manifest_path);
372 ASSERT_FALSE(bf::exists(package_backup));
373 ASSERT_FALSE(bf::exists(manifest_backup));
376 bool ValidatePackage(const std::string& pkgid,
377 const std::vector<std::string>& appids, bool is_readonly) {
378 EXTENDED_ASSERT_TRUE(ci::QueryIsPackageInstalled(
379 pkgid, ci::GetRequestMode(kTestUserId), kTestUserId));
380 EXTENDED_ASSERT_TRUE(ValidatePackageFS(
381 pkgid, appids, kTestUserId, kTestGroupId, is_readonly));
382 if (kTestUserId == kGlobalUserUid) {
383 ci::UserList list = ci::GetUserList();
385 EXTENDED_ASSERT_TRUE(ValidatePackageRWFS(pkgid, std::get<0>(l)));
387 EXTENDED_ASSERT_TRUE(ValidatePackageRWFS(pkgid, kTestUserId));
392 void ValidateExternalPackageFS(const std::string& pkgid,
393 const std::vector<std::string>& appids,
394 uid_t uid, gid_t gid) {
395 ASSERT_EQ(app2ext_usr_enable_external_pkg(pkgid.c_str(), uid), 0);
396 bf::path root_path = ci::GetRootAppPath(false, uid);
397 ASSERT_TRUE(bf::exists(root_path / pkgid / ".mmc" / "res"));
398 ValidatePackageFS(pkgid, appids, uid, gid, false);
399 ASSERT_EQ(app2ext_usr_disable_external_pkg(pkgid.c_str(), uid), 0);
402 void ValidateExternalPackage(const std::string& pkgid,
403 const std::vector<std::string>& appids) {
404 ASSERT_TRUE(ci::QueryIsPackageInstalled(
405 pkgid, ci::GetRequestMode(kTestUserId),
407 std::string storage = ci::QueryStorageForPkgId(pkgid, kTestUserId);
408 bf::path ext_mount_path = ci::GetExternalCardPath();
409 if (bf::is_empty(ext_mount_path)) {
410 LOG(INFO) << "Sdcard not exists!";
411 ASSERT_EQ(storage, "installed_internal");
413 ASSERT_EQ(storage, "installed_external");
415 ValidateExternalPackageFS(pkgid, appids, kTestUserId, kTestGroupId);
416 if (kTestUserId == kGlobalUserUid) {
417 ci::UserList list = ci::GetUserList();
419 ValidatePackageRWFS(pkgid, std::get<0>(l));
421 ValidatePackageRWFS(pkgid, kTestUserId);
425 bool CheckPackageNonExistance(const std::string& pkgid,
426 const std::vector<std::string>& appids) {
427 EXTENDED_ASSERT_FALSE(ci::QueryIsPackageInstalled(
428 pkgid, ci::GetRequestMode(kTestUserId),
430 PackageCheckCleanup(pkgid, appids);
431 if (kTestUserId == kGlobalUserUid) {
432 ci::UserList list = ci::GetUserList();
433 bf::path skel_path(kSkelDir);
434 EXTENDED_ASSERT_FALSE(bf::exists(skel_path / pkgid));
435 for (auto& l : list) {
436 bf::path root_path = ci::GetRootAppPath(false, std::get<0>(l));
437 bf::path package_path = root_path / pkgid;
438 EXTENDED_ASSERT_FALSE(bf::exists(package_path));
444 void CheckPackageReadonlyNonExistance(const std::string& pkgid,
445 const std::vector<std::string>& appids) {
446 ASSERT_FALSE(ci::QueryIsPackageInstalled(
447 pkgid, ci::GetRequestMode(kTestUserId), kTestUserId));
448 PackageCheckCleanup(pkgid, appids, true);
451 std::unique_ptr<ci::AppQueryInterface> CreateQueryInterface() {
452 std::unique_ptr<ci::AppQueryInterface> query_interface(
453 new wgt::WgtAppQueryInterface());
454 return query_interface;
457 std::unique_ptr<ci::AppInstaller> CreateInstaller(ci::PkgMgrPtr pkgmgr,
460 case PackageType::WGT:
461 return std::unique_ptr<ci::AppInstaller>(new wgt::WgtInstaller(pkgmgr));
462 case PackageType::HYBRID:
463 return std::unique_ptr<ci::AppInstaller>(
464 new hybrid::HybridInstaller(pkgmgr));
466 LOG(ERROR) << "Unknown installer type";
471 void TestRollbackAfterEachStep(int argc, const char*argv[],
472 std::function<bool()> validator,
474 TestPkgmgrInstaller pkgmgr_installer;
475 std::unique_ptr<ci::AppQueryInterface> query_interface =
476 CreateQueryInterface();
478 ci::PkgMgrInterface::Create(argc, const_cast<char**>(argv),
480 query_interface.get());
482 LOG(ERROR) << "Failed to initialize pkgmgr interface";
485 std::unique_ptr<ci::AppInstaller> backend = CreateInstaller(pkgmgr, type);
487 for (i = backend->StepCount()-1; i >= 0; i--) {
488 backend->AddStepAtIndex<ci::configuration::StepFail>(i);
489 LOG(DEBUG) << "StepFail is inserted at: " << i;
490 ASSERT_EQ(ci::AppInstaller::Result::ERROR,
498 void CrashAfterEachStep(std::vector<std::string> args,
499 std::function<bool(int iter)> validator,
501 std::unique_ptr<const char*[]> argv(new const char*[args.size()]);
502 for (size_t i = 0; i < args.size(); ++i) {
503 argv[i] = args[i].c_str();
505 TestPkgmgrInstaller pkgmgr_installer;
506 std::unique_ptr<ci::AppQueryInterface> query_interface =
507 CreateQueryInterface();
509 ci::PkgMgrInterface::Create(args.size(), const_cast<char**>(argv.get()),
511 query_interface.get());
513 LOG(ERROR) << "Failed to initialize pkgmgr interface";
516 std::unique_ptr<ci::AppInstaller> backend = CreateInstaller(pkgmgr, type);
517 int stepCount = backend->StepCount();
519 args.push_back("-idx");
520 args.push_back(std::to_string(stepCount));
522 for (i = 0; i < stepCount; i++) {
523 ci::Subprocess backend_crash("/usr/bin/wgt-backend-ut/smoke-test-helper");
524 args.back() = std::to_string(i);
525 backend_crash.Run(args);
526 ASSERT_NE(backend_crash.Wait(), 0);
530 ASSERT_EQ(stepCount, i);
533 ci::AppInstaller::Result RunInstallerWithPkgrmgr(ci::PkgMgrPtr pkgmgr,
535 RequestResult mode) {
536 std::unique_ptr<ci::AppInstaller> installer = CreateInstaller(pkgmgr, type);
538 case RequestResult::FAIL:
539 installer->AddStep<ci::configuration::StepFail>();
544 return installer->Run();
546 ci::AppInstaller::Result CallBackend(int argc,
549 RequestResult mode) {
550 TestPkgmgrInstaller pkgmgr_installer;
551 std::unique_ptr<ci::AppQueryInterface> query_interface =
552 CreateQueryInterface();
554 ci::PkgMgrInterface::Create(argc, const_cast<char**>(argv),
555 &pkgmgr_installer, query_interface.get());
557 LOG(ERROR) << "Failed to initialize pkgmgr interface";
558 return ci::AppInstaller::Result::UNKNOWN;
560 return RunInstallerWithPkgrmgr(pkgmgr, type, mode);
563 ci::AppInstaller::Result Install(const bf::path& path,
565 RequestResult mode) {
566 const char* argv[] = {"", "-i", path.c_str(), "-u", kTestUserIdStr.c_str()};
567 return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
570 ci::AppInstaller::Result InstallPreload(const bf::path& path, PackageType type,
571 RequestResult mode) {
572 const char* argv[] = {"", "-i", path.c_str(), "--preload"};
573 return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
576 bool CheckAvailableExternalPath() {
577 bf::path ext_mount_path = ci::GetExternalCardPath();
578 LOG(DEBUG) << "ext_mount_path :" << ext_mount_path;
579 if (ext_mount_path.empty()) {
580 LOG(ERROR) << "Sdcard not exists!";
586 ci::AppInstaller::Result InstallExternal(const bf::path& path,
588 RequestResult mode) {
589 int default_storage = 0;
590 vconf_get_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT,
592 vconf_set_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT, 1);
594 const char* argv[] = {"", "-i", path.c_str(), "-u", kTestUserIdStr.c_str()};
595 ci::AppInstaller::Result result =
596 CallBackend(SIZEOFARRAY(argv), argv, type, mode);
598 vconf_set_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT,
603 ci::AppInstaller::Result MigrateLegacyExternalImage(const std::string& pkgid,
604 const bf::path& path,
605 const bf::path& legacy_path,
607 RequestResult mode) {
608 if (InstallExternal(path, type) != ci::AppInstaller::Result::OK) {
609 LOG(ERROR) << "Failed to install application. Cannot perform Migrate";
610 return ci::AppInstaller::Result::ERROR;
613 bf::path ext_mount_path = ci::GetExternalCardPath();
614 if (bf::is_empty(ext_mount_path)) {
615 LOG(ERROR) << "Sdcard not exists!";
616 return ci::AppInstaller::Result::ERROR;
618 bf::path app2sd_path = ext_mount_path / "app2sd";
620 char* image_name = app2ext_usr_getname_image(pkgid.c_str(),
623 LOG(ERROR) << "Failed to get external image name";
624 return ci::AppInstaller::Result::ERROR;
626 bf::path org_image = app2sd_path / image_name;
629 bs::error_code error;
630 bf::remove(org_image, error);
632 LOG(ERROR) << "Failed to remove org image";
633 return ci::AppInstaller::Result::ERROR;
636 bf::path db_path = tzplatform_getenv(TZ_SYS_DB);
637 bf::path app2sd_db = db_path / ".app2sd.db";
638 bf::path app2sd_db_journal = db_path / ".app2sd.db-journal";
639 bf::remove(app2sd_db, error);
641 LOG(ERROR) << "Failed to remove app2sd db";
642 return ci::AppInstaller::Result::ERROR;
644 bf::remove(app2sd_db_journal, error);
646 LOG(ERROR) << "Failed to remove app2sd journal db";
647 return ci::AppInstaller::Result::ERROR;
650 bf::path app2sd_migrate_db = legacy_path / kMigrateTestDBName;
651 if (!ci::CopyFile(app2sd_migrate_db, app2sd_db)) {
652 LOG(ERROR) << "Failed to copy test db";
653 return ci::AppInstaller::Result::ERROR;
656 bf::path legacy_src = legacy_path / pkgid;
657 bf::path legacy_dst = app2sd_path / pkgid;
658 if (!ci::CopyFile(legacy_src, legacy_dst)) {
659 LOG(ERROR) << "Failed to copy test image";
660 return ci::AppInstaller::Result::ERROR;
662 const char* argv[] = {"", "--migrate-extimg", pkgid.c_str(),
663 "-u", kTestUserIdStr.c_str()};
664 return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
667 ci::AppInstaller::Result MountInstall(const bf::path& path,
668 PackageType type, RequestResult mode) {
669 const char* argv[] = {"", "-w", path.c_str(), "-u", kTestUserIdStr.c_str()};
670 return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
673 ci::AppInstaller::Result Uninstall(const std::string& pkgid,
676 RequestResult mode) {
678 const char* argv[] = {"", "-d", pkgid.c_str(), "--preload",
680 return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
682 const char* argv[] = {"", "-d", pkgid.c_str(), "-u",
683 kTestUserIdStr.c_str()};
684 return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
688 ci::AppInstaller::Result RDSUpdate(const bf::path& path,
689 const std::string& pkgid,
691 RequestResult mode) {
692 if (Install(path, type) != ci::AppInstaller::Result::OK) {
693 LOG(ERROR) << "Failed to install application. Cannot perform RDS";
694 return ci::AppInstaller::Result::UNKNOWN;
696 const char* argv[] = {"", "-r", pkgid.c_str(), "-u",
697 kTestUserIdStr.c_str()};
698 return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
701 ci::AppInstaller::Result DeltaInstall(const bf::path& path,
702 const bf::path& delta_package, PackageType type) {
703 if (Install(path, type) != ci::AppInstaller::Result::OK) {
704 LOG(ERROR) << "Failed to install application. Cannot perform delta update";
705 return ci::AppInstaller::Result::UNKNOWN;
707 return Install(delta_package, type);
710 ci::AppInstaller::Result EnablePackage(const std::string& pkgid,
712 RequestResult mode) {
713 const char* argv[] = {"", "-A", pkgid.c_str(), "-u", kTestUserIdStr.c_str()};
714 return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
717 ci::AppInstaller::Result DisablePackage(const std::string& pkgid,
719 RequestResult mode) {
720 const char* argv[] = {"", "-D", pkgid.c_str(), "-u", kTestUserIdStr.c_str()};
721 return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
724 ci::AppInstaller::Result Recover(const bf::path& recovery_file,
726 RequestResult mode) {
727 const char* argv[] = {"", "-b", recovery_file.c_str(), "-u",
728 kTestUserIdStr.c_str()};
729 return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
734 boost::filesystem::path GetTrashPath(const boost::filesystem::path& path) {
735 return path.string() + ".trash";
740 bool BackupPath(const bf::path& path) {
741 bf::path trash_path = GetTrashPath(path);
742 if (bf::exists(trash_path)) {
743 LOG(ERROR) << trash_path << " exists. Please remove "
744 << trash_path << " manually!";
747 bf::path backup_path = path.string() + ".bck";
748 std::cout << "Backup path: " << path << " to " << backup_path << std::endl;
749 bs::error_code error;
750 bf::remove_all(backup_path, error);
752 LOG(ERROR) << "Remove failed: " << backup_path
753 << " (" << error.message() << ")";
754 if (bf::exists(path)) {
755 bf::rename(path, backup_path, error);
757 LOG(ERROR) << "Failed to setup test environment. Does some previous"
758 << " test crashed? Path: "
759 << backup_path << " should not exist.";
767 bool RestorePath(const bf::path& path) {
768 bf::path backup_path = path.string() + ".bck";
769 std::cout << "Restore path: " << path << " from " << backup_path << std::endl;
770 bs::error_code error;
771 bf::remove_all(path, error);
773 bf::path trash_path = GetTrashPath(path);
774 LOG(ERROR) << "Remove failed: " << path << " (" << error.message() << ")";
775 std::cout << "Moving " << path << " to " << trash_path << std::endl;
776 bf::rename(path, trash_path, error);
778 LOG(ERROR) << "Failed to move " << path << " to " << trash_path
779 << " (" << error.message() << ")";
781 LOG(ERROR) << trash_path << " should be removed manually!";
783 if (bf::exists(backup_path)) {
784 bf::rename(backup_path, path, error);
786 LOG(ERROR) << "Failed to restore backup path: " << backup_path
787 << " (" << error.message() << ")";
794 std::vector<bf::path> SetupBackupDirectories() {
795 std::vector<bf::path> entries;
796 bf::path db_dir = bf::path(tzplatform_getenv(TZ_SYS_DB));
797 if (kTestUserId != kGlobalUserUid)
798 db_dir = db_dir / "user" / std::to_string(kTestUserId);
799 for (auto e : kDBEntries) {
800 bf::path path = db_dir / e;
801 entries.emplace_back(path);
805 entries.emplace_back(kPreloadApps);
806 entries.emplace_back(kPreloadManifestDir);
807 entries.emplace_back(kPreloadIcons);
810 if (kTestUserId == kGlobalUserUid) {
811 entries.emplace_back(kSkelDir);
812 entries.emplace_back(kGlobalManifestDir);
813 ci::UserList list = ci::GetUserList();
814 for (auto l : list) {
815 bf::path apps = std::get<2>(l) / "apps_rw";
816 entries.emplace_back(apps);
819 tzplatform_set_user(kTestUserId);
820 bf::path approot = tzplatform_getenv(TZ_USER_APPROOT);
821 tzplatform_reset_user();
822 entries.emplace_back(approot);
825 bf::path apps_rw = ci::GetRootAppPath(false, kTestUserId);
826 entries.emplace_back(apps_rw);
831 void UninstallAllAppsInDirectory(bf::path dir, bool is_preload) {
832 if (bf::exists(dir)) {
833 for (auto& dir_entry : boost::make_iterator_range(
834 bf::directory_iterator(dir), bf::directory_iterator())) {
835 if (dir_entry.path().string().find("smoke") != std::string::npos &&
836 bf::is_directory(dir_entry)) {
837 std::string package = dir_entry.path().filename().string();
838 std::regex pkg_regex("smoke[a-zA-Z0-9]{5,}");
839 if (std::regex_match(package, pkg_regex)) {
840 if (Uninstall(dir_entry.path().filename().string(), PackageType::WGT,
841 is_preload, RequestResult::NORMAL) !=
842 ci::AppInstaller::Result::OK) {
843 LOG(ERROR) << "Cannot uninstall smoke test app: "
844 << dir_entry.path().filename().string();
852 void UninstallAllSmokeApps(ci::RequestMode request_mode) {
853 std::cout << "Uninstalling all smoke apps" << std::endl;
854 if (getuid() == 0 && request_mode == ci::RequestMode::GLOBAL) {
855 bf::path root_path = kPreloadApps;
856 UninstallAllAppsInDirectory(root_path, true);
858 bf::path apps_rw = ci::GetRootAppPath(false, kTestUserId);
859 UninstallAllAppsInDirectory(apps_rw, false);