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";
79 ci::RequestMode ParseRequestMode(int argc, char** argv) {
80 bo::options_description desc("Available options");
82 ("request-mode", bo::value<std::string>(), "set request mode")
83 ("global-request,g", "set request mode to global")
84 ("user-request,u", "set request mode to user");
87 bo::store(bo::command_line_parser(argc, argv).
88 options(desc).allow_unregistered().run(), vm);
91 if (vm.count("global-request")) {
92 std::cout << "Request mode was set to global." << std::endl;
93 return ci::RequestMode::GLOBAL;
95 if (vm.count("user-request")) {
96 std::cout << "Request mode was set to user." << std::endl;
97 return ci::RequestMode::USER;
99 if (vm.count("request-mode")) {
100 if (vm["request-mode"].as<std::string>() == "global") {
101 std::cout << "Request mode was set to global." << std::endl;
102 return ci::RequestMode::GLOBAL;
104 if (vm["request-mode"].as<std::string>() == "user") {
105 std::cout << "Request mode was set to user." << std::endl;
106 return ci::RequestMode::USER;
108 std::cout << "Cannot set request mode to "
109 << vm["request-mode"].as<std::string>() << std::endl;
111 std::cout << "Request mode was set to global." << std::endl;
112 return ci::RequestMode::GLOBAL;
115 bool TouchFile(const bf::path& path) {
116 FILE* f = fopen(path.c_str(), "w+");
123 bool AddUser(const char *user_name) {
124 GumUser* user = nullptr;
125 user = gum_user_create_sync(FALSE);
127 LOG(WARNING) << "Failed to create gum user! (user name: "
129 g_object_set(G_OBJECT(user), "username", user_name, "usertype",
130 GUM_USERTYPE_NORMAL, NULL);
131 gboolean rval = FALSE;
132 rval = gum_user_add_sync(user);
133 g_object_unref(user);
137 bool DeleteUser(const char *user_name, bool rem_home_dir) {
139 GumUser* guser = gum_user_get_by_name_sync(user_name, FALSE);
141 rval = gum_user_delete_sync(guser, rem_home_dir);
145 bool AddTestUser(const char *user_name) {
146 std::cout << "Adding test user: " << user_name << std::endl;
147 bool ret = AddUser(user_name);
148 if (boost::optional<uid_t> uid = ci::GetUidByUserName(user_name)) {
150 kTestUserIdStr = std::to_string(kTestUserId);
151 std::cout << "User created properly: uid=" << *uid;
152 if (boost::optional<gid_t> gid = ci::GetGidByUid(*uid)) {
154 std::cout << " gid=" << *gid;
156 std::cout << std::endl;
159 LOG(ERROR) << "Adding test user failed";
163 bool DeleteTestUser(const char *user_name) {
164 std::cout << "Deleting test user: " << user_name << std::endl;
166 if (boost::optional<uid_t> uid = ci::GetUidByUserName(user_name))
168 bool ret = DeleteUser(user_name, true);
169 if (!ci::GetUidByUserName(user_name)) {
170 std::cout << "User deleted properly: user_name=" << user_name
171 << " uid=" << test_uid << std::endl;
174 LOG(ERROR) << "Deleting test user failed";
178 void RemoveAllRecoveryFiles() {
179 bf::path root_path = ci::GetRootAppPath(false,
181 if (!bf::exists(root_path))
183 for (auto& dir_entry : boost::make_iterator_range(
184 bf::directory_iterator(root_path), bf::directory_iterator())) {
185 if (bf::is_regular_file(dir_entry)) {
186 if (dir_entry.path().string().find("/wgt-recovery")
187 != std::string::npos) {
188 bs::error_code error;
189 bf::remove(dir_entry.path(), error);
195 bf::path FindRecoveryFile() {
196 bf::path root_path = ci::GetRootAppPath(false,
198 for (auto& dir_entry : boost::make_iterator_range(
199 bf::directory_iterator(root_path), bf::directory_iterator())) {
200 if (bf::is_regular_file(dir_entry)) {
201 if (dir_entry.path().string().find("/wgt-recovery")
202 != std::string::npos) {
203 return dir_entry.path();
210 bf::path GetPackageRoot(const std::string& pkgid, uid_t uid) {
211 bf::path root_path = ci::GetRootAppPath(false, uid);
212 return root_path / pkgid;
215 bool ValidateFileContentInPackage(const std::string& pkgid,
216 const std::string& relative,
217 const std::string& expected,
219 bf::path file_path = ci::GetRootAppPath(is_readonly, kTestUserId);
220 file_path = file_path / pkgid / relative;
221 if (!bf::exists(file_path)) {
222 LOG(ERROR) << file_path << " doesn't exist";
225 FILE* handle = fopen(file_path.c_str(), "r");
227 LOG(ERROR) << file_path << " cannot be open";
231 std::array<char, 200> buffer;
232 while (fgets(buffer.data(), buffer.size(), handle)) {
233 content += buffer.data();
236 return content == expected;
239 void AddDataFiles(const std::string& pkgid, uid_t uid) {
240 if (uid == kGlobalUserUid) {
241 ci::UserList list = ci::GetUserList();
242 for (auto l : list) {
243 auto pkg_path = GetPackageRoot(pkgid, std::get<0>(l));
244 ASSERT_TRUE(TouchFile(pkg_path / "data" / "file1.txt"));
245 ASSERT_TRUE(TouchFile(pkg_path / "data" / "file2.txt"));
248 auto pkg_path = GetPackageRoot(pkgid, uid);
249 ASSERT_TRUE(TouchFile(pkg_path / "data" / "file1.txt"));
250 ASSERT_TRUE(TouchFile(pkg_path / "data" / "file2.txt"));
254 bool ValidateDataFiles(const std::string& pkgid, uid_t uid) {
255 if (uid == kGlobalUserUid) {
256 ci::UserList list = ci::GetUserList();
257 for (auto l : list) {
258 auto pkg_path = GetPackageRoot(pkgid, std::get<0>(l));
259 EXTENDED_ASSERT_TRUE(bf::exists(pkg_path / "data" / "file1.txt"));
260 EXTENDED_ASSERT_TRUE(bf::exists(pkg_path / "data" / "file2.txt"));
263 auto pkg_path = GetPackageRoot(pkgid, uid);
264 EXTENDED_ASSERT_TRUE(bf::exists(pkg_path / "data" / "file1.txt"));
265 EXTENDED_ASSERT_TRUE(bf::exists(pkg_path / "data" / "file2.txt"));
270 bool ValidatePackageRWFS(const std::string& pkgid, uid_t uid) {
271 bf::path root_path = ci::GetRootAppPath(false, uid);
272 bf::path package_path = root_path / pkgid;
273 bf::path data_path = package_path / rwDirectories[DATA];
274 bf::path cache_path = package_path / rwDirectories[CACHE];
275 bf::path shared_data_path = package_path / rwDirectories[SHARED_DATA];
277 EXTENDED_ASSERT_TRUE(bf::exists(data_path));
278 EXTENDED_ASSERT_TRUE(bf::exists(cache_path));
281 stat(data_path.c_str(), &stats);
282 // gid of RW dirs should be system_share
283 boost::optional<gid_t> system_share =
284 ci::GetGidByGroupName(kSystemShareGroupName);
285 EXTENDED_ASSERT_EQ(uid, stats.st_uid);
286 EXTENDED_ASSERT_EQ(*system_share, stats.st_gid);
287 if (bf::exists(shared_data_path)) {
288 stat(shared_data_path.c_str(), &stats);
289 EXTENDED_ASSERT_EQ(uid, stats.st_uid);
290 EXTENDED_ASSERT_EQ(*system_share, stats.st_gid);
293 stat(cache_path.c_str(), &stats);
294 EXTENDED_ASSERT_EQ(uid, stats.st_uid);
295 EXTENDED_ASSERT_EQ(*system_share, stats.st_gid);
299 bool ValidatePackageFS(const std::string& pkgid,
300 const std::vector<std::string>& appids,
301 uid_t uid, gid_t gid, bool is_readonly) {
302 bf::path root_path = ci::GetRootAppPath(is_readonly, uid);
303 bf::path package_path = root_path / pkgid;
304 bf::path shared_path = package_path / "shared";
305 EXTENDED_ASSERT_TRUE(bf::exists(root_path));
306 EXTENDED_ASSERT_TRUE(bf::exists(package_path));
307 EXTENDED_ASSERT_TRUE(bf::exists(shared_path));
309 bf::path manifest_path =
310 bf::path(getUserManifestPath(uid, is_readonly)) / (pkgid + ".xml");
311 EXTENDED_ASSERT_TRUE(bf::exists(manifest_path));
313 for (auto& appid : appids) {
314 bf::path binary_path = package_path / "bin" / appid;
315 EXTENDED_ASSERT_TRUE(bf::exists(binary_path));
318 bf::path widget_root_path = package_path / "res" / "wgt";
319 bf::path config_path = widget_root_path / "config.xml";
320 EXTENDED_ASSERT_TRUE(bf::exists(widget_root_path));
321 EXTENDED_ASSERT_TRUE(bf::exists(config_path));
323 bf::path private_tmp_path = package_path / "tmp";
324 EXTENDED_ASSERT_TRUE(bf::exists(private_tmp_path));
326 // backups should not exist
327 bf::path package_backup = ci::GetBackupPathForPackagePath(package_path);
328 bf::path manifest_backup = ci::GetBackupPathForManifestFile(manifest_path);
329 EXTENDED_ASSERT_FALSE(bf::exists(package_backup));
330 EXTENDED_ASSERT_FALSE(bf::exists(manifest_backup));
332 for (bf::recursive_directory_iterator iter(package_path);
333 iter != bf::recursive_directory_iterator(); ++iter) {
334 if (bf::is_symlink(symlink_status(iter->path())))
336 bool is_rw_dir = false;
337 for (const auto rw_dir : rwDirectories) {
338 bf::path rw_dir_path = rw_dir;
339 is_rw_dir |= ci::MakeRelativePath(iter->path(), package_path)
342 if (is_rw_dir || iter->path().filename() == ".mmc") {
347 stat(iter->path().c_str(), &stats);
348 EXTENDED_ASSERT_EQ(uid, stats.st_uid);
349 EXTENDED_ASSERT_EQ(gid, stats.st_gid);
354 void PackageCheckCleanup(const std::string& pkgid,
355 const std::vector<std::string>&, bool is_readonly) {
356 bf::path root_path = ci::GetRootAppPath(is_readonly, kTestUserId);
357 bf::path package_path = root_path / pkgid;
358 ASSERT_FALSE(bf::exists(package_path));
360 bf::path manifest_path = bf::path(getUserManifestPath(kTestUserId,
361 is_readonly)) / (pkgid + ".xml");
362 ASSERT_FALSE(bf::exists(manifest_path));
364 // backups should not exist
365 bf::path package_backup = ci::GetBackupPathForPackagePath(package_path);
366 bf::path manifest_backup = ci::GetBackupPathForManifestFile(manifest_path);
367 ASSERT_FALSE(bf::exists(package_backup));
368 ASSERT_FALSE(bf::exists(manifest_backup));
371 bool ValidatePackage(const std::string& pkgid,
372 const std::vector<std::string>& appids, bool is_readonly) {
373 EXTENDED_ASSERT_TRUE(ci::QueryIsPackageInstalled(
374 pkgid, ci::GetRequestMode(kTestUserId), kTestUserId));
375 EXTENDED_ASSERT_TRUE(ValidatePackageFS(
376 pkgid, appids, kTestUserId, kTestGroupId, is_readonly));
377 if (kTestUserId == kGlobalUserUid) {
378 ci::UserList list = ci::GetUserList();
380 EXTENDED_ASSERT_TRUE(ValidatePackageRWFS(pkgid, std::get<0>(l)));
382 EXTENDED_ASSERT_TRUE(ValidatePackageRWFS(pkgid, kTestUserId));
387 void ValidateExternalPackageFS(const std::string& pkgid,
388 const std::vector<std::string>& appids,
389 uid_t uid, gid_t gid) {
390 ASSERT_EQ(app2ext_usr_enable_external_pkg(pkgid.c_str(), uid), 0);
391 bf::path root_path = ci::GetRootAppPath(false, uid);
392 ASSERT_TRUE(bf::exists(root_path / pkgid / ".mmc" / "res"));
393 ValidatePackageFS(pkgid, appids, uid, gid, false);
394 ASSERT_EQ(app2ext_usr_disable_external_pkg(pkgid.c_str(), uid), 0);
397 void ValidateExternalPackage(const std::string& pkgid,
398 const std::vector<std::string>& appids) {
399 ASSERT_TRUE(ci::QueryIsPackageInstalled(
400 pkgid, ci::GetRequestMode(kTestUserId),
402 std::string storage = ci::QueryStorageForPkgId(pkgid, kTestUserId);
403 bf::path ext_mount_path = ci::GetExternalCardPath();
404 if (bf::is_empty(ext_mount_path)) {
405 LOG(INFO) << "Sdcard not exists!";
406 ASSERT_EQ(storage, "installed_internal");
408 ASSERT_EQ(storage, "installed_external");
410 ValidateExternalPackageFS(pkgid, appids, kTestUserId, kTestGroupId);
411 if (kTestUserId == kGlobalUserUid) {
412 ci::UserList list = ci::GetUserList();
414 ValidatePackageRWFS(pkgid, std::get<0>(l));
416 ValidatePackageRWFS(pkgid, kTestUserId);
420 bool CheckPackageNonExistance(const std::string& pkgid,
421 const std::vector<std::string>& appids) {
422 EXTENDED_ASSERT_FALSE(ci::QueryIsPackageInstalled(
423 pkgid, ci::GetRequestMode(kTestUserId),
425 PackageCheckCleanup(pkgid, appids);
426 if (kTestUserId == kGlobalUserUid) {
427 ci::UserList list = ci::GetUserList();
428 bf::path skel_path(kSkelDir);
429 EXTENDED_ASSERT_FALSE(bf::exists(skel_path / pkgid));
430 for (auto& l : list) {
431 bf::path root_path = ci::GetRootAppPath(false, std::get<0>(l));
432 bf::path package_path = root_path / pkgid;
433 EXTENDED_ASSERT_FALSE(bf::exists(package_path));
439 void CheckPackageReadonlyNonExistance(const std::string& pkgid,
440 const std::vector<std::string>& appids) {
441 ASSERT_FALSE(ci::QueryIsPackageInstalled(
442 pkgid, ci::GetRequestMode(kTestUserId), kTestUserId));
443 PackageCheckCleanup(pkgid, appids, true);
446 std::unique_ptr<ci::AppQueryInterface> CreateQueryInterface() {
447 std::unique_ptr<ci::AppQueryInterface> query_interface(
448 new wgt::WgtAppQueryInterface());
449 return query_interface;
452 std::unique_ptr<ci::AppInstaller> CreateInstaller(ci::PkgMgrPtr pkgmgr,
455 case PackageType::WGT:
456 return std::unique_ptr<ci::AppInstaller>(new wgt::WgtInstaller(pkgmgr));
457 case PackageType::HYBRID:
458 return std::unique_ptr<ci::AppInstaller>(
459 new hybrid::HybridInstaller(pkgmgr));
461 LOG(ERROR) << "Unknown installer type";
466 void TestRollbackAfterEachStep(int argc, const char*argv[],
467 std::function<bool()> validator,
469 TestPkgmgrInstaller pkgmgr_installer;
470 std::unique_ptr<ci::AppQueryInterface> query_interface =
471 CreateQueryInterface();
473 ci::PkgMgrInterface::Create(argc, const_cast<char**>(argv),
475 query_interface.get());
477 LOG(ERROR) << "Failed to initialize pkgmgr interface";
480 std::unique_ptr<ci::AppInstaller> backend = CreateInstaller(pkgmgr, type);
482 for (i = backend->StepCount()-1; i >= 0; i--) {
483 backend->AddStepAtIndex<ci::configuration::StepFail>(i);
484 LOG(DEBUG) << "StepFail is inserted at: " << i;
485 ASSERT_EQ(ci::AppInstaller::Result::ERROR,
493 void CrashAfterEachStep(std::vector<std::string> args,
494 std::function<bool(int iter)> validator,
496 std::unique_ptr<const char*[]> argv(new const char*[args.size()]);
497 for (size_t i = 0; i < args.size(); ++i) {
498 argv[i] = args[i].c_str();
500 TestPkgmgrInstaller pkgmgr_installer;
501 std::unique_ptr<ci::AppQueryInterface> query_interface =
502 CreateQueryInterface();
504 ci::PkgMgrInterface::Create(args.size(), const_cast<char**>(argv.get()),
506 query_interface.get());
508 LOG(ERROR) << "Failed to initialize pkgmgr interface";
511 std::unique_ptr<ci::AppInstaller> backend = CreateInstaller(pkgmgr, type);
512 int stepCount = backend->StepCount();
514 args.push_back("-idx");
515 args.push_back(std::to_string(stepCount));
517 for (i = 0; i < stepCount; i++) {
518 ci::Subprocess backend_crash("/usr/bin/wgt-backend-ut/smoke-test-helper");
519 args.back() = std::to_string(i);
520 backend_crash.Run(args);
521 ASSERT_NE(backend_crash.Wait(), 0);
525 ASSERT_EQ(stepCount, i);
528 ci::AppInstaller::Result RunInstallerWithPkgrmgr(ci::PkgMgrPtr pkgmgr,
530 RequestResult mode) {
531 std::unique_ptr<ci::AppInstaller> installer = CreateInstaller(pkgmgr, type);
533 case RequestResult::FAIL:
534 installer->AddStep<ci::configuration::StepFail>();
539 return installer->Run();
541 ci::AppInstaller::Result CallBackend(int argc,
544 RequestResult mode) {
545 TestPkgmgrInstaller pkgmgr_installer;
546 std::unique_ptr<ci::AppQueryInterface> query_interface =
547 CreateQueryInterface();
549 ci::PkgMgrInterface::Create(argc, const_cast<char**>(argv),
550 &pkgmgr_installer, query_interface.get());
552 LOG(ERROR) << "Failed to initialize pkgmgr interface";
553 return ci::AppInstaller::Result::UNKNOWN;
555 return RunInstallerWithPkgrmgr(pkgmgr, type, mode);
558 ci::AppInstaller::Result Install(const bf::path& path,
560 RequestResult mode) {
561 const char* argv[] = {"", "-i", path.c_str(), "-u", kTestUserIdStr.c_str()};
562 return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
565 ci::AppInstaller::Result InstallPreload(const bf::path& path, PackageType type,
566 RequestResult mode) {
567 const char* argv[] = {"", "-i", path.c_str(), "--preload"};
568 return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
571 bool CheckAvailableExternalPath() {
572 bf::path ext_mount_path = ci::GetExternalCardPath();
573 LOG(DEBUG) << "ext_mount_path :" << ext_mount_path;
574 if (ext_mount_path.empty()) {
575 LOG(ERROR) << "Sdcard not exists!";
581 ci::AppInstaller::Result InstallExternal(const bf::path& path,
583 RequestResult mode) {
584 int default_storage = 0;
585 vconf_get_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT,
587 vconf_set_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT, 1);
589 const char* argv[] = {"", "-i", path.c_str(), "-u", kTestUserIdStr.c_str()};
590 ci::AppInstaller::Result result =
591 CallBackend(SIZEOFARRAY(argv), argv, type, mode);
593 vconf_set_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT,
598 ci::AppInstaller::Result MigrateLegacyExternalImage(const std::string& pkgid,
599 const bf::path& path,
600 const bf::path& legacy_path,
602 RequestResult mode) {
603 if (InstallExternal(path, type) != ci::AppInstaller::Result::OK) {
604 LOG(ERROR) << "Failed to install application. Cannot perform Migrate";
605 return ci::AppInstaller::Result::ERROR;
608 bf::path ext_mount_path = ci::GetExternalCardPath();
609 if (bf::is_empty(ext_mount_path)) {
610 LOG(ERROR) << "Sdcard not exists!";
611 return ci::AppInstaller::Result::ERROR;
613 bf::path app2sd_path = ext_mount_path / "app2sd";
615 char* image_name = app2ext_usr_getname_image(pkgid.c_str(),
618 LOG(ERROR) << "Failed to get external image name";
619 return ci::AppInstaller::Result::ERROR;
621 bf::path org_image = app2sd_path / image_name;
624 bs::error_code error;
625 bf::remove(org_image, error);
627 LOG(ERROR) << "Failed to remove org image";
628 return ci::AppInstaller::Result::ERROR;
631 bf::path db_path = tzplatform_getenv(TZ_SYS_DB);
632 bf::path app2sd_db = db_path / ".app2sd.db";
633 bf::path app2sd_db_journal = db_path / ".app2sd.db-journal";
634 bf::remove(app2sd_db, error);
636 LOG(ERROR) << "Failed to remove app2sd db";
637 return ci::AppInstaller::Result::ERROR;
639 bf::remove(app2sd_db_journal, error);
641 LOG(ERROR) << "Failed to remove app2sd journal db";
642 return ci::AppInstaller::Result::ERROR;
645 bf::path app2sd_migrate_db = legacy_path / kMigrateTestDBName;
646 if (!ci::CopyFile(app2sd_migrate_db, app2sd_db)) {
647 LOG(ERROR) << "Failed to copy test db";
648 return ci::AppInstaller::Result::ERROR;
651 bf::path legacy_src = legacy_path / pkgid;
652 bf::path legacy_dst = app2sd_path / pkgid;
653 if (!ci::CopyFile(legacy_src, legacy_dst)) {
654 LOG(ERROR) << "Failed to copy test image";
655 return ci::AppInstaller::Result::ERROR;
657 const char* argv[] = {"", "--migrate-extimg", pkgid.c_str(),
658 "-u", kDefaultUserIdStr.c_str()};
659 return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
662 ci::AppInstaller::Result MountInstall(const bf::path& path,
663 PackageType type, RequestResult mode) {
664 const char* argv[] = {"", "-w", path.c_str(), "-u", kTestUserIdStr.c_str()};
665 return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
668 ci::AppInstaller::Result Uninstall(const std::string& pkgid,
671 RequestResult mode) {
673 const char* argv[] = {"", "-d", pkgid.c_str(), "--preload",
675 return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
677 const char* argv[] = {"", "-d", pkgid.c_str(), "-u",
678 kTestUserIdStr.c_str()};
679 return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
683 ci::AppInstaller::Result RDSUpdate(const bf::path& path,
684 const std::string& pkgid,
686 RequestResult mode) {
687 if (Install(path, type) != ci::AppInstaller::Result::OK) {
688 LOG(ERROR) << "Failed to install application. Cannot perform RDS";
689 return ci::AppInstaller::Result::UNKNOWN;
691 const char* argv[] = {"", "-r", pkgid.c_str(), "-u",
692 kTestUserIdStr.c_str()};
693 return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
696 ci::AppInstaller::Result DeltaInstall(const bf::path& path,
697 const bf::path& delta_package, PackageType type) {
698 if (Install(path, type) != ci::AppInstaller::Result::OK) {
699 LOG(ERROR) << "Failed to install application. Cannot perform delta update";
700 return ci::AppInstaller::Result::UNKNOWN;
702 return Install(delta_package, type);
705 ci::AppInstaller::Result EnablePackage(const std::string& pkgid,
707 RequestResult mode) {
708 const char* argv[] = {"", "-A", pkgid.c_str(), "-u", kTestUserIdStr.c_str()};
709 return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
712 ci::AppInstaller::Result DisablePackage(const std::string& pkgid,
714 RequestResult mode) {
715 const char* argv[] = {"", "-D", pkgid.c_str(), "-u", kTestUserIdStr.c_str()};
716 return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
719 ci::AppInstaller::Result Recover(const bf::path& recovery_file,
721 RequestResult mode) {
722 const char* argv[] = {"", "-b", recovery_file.c_str(), "-u",
723 kTestUserIdStr.c_str()};
724 return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
727 void BackupPath(const bf::path& path) {
728 bf::path backup_path = path.string() + ".bck";
729 std::cout << "Backup path: " << path << " to " << backup_path << std::endl;
730 bs::error_code error;
731 bf::remove_all(backup_path, error);
733 LOG(ERROR) << "Remove failed: " << backup_path
734 << " (" << error.message() << ")";
735 if (bf::exists(path)) {
736 bf::rename(path, backup_path, error);
738 LOG(ERROR) << "Failed to setup test environment. Does some previous"
739 << " test crashed? Path: "
740 << backup_path << " should not exist.";
745 void RestorePath(const bf::path& path) {
746 bf::path backup_path = path.string() + ".bck";
747 std::cout << "Restore path: " << path << " from " << backup_path << std::endl;
748 bs::error_code error;
749 bf::remove_all(path, error);
751 LOG(ERROR) << "Remove failed: " << path
752 << " (" << error.message() << ")";
753 if (bf::exists(backup_path)) {
754 bf::rename(backup_path, path, error);
756 LOG(ERROR) << "Failed to restore backup path: " << backup_path
757 << " (" << error.message() << ")";
761 std::vector<bf::path> SetupBackupDirectories() {
762 std::vector<bf::path> entries;
763 bf::path db_dir = bf::path(tzplatform_getenv(TZ_SYS_DB));
764 if (kTestUserId != kGlobalUserUid)
765 db_dir = db_dir / "user" / std::to_string(kTestUserId);
766 for (auto e : kDBEntries) {
767 bf::path path = db_dir / e;
768 entries.emplace_back(path);
772 entries.emplace_back(kPreloadApps);
773 entries.emplace_back(kPreloadManifestDir);
774 entries.emplace_back(kPreloadIcons);
777 if (kTestUserId == kGlobalUserUid) {
778 entries.emplace_back(kSkelDir);
779 entries.emplace_back(kGlobalManifestDir);
780 ci::UserList list = ci::GetUserList();
781 for (auto l : list) {
782 bf::path apps = std::get<2>(l) / "apps_rw";
783 entries.emplace_back(apps);
786 tzplatform_set_user(kTestUserId);
787 bf::path approot = tzplatform_getenv(TZ_USER_APPROOT);
788 tzplatform_reset_user();
789 entries.emplace_back(approot);
792 bf::path apps_rw = ci::GetRootAppPath(false, kTestUserId);
793 entries.emplace_back(apps_rw);
798 void UninstallAllAppsInDirectory(bf::path dir, bool is_preload) {
799 if (bf::exists(dir)) {
800 for (auto& dir_entry : boost::make_iterator_range(
801 bf::directory_iterator(dir), bf::directory_iterator())) {
802 if (dir_entry.path().string().find("smoke") != std::string::npos &&
803 bf::is_directory(dir_entry)) {
804 std::string package = dir_entry.path().filename().string();
805 std::regex pkg_regex("smoke[a-zA-Z]{3,}[1-9]{2,}");
806 if (std::regex_match(package, pkg_regex)) {
807 if (Uninstall(dir_entry.path().filename().string(), PackageType::WGT,
808 is_preload, RequestResult::NORMAL) !=
809 ci::AppInstaller::Result::OK) {
810 LOG(ERROR) << "Cannot uninstall smoke test app: "
811 << dir_entry.path().filename().string();
819 void UninstallAllSmokeApps(ci::RequestMode request_mode) {
820 if (getuid() == 0 && request_mode == ci::RequestMode::GLOBAL) {
821 bf::path root_path = kPreloadApps;
822 UninstallAllAppsInDirectory(root_path, true);
824 bf::path apps_rw = ci::GetRootAppPath(false, kTestUserId);
825 UninstallAllAppsInDirectory(apps_rw, false);