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 "smoke_tests/common/smoke_utils.h"
7 #include <gum/gum-user.h>
8 #include <gum/gum-user-service.h>
9 #include <gum/common/gum-user-types.h>
10 #include <manifest_parser/utils/version_number.h>
11 #include <sys/smack.h>
13 #include <vconf-internal-keys.h>
15 #include <boost/filesystem/path.hpp>
16 #include <gtest/gtest.h>
18 #include <common/installer/app_installer.h>
19 #include <common/utils/paths.h>
20 #include <common/pkgmgr_interface.h>
21 #include <common/utils/pkgmgr_query.h>
22 #include <common/tzip_interface.h>
24 #include "pkgmgr_parser_db.h"
31 namespace bf = boost::filesystem;
32 namespace bs = boost::system;
33 namespace ci = common_installer;
34 namespace bo = boost::program_options;
38 const uid_t kDefaultUserUid = tzplatform_getuid(TZ_SYS_DEFAULT_USER);
39 const gid_t kDefaultUserGid = tzplatform_getgid(TZ_SYS_DEFAULT_USER);
40 const char kNormalUserName[] = "smokeuser";
41 const char kSystemShareGroupName[] = "system_share";
42 const char kMigrateTestDBName[] = "app2sd_migrate.db";
44 const std::vector<std::string> kDBEntries = {
45 {".pkgmgr_parser.db"},
46 {".pkgmgr_parser.db-journal"},
48 {".pkgmgr_cert.db-journal"},
50 {".app2sd.db-journal"},
53 const char kGlobalManifestDir[] = "/opt/share/packages";
54 const char kSkelDir[] = "/etc/skel/apps_rw";
55 const char kPreloadApps[] = "/usr/apps";
56 const char kPreloadManifestDir[] = "/usr/share/packages";
57 const char kPreloadIcons[] = "/usr/share/icons";
58 const char kData[] = "data";
59 const char kShared[] = ".shared";
60 const char kSharedTmp[] = ".shared_tmp";
70 const char* rwDirectories[] = {
80 namespace smoke_test {
82 const char kLegacyExtImageDir[] = "legacy_extimage_dir";
83 const std::string& kDefaultUserIdStr = std::to_string(kDefaultUserUid);
84 const uid_t kGlobalUserUid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
85 const uid_t kGlobalUserGid = tzplatform_getgid(TZ_SYS_GLOBALAPP_USER);
86 extern const bf::path kSdkDirectory = "/home/owner/share/tmp/sdk_tools";
88 ci::RequestMode ParseRequestMode(int argc, char** argv) {
89 bo::options_description desc("Available options");
91 ("request-mode", bo::value<std::string>(), "set request mode")
92 ("global-request,g", "set request mode to global")
93 ("user-request,u", "set request mode to user");
96 bo::store(bo::command_line_parser(argc, argv).
97 options(desc).allow_unregistered().run(), vm);
100 if (vm.count("global-request")) {
101 std::cout << "Request mode was set to global." << std::endl;
102 return ci::RequestMode::GLOBAL;
104 if (vm.count("user-request")) {
105 std::cout << "Request mode was set to user." << std::endl;
106 return ci::RequestMode::USER;
108 if (vm.count("request-mode")) {
109 if (vm["request-mode"].as<std::string>() == "global") {
110 std::cout << "Request mode was set to global." << std::endl;
111 return ci::RequestMode::GLOBAL;
113 if (vm["request-mode"].as<std::string>() == "user") {
114 std::cout << "Request mode was set to user." << std::endl;
115 return ci::RequestMode::USER;
117 std::cout << "Cannot set request mode to "
118 << vm["request-mode"].as<std::string>() << std::endl;
120 std::cout << "Request mode was set to global." << std::endl;
121 return ci::RequestMode::GLOBAL;
124 static bool AddUser(const char* user_name) {
125 GumUser* user = nullptr;
126 user = gum_user_create_sync(FALSE);
128 LOG(WARNING) << "Failed to create gum user! (user name: "
130 g_object_set(G_OBJECT(user), "username", user_name, "usertype",
131 GUM_USERTYPE_NORMAL, NULL);
132 gboolean rval = FALSE;
133 rval = gum_user_add_sync(user);
134 g_object_unref(user);
138 static bool DeleteUser(const char* user_name, bool rem_home_dir) {
140 GumUser* guser = gum_user_get_by_name_sync(user_name, FALSE);
142 rval = gum_user_delete_sync(guser, rem_home_dir);
146 bool AddTestUser(User* test_user) {
147 std::cout << "Adding test user: " << kNormalUserName << std::endl;
148 AddUser(kNormalUserName);
149 if (boost::optional<uid_t> uid = ci::GetUidByUserName(kNormalUserName)) {
150 test_user->uid = *uid;
151 std::cout << "User created properly: uid=" << *uid;
152 if (boost::optional<gid_t> gid = ci::GetGidByUid(*uid)) {
153 test_user->gid = *gid;
154 std::cout << " gid=" << *gid;
156 std::cout << std::endl;
159 LOG(ERROR) << "Adding test user failed";
163 bool DeleteTestUser() {
164 std::cout << "Deleting test user: " << kNormalUserName << std::endl;
166 if (boost::optional<uid_t> uid = ci::GetUidByUserName(kNormalUserName))
170 DeleteUser(kNormalUserName, true);
171 if (!ci::GetUidByUserName(kNormalUserName)) {
172 std::cout << "User deleted properly: user_name=" << kNormalUserName
173 << " uid=" << test_uid << std::endl;
176 LOG(ERROR) << "Deleting test user failed";
180 bool TouchFile(const bf::path& path) {
181 FILE* f = fopen(path.c_str(), "w+");
188 void AddDataFiles(const std::string& pkgid, uid_t uid) {
189 if (uid == kGlobalUserUid) {
190 ci::UserList list = ci::GetUserList();
191 for (auto l : list) {
192 auto pkg_path = GetPackageRoot(pkgid, std::get<0>(l));
193 ASSERT_TRUE(TouchFile(pkg_path / "data" / "file1.txt"));
194 ASSERT_TRUE(TouchFile(pkg_path / "data" / "file2.txt"));
197 auto pkg_path = GetPackageRoot(pkgid, uid);
198 ASSERT_TRUE(TouchFile(pkg_path / "data" / "file1.txt"));
199 ASSERT_TRUE(TouchFile(pkg_path / "data" / "file2.txt"));
203 void RemoveAllRecoveryFiles(const std::string& prefix, uid_t uid) {
204 bf::path root_path = ci::GetRootAppPath(false, uid);
205 if (!bf::exists(root_path))
207 for (auto& dir_entry : boost::make_iterator_range(
208 bf::directory_iterator(root_path), bf::directory_iterator())) {
209 if (bf::is_regular_file(dir_entry)) {
210 if (dir_entry.path().string().find(prefix) != std::string::npos) {
211 bs::error_code error;
212 bf::remove(dir_entry.path(), error);
214 LOG(ERROR) << "Failed to remove " << dir_entry.path()
215 << ": " << error.message();
221 bf::path FindRecoveryFile(const std::string& prefix, uid_t uid) {
222 bf::path root_path = ci::GetRootAppPath(false, uid);
223 if (!bf::exists(root_path))
226 for (auto& dir_entry : boost::make_iterator_range(
227 bf::directory_iterator(root_path), bf::directory_iterator())) {
228 if (bf::is_regular_file(dir_entry)) {
229 if (dir_entry.path().string().find(prefix) != std::string::npos) {
230 return dir_entry.path();
237 std::unique_ptr<ci::recovery::RecoveryFile> GetRecoverFileInfo(
238 const bf::path& recovery_file_path) {
239 return ci::recovery::RecoveryFile::OpenRecoveryFile(recovery_file_path);
242 bf::path GetPackageRoot(const std::string& pkgid, uid_t uid) {
243 bf::path root_path = ci::GetRootAppPath(false, uid);
244 return root_path / pkgid;
247 bool ValidateFileContentInPackage(const std::string& pkgid,
248 const std::string& relative,
249 const std::string& expected,
250 const TestParameters& params) {
251 bf::path file_path = ci::GetRootAppPath(params.is_readonly,
252 params.test_user.uid);
253 file_path = file_path / pkgid / relative;
254 if (!bf::exists(file_path)) {
255 LOG(ERROR) << file_path << " doesn't exist";
258 FILE* handle = fopen(file_path.c_str(), "r");
260 LOG(ERROR) << file_path << " cannot be open";
264 std::array<char, 200> buffer;
265 while (fgets(buffer.data(), buffer.size(), handle)) {
266 content += buffer.data();
269 return content == expected;
272 static bool ValidatePackageRWFS(const std::string& pkgid, uid_t uid) {
273 bf::path root_path = ci::GetRootAppPath(false, uid);
274 bf::path package_path = root_path / pkgid;
275 bf::path data_path = package_path / rwDirectories[DATA];
276 bf::path cache_path = package_path / rwDirectories[CACHE];
277 bf::path shared_data_path = package_path / rwDirectories[SHARED_DATA];
279 EXTENDED_ASSERT_TRUE(bf::exists(data_path));
280 EXTENDED_ASSERT_TRUE(bf::exists(cache_path));
283 stat(data_path.c_str(), &stats);
284 // gid of RW dirs should be system_share
285 boost::optional<gid_t> system_share =
286 ci::GetGidByGroupName(kSystemShareGroupName);
287 EXTENDED_ASSERT_EQ(uid, stats.st_uid);
288 EXTENDED_ASSERT_EQ(*system_share, stats.st_gid);
289 if (bf::exists(shared_data_path)) {
290 stat(shared_data_path.c_str(), &stats);
291 EXTENDED_ASSERT_EQ(uid, stats.st_uid);
292 EXTENDED_ASSERT_EQ(*system_share, stats.st_gid);
295 stat(cache_path.c_str(), &stats);
296 EXTENDED_ASSERT_EQ(uid, stats.st_uid);
297 EXTENDED_ASSERT_EQ(*system_share, stats.st_gid);
301 static bool ValidatePackageFS(const std::string& pkgid, const Apps& apps,
302 const TestParameters& params) {
303 bf::path root_path = ci::GetRootAppPath(params.is_readonly,
304 params.test_user.uid);
305 bf::path package_path = root_path / pkgid;
306 bf::path shared_path = package_path / "shared";
307 EXTENDED_ASSERT_TRUE(bf::exists(root_path));
308 EXTENDED_ASSERT_TRUE(bf::exists(package_path));
309 EXTENDED_ASSERT_TRUE(bf::exists(shared_path));
311 bf::path manifest_path =
312 bf::path(getUserManifestPath(params.test_user.uid,
313 params.is_readonly)) / (pkgid + ".xml");
314 EXTENDED_ASSERT_TRUE(bf::exists(manifest_path));
316 for (auto& app : apps) {
317 const std::string &exec = app.second;
318 bf::path binary_path = package_path / "bin" / exec;
319 EXTENDED_ASSERT_TRUE(bf::exists(binary_path));
322 if (params.pkg_type == PackageType::WGT ||
323 params.pkg_type == PackageType::HYBRID) {
324 bf::path widget_root_path = package_path / "res" / "wgt";
325 bf::path config_path = widget_root_path / "config.xml";
326 EXTENDED_ASSERT_TRUE(bf::exists(widget_root_path));
327 EXTENDED_ASSERT_TRUE(bf::exists(config_path));
329 bf::path private_tmp_path = package_path / "tmp";
330 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(params.test_user.uid, stats.st_uid);
356 EXTENDED_ASSERT_EQ(params.test_user.gid, stats.st_gid);
361 bool ValidatePackage(const std::string& pkgid, const Apps& apps,
362 const TestParameters& params) {
363 ci::PkgQueryInterface pkg_query(pkgid, params.test_user.uid, true);
364 EXTENDED_ASSERT_TRUE(pkg_query.IsPackageInstalled(
365 ci::GetRequestMode(params.test_user.uid)));
366 EXTENDED_ASSERT_TRUE(ValidatePackageFS(pkgid, apps, params));
367 if (params.test_user.uid == kGlobalUserUid) {
368 ci::UserList list = ci::GetUserList();
370 EXTENDED_ASSERT_TRUE(ValidatePackageRWFS(pkgid, std::get<0>(l)));
372 EXTENDED_ASSERT_TRUE(ValidatePackageRWFS(pkgid, params.test_user.uid));
377 bool ValidateDataFiles(const std::string& pkgid, uid_t uid) {
378 if (uid == kGlobalUserUid) {
379 ci::UserList list = ci::GetUserList();
380 for (auto l : list) {
381 auto pkg_path = GetPackageRoot(pkgid, std::get<0>(l));
382 EXTENDED_ASSERT_TRUE(bf::exists(pkg_path / "data" / "file1.txt"));
383 EXTENDED_ASSERT_TRUE(bf::exists(pkg_path / "data" / "file2.txt"));
386 auto pkg_path = GetPackageRoot(pkgid, uid);
387 EXTENDED_ASSERT_TRUE(bf::exists(pkg_path / "data" / "file1.txt"));
388 EXTENDED_ASSERT_TRUE(bf::exists(pkg_path / "data" / "file2.txt"));
393 static bool ValidateExternalPackageFS(const std::string& pkgid,
394 const Apps& apps, const TestParameters& params) {
395 EXTENDED_ASSERT_EQ(app2ext_usr_enable_external_pkg(pkgid.c_str(),
396 params.test_user.uid), 0);
397 bf::path root_path = ci::GetRootAppPath(false, params.test_user.uid);
398 if (params.pkg_type == PackageType::TPK) {
399 EXTENDED_ASSERT_TRUE(bf::exists(root_path / pkgid / ".mmc" / "bin"));
400 EXTENDED_ASSERT_TRUE(bf::exists(root_path / pkgid / ".mmc" / "lib"));
402 EXTENDED_ASSERT_TRUE(bf::exists(root_path / pkgid / ".mmc" / "res"));
403 EXTENDED_ASSERT_TRUE(ValidatePackageFS(pkgid, apps, params));
404 EXTENDED_ASSERT_EQ(app2ext_usr_disable_external_pkg(pkgid.c_str(),
405 params.test_user.uid), 0);
409 bool ValidateExternalPackage(const std::string& pkgid, const Apps& apps,
410 const TestParameters& params) {
411 ci::PkgQueryInterface pkg_query(pkgid, params.test_user.uid, true);
412 std::string storage = pkg_query.StorageForPkgId();
413 bf::path ext_mount_path = ci::GetExternalCardPath();
414 if (bf::is_empty(ext_mount_path)) {
415 LOG(INFO) << "Sdcard not exists!";
416 EXTENDED_ASSERT_EQ(storage, "installed_internal");
418 EXTENDED_ASSERT_EQ(storage, "installed_external");
420 EXTENDED_ASSERT_TRUE(ValidateExternalPackageFS(pkgid, apps, params));
424 bool ValidateExtendedPackage(const std::string& pkgid, const Apps& apps,
425 const TestParameters& params) {
426 ci::PkgQueryInterface pkg_query(pkgid, params.test_user.uid, true);
427 std::string storage = pkg_query.StorageForPkgId();
428 bf::path extended_path =
429 bf::path(ci::GetExtendedRootAppPath(params.test_user.uid)) / pkgid;
430 if (!bf::exists(extended_path)) {
431 LOG(INFO) << "Extended storage not exists!";
432 EXTENDED_ASSERT_EQ(storage, "installed_internal");
434 EXTENDED_ASSERT_EQ(storage, "installed_extended");
436 EXTENDED_ASSERT_TRUE(ValidatePackage(pkgid, apps, params));
440 static bool PackageCheckCleanup(const std::string& pkgid,
441 const TestParameters& params) {
442 bf::path root_path = ci::GetRootAppPath(params.is_readonly,
443 params.test_user.uid);
444 bf::path package_path = root_path / pkgid;
445 EXTENDED_ASSERT_FALSE(bf::exists(package_path));
447 bf::path manifest_path = bf::path(getUserManifestPath(params.test_user.uid,
448 params.is_readonly)) / (pkgid + ".xml");
449 EXTENDED_ASSERT_FALSE(bf::exists(manifest_path));
451 // backups should not exist
452 bf::path package_backup = ci::GetBackupPathForPackagePath(package_path);
453 bf::path manifest_backup = ci::GetBackupPathForManifestFile(manifest_path);
454 EXTENDED_ASSERT_FALSE(bf::exists(package_backup));
455 EXTENDED_ASSERT_FALSE(bf::exists(manifest_backup));
459 bool CheckPackageNonExistance(const std::string& pkgid,
460 const TestParameters& params) {
461 ci::PkgQueryInterface pkg_query(pkgid, params.test_user.uid, true);
462 EXTENDED_ASSERT_FALSE(pkg_query.IsPackageInstalled(
463 ci::GetRequestMode(params.test_user.uid)));
464 EXTENDED_ASSERT_TRUE(PackageCheckCleanup(pkgid, params));
465 if (params.test_user.uid == kGlobalUserUid) {
466 bf::path skel_path(kSkelDir);
467 EXTENDED_ASSERT_FALSE(bf::exists(skel_path / pkgid));
468 EXTENDED_ASSERT_FALSE(bf::exists(skel_path / kShared / pkgid));
469 EXTENDED_ASSERT_FALSE(bf::exists(skel_path / kSharedTmp / pkgid));
470 ci::UserList list = ci::GetUserList();
471 for (auto& l : list) {
472 bf::path root_path = ci::GetRootAppPath(false, std::get<0>(l));
473 EXTENDED_ASSERT_FALSE(bf::exists(root_path / kShared / pkgid));
474 EXTENDED_ASSERT_FALSE(bf::exists(root_path / kSharedTmp / pkgid));
475 bf::path package_path = root_path / pkgid;
476 EXTENDED_ASSERT_FALSE(bf::exists(package_path));
482 bool CheckAvailableExternalPath() {
483 bf::path ext_mount_path = ci::GetExternalCardPath();
484 LOG(DEBUG) << "ext_mount_path :" << ext_mount_path;
485 if (ext_mount_path.empty()) {
486 LOG(ERROR) << "Sdcard not exists!";
492 bool CheckAvailableExtendedPath() {
493 bf::path extended_path = bf::path(tzplatform_getenv(TZ_SYS_EXTENDEDSD));
494 LOG(DEBUG) << "extended_path :" << extended_path;
495 // TODO(jeremy.jang): It should be checked by libstorage API.
496 if (!bf::exists(extended_path)) {
497 LOG(ERROR) << "Extended storage not exists!";
503 bool CheckPackageReadonlyNonExistance(const std::string& pkgid,
504 const TestParameters& params) {
505 ci::PkgQueryInterface pkg_query(pkgid, params.test_user.uid, true);
506 EXTENDED_ASSERT_FALSE(pkg_query.IsPackageInstalled(
507 ci::GetRequestMode(params.test_user.uid)));
508 EXTENDED_ASSERT_TRUE(PackageCheckCleanup(pkgid, params));
512 static bool CheckSharedDataExistanceForPath(const bf::path& apps_rw,
513 const std::string& pkgid) {
514 bf::path shared_data_path = apps_rw / pkgid / rwDirectories[SHARED_DATA];
515 bf::path shared = apps_rw / kShared / pkgid / kData;
516 bf::path shared_tmp = apps_rw / kSharedTmp / pkgid;
517 EXTENDED_ASSERT_TRUE(bf::exists(shared_data_path));
518 EXTENDED_ASSERT_TRUE(bf::exists(shared));
519 EXTENDED_ASSERT_TRUE(bf::exists(shared_tmp));
523 static bool CheckSharedDataPermissions(const bf::path& apps_rw,
524 const std::string& pkgid, uid_t uid) {
525 bf::path shared_data_path = apps_rw / pkgid / rwDirectories[SHARED_DATA];
526 bf::path shared = apps_rw / kShared / pkgid / kData;
527 bf::path shared_tmp = apps_rw / kSharedTmp / pkgid;
528 // gid of RW dirs should be system_share
529 boost::optional<gid_t> system_share =
530 ci::GetGidByGroupName(kSystemShareGroupName);
532 stat(shared_data_path.c_str(), &stats);
533 EXTENDED_ASSERT_EQ(uid, stats.st_uid);
534 EXTENDED_ASSERT_EQ(*system_share, stats.st_gid);
535 stat(shared.c_str(), &stats);
536 EXTENDED_ASSERT_EQ(uid, stats.st_uid);
537 EXTENDED_ASSERT_EQ(*system_share, stats.st_gid);
538 stat(shared_tmp.c_str(), &stats);
539 EXTENDED_ASSERT_EQ(uid, stats.st_uid);
540 EXTENDED_ASSERT_EQ(kDefaultUserGid, stats.st_gid);
544 bool CheckSharedDataExistance(const std::string& pkgid,
545 const TestParameters& params) {
546 if (params.test_user.uid == kGlobalUserUid) {
547 bf::path skel_path(kSkelDir);
548 EXTENDED_ASSERT_TRUE(CheckSharedDataExistanceForPath(kSkelDir, pkgid));
549 ci::UserList list = ci::GetUserList();
550 for (auto& l : list) {
551 uid_t uid = std::get<0>(l);
552 bf::path apps_rw = ci::GetRootAppPath(false, uid);
553 EXTENDED_ASSERT_TRUE(CheckSharedDataExistanceForPath(apps_rw, pkgid));
554 EXTENDED_ASSERT_TRUE(CheckSharedDataPermissions(apps_rw, pkgid, uid));
557 bf::path apps_rw = ci::GetRootAppPath(false, params.test_user.uid);
558 EXTENDED_ASSERT_TRUE(CheckSharedDataExistanceForPath(apps_rw, pkgid));
559 EXTENDED_ASSERT_TRUE(
560 CheckSharedDataPermissions(apps_rw, pkgid, params.test_user.uid));
565 static bool CheckSharedDataNonExistanceForPath(const bf::path& apps_rw,
566 const std::string pkgid) {
567 bf::path shared_data_path = apps_rw / pkgid / rwDirectories[SHARED_DATA];
568 bf::path shared = apps_rw / kShared / pkgid / kData;
569 bf::path shared_tmp = apps_rw / kSharedTmp / pkgid;
570 EXTENDED_ASSERT_FALSE(bf::exists(shared_data_path));
571 EXTENDED_ASSERT_FALSE(bf::exists(shared));
572 EXTENDED_ASSERT_FALSE(bf::exists(shared_tmp));
576 bool CheckSharedDataNonExistance(const std::string& pkgid,
577 const TestParameters& params) {
578 if (params.test_user.uid == kGlobalUserUid) {
579 bf::path skel_path(kSkelDir);
580 EXTENDED_ASSERT_TRUE(
581 CheckSharedDataNonExistanceForPath(skel_path, pkgid));
583 ci::UserList list = ci::GetUserList();
584 for (auto& l : list) {
585 uid_t uid = std::get<0>(l);
586 bf::path apps_rw = ci::GetRootAppPath(false, uid);
587 EXTENDED_ASSERT_TRUE(CheckSharedDataNonExistanceForPath(apps_rw, pkgid));
590 bf::path apps_rw = ci::GetRootAppPath(false, params.test_user.uid);
591 EXTENDED_ASSERT_TRUE(CheckSharedDataNonExistanceForPath(apps_rw, pkgid));
596 void BackendInterface::TestRollbackAfterEachStep(int argc, const char* argv[],
597 std::function<bool()> validator) const {
598 ci::Subprocess backend_helper = CreateSubprocess();
599 bool result = backend_helper.RunFunc({[&]() -> int {
600 TestPkgmgrInstaller pkgmgr_installer;
601 std::shared_ptr<ci::AppQueryInterface> query_interface =
602 CreateQueryInterface();
604 ci::PkgMgrInterface::Create(argc, const_cast<char**>(argv),
608 LOG(ERROR) << "Failed to initialize pkgmgr interface";
611 AppInstallerPtr backend;
612 unsigned int insert_idx = 0;
614 backend = CreateFailExpectedInstaller(pkgmgr, insert_idx);
615 LOG(DEBUG) << "StepFail is inserted at: " << insert_idx;
616 ci::AppInstaller::Result ret = backend->Run();
617 if (ret != ci::AppInstaller::Result::ERROR) {
618 LOG(ERROR) << "StepFail not executed";
622 LOG(ERROR) << "Fail to validate. index of StepFail : " << insert_idx;
626 } while (insert_idx < backend->StepCount());
627 if (insert_idx != backend->StepCount())
632 ASSERT_EQ(result, true);
633 int status = backend_helper.Wait();
634 ASSERT_NE(WIFEXITED(status), 0);
635 ASSERT_EQ(WEXITSTATUS(status), 0);
638 void BackendInterface::CrashAfterEachStep(std::vector<std::string>* args,
639 std::function<bool(int iter)> validator, PackageType type) const {
640 ci::Subprocess backend_helper = CreateSubprocess();
641 bool result = backend_helper.RunFunc({[&]() {
642 std::unique_ptr<const char*[]> argv(new const char*[args->size()]);
643 for (size_t i = 0; i < args->size(); ++i) {
644 argv[i] = args->at(i).c_str();
646 TestPkgmgrInstaller pkgmgr_installer;
647 auto query_interface = CreateQueryInterface();
648 auto pkgmgr = ci::PkgMgrInterface::Create(args->size(),
649 const_cast<char**>(argv.get()), &pkgmgr_installer, query_interface);
651 LOG(ERROR) << "Failed to initialize pkgmgr interface";
654 auto backend = CreateFailExpectedInstaller(pkgmgr, 0);
655 if (backend->Run() != ci::AppInstaller::Result::ERROR) {
656 LOG(ERROR) << "StepFail not executed";
659 int stepCount = backend->StepCount();
661 args->push_back("-idx");
662 args->push_back(std::to_string(stepCount));
664 std::string prefix = (type == PackageType::TPK) ? "tpk" : "wgt";
665 for (insert_idx = 0; insert_idx < stepCount; insert_idx++) {
666 ci::Subprocess backend_crash(
667 "/usr/bin/" + prefix + "-installer-ut/smoke-test-helper");
668 args->back() = std::to_string(insert_idx);
669 backend_crash.Run(*args);
670 if (backend_crash.Wait() == 0) {
671 LOG(ERROR) << "Subprocess exit without crash";
674 if (!validator(insert_idx)) {
675 LOG(ERROR) << "Fail to validate. index of StepCrash : " << insert_idx;
679 if (stepCount != insert_idx)
682 args->push_back("-type_clean");
683 for (insert_idx = stepCount - 1; insert_idx >= 2; insert_idx--) {
684 ci::Subprocess backend_crash(
685 "/usr/bin/" + prefix + "-installer-ut/smoke-test-helper");
686 auto it = args->end();
688 *it = std::to_string(insert_idx);
689 backend_crash.Run(*args);
690 if (backend_crash.Wait() == 0) {
691 LOG(ERROR) << "Subprocess exit without crash";
694 if (!validator(insert_idx)) {
695 LOG(ERROR) << "Fail to validate. index of StepCrash : " << insert_idx;
705 ASSERT_EQ(result, true);
706 int status = backend_helper.Wait();
707 ASSERT_NE(WIFEXITED(status), 0);
708 ASSERT_EQ(WEXITSTATUS(status), 0);
711 BackendInterface::CommandResult BackendInterface::RunInstallersWithPkgmgr(
712 ci::PkgMgrPtr pkgmgr) const {
713 std::list<AppInstallerPtr> installers;
714 for (int i = 0; i < pkgmgr->GetRequestInfoCount(); i++) {
715 AppInstallerPtr installer;
716 if (mode_ == RequestResult::FAIL && i == pkgmgr->GetRequestInfoCount() - 1)
717 installer = factory_->CreateFailExpectedInstaller(i, pkgmgr);
719 installer = factory_->CreateInstaller(i, pkgmgr);
721 LOG(ERROR) << "Failed to create installer";
723 installers.emplace_back(std::move(installer));
726 // FIXME: I think we should not implement this logic here...
727 CommandResult result = CommandResult::OK;
728 std::list<AppInstallerPtr>::iterator it(installers.begin());
729 for (; it != installers.end(); ++it) {
730 result = (*it)->Process();
731 if (result != CommandResult::OK)
734 if (it != installers.end() && result == CommandResult::ERROR) {
736 CommandResult ret = (*it)->Undo();
737 if (ret != CommandResult::OK && ret != CommandResult::ERROR)
738 result = CommandResult::UNDO_ERROR;
739 } while (it-- != installers.begin());
743 if ((*it)->Clean() != CommandResult::OK)
744 result = CommandResult::CLEANUP_ERROR;
745 } while (it-- != installers.begin());
750 BackendInterface::CommandResult BackendInterface::CallBackendWithRunner(
751 int argc, const char* argv[]) const {
752 TestPkgmgrInstaller pkgmgr_installer;
753 auto pkgmgr = ci::PkgMgrInterface::Create(argc, const_cast<char**>(argv),
756 LOG(ERROR) << "Failed to initialize pkgmgr interface";
757 return BackendInterface::CommandResult::UNKNOWN;
759 return RunInstallersWithPkgmgr(pkgmgr);
762 BackendInterface::CommandResult BackendInterface::Install(
763 const std::vector<bf::path>& paths) const {
764 std::vector<const char*> argv;
765 argv.emplace_back("");
766 argv.emplace_back("-i");
767 for (const auto& p : paths)
768 argv.emplace_back(p.string().c_str());
769 return CallBackendWithRunner(argv.size(), argv.data());
772 BackendInterface::CommandResult BackendInterface::Uninstall(
773 const std::vector<std::string>& pkgids) const {
774 std::vector<const char*> argv;
775 argv.emplace_back("");
776 argv.emplace_back("-d");
777 for (const auto& p : pkgids)
778 argv.emplace_back(p.c_str());
779 return CallBackendWithRunner(argv.size(), argv.data());
782 BackendInterface::CommandResult BackendInterface::InstallSuccess(
783 const std::vector<bf::path>& paths) const {
784 RequestResult tmp_mode = mode_;
785 RequestResult &original_mode = const_cast<RequestResult&>(mode_);
786 original_mode = RequestResult::NORMAL;
787 if (Install(paths) != BackendInterface::CommandResult::OK) {
788 LOG(ERROR) << "Failed to install application. Cannot update";
789 return BackendInterface::CommandResult::UNKNOWN;
791 original_mode = tmp_mode;
792 return BackendInterface::CommandResult::OK;
795 BackendInterface::CommandResult BackendInterface::RunInstallerWithPkgrmgr(
796 ci::PkgMgrPtr pkgmgr) const {
797 std::unique_ptr<ci::AppInstaller> installer;
799 case RequestResult::FAIL:
800 installer = CreateFailExpectedInstaller(pkgmgr);
803 installer = CreateInstaller(pkgmgr);
806 return installer->Run();
809 BackendInterface::CommandResult BackendInterface::CallBackend(int argc,
810 const char* argv[]) const {
811 TestPkgmgrInstaller pkgmgr_installer;
812 auto query_interface = CreateQueryInterface();
813 auto pkgmgr = ci::PkgMgrInterface::Create(argc, const_cast<char**>(argv),
814 &pkgmgr_installer, query_interface);
816 LOG(ERROR) << "Failed to initialize pkgmgr interface";
817 return BackendInterface::CommandResult::UNKNOWN;
819 return RunInstallerWithPkgrmgr(pkgmgr);
822 BackendInterface::CommandResult BackendInterface::Install(
823 const bf::path& path) const {
824 const char* argv[] = {"", "-i", path.c_str(), "-u", uid_str_.c_str()};
825 return CallBackend(SIZEOFARRAY(argv), argv);
828 BackendInterface::CommandResult BackendInterface::InstallPreload(
829 const bf::path& path) const {
830 const char* argv[] = {"", "-i", path.c_str(), "--preload"};
831 return CallBackend(SIZEOFARRAY(argv), argv);
834 BackendInterface::CommandResult BackendInterface::InstallWithStorage(
835 const bf::path& path, StorageType type) const {
836 int default_storage = 0;
839 case StorageType::EXTERNAL:
842 case StorageType::EXTENDED:
846 LOG(ERROR) << "Unknown storage type";
849 if (vconf_get_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT,
850 &default_storage) != 0) {
851 LOG(ERROR) << "Failed to get value of "
852 "VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT";
853 return BackendInterface::CommandResult::ERROR;
855 if (vconf_set_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT,
857 LOG(ERROR) << "Failed to set value of "
858 "VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT";
859 return BackendInterface::CommandResult::ERROR;
862 const char* argv[] = {"", "-i", path.c_str(), "-u", uid_str_.c_str()};
863 BackendInterface::CommandResult result = CallBackend(SIZEOFARRAY(argv), argv);
865 if (vconf_set_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT,
866 default_storage) != 0) {
867 LOG(ERROR) << "Failed to set value of "
868 "VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT";
869 return BackendInterface::CommandResult::ERROR;
875 BackendInterface::CommandResult BackendInterface::MigrateLegacyExternalImage(
876 const std::string& pkgid,
877 const bf::path& path,
878 const bf::path& legacy_path) const {
879 if (InstallWithStorage(path, StorageType::EXTERNAL) !=
880 BackendInterface::CommandResult::OK) {
881 LOG(ERROR) << "Failed to install application. Cannot perform Migrate";
882 return BackendInterface::CommandResult::ERROR;
885 bf::path ext_mount_path = ci::GetExternalCardPath();
886 if (bf::is_empty(ext_mount_path)) {
887 LOG(ERROR) << "Sdcard not exists!";
888 return BackendInterface::CommandResult::ERROR;
890 bf::path app2sd_path = ext_mount_path / "app2sd";
892 char* image_name = app2ext_usr_getname_image(pkgid.c_str(),
895 LOG(ERROR) << "Failed to get external image name";
896 return BackendInterface::CommandResult::ERROR;
898 bf::path org_image = app2sd_path / image_name;
901 bs::error_code error;
902 bf::remove(org_image, error);
904 LOG(ERROR) << "Failed to remove org image";
905 return BackendInterface::CommandResult::ERROR;
908 bf::path db_path = tzplatform_getenv(TZ_SYS_DB);
909 bf::path app2sd_db = db_path / ".app2sd.db";
910 bf::path app2sd_db_journal = db_path / ".app2sd.db-journal";
911 bf::remove(app2sd_db, error);
913 LOG(ERROR) << "Failed to remove app2sd db";
914 return BackendInterface::CommandResult::ERROR;
916 bf::remove(app2sd_db_journal, error);
918 LOG(ERROR) << "Failed to remove app2sd journal db";
919 return BackendInterface::CommandResult::ERROR;
922 bf::path app2sd_migrate_db = legacy_path / kMigrateTestDBName;
923 if (!ci::CopyFile(app2sd_migrate_db, app2sd_db)) {
924 LOG(ERROR) << "Failed to copy test db";
925 return BackendInterface::CommandResult::ERROR;
928 bf::path legacy_src = legacy_path / pkgid;
929 bf::path legacy_dst = app2sd_path / pkgid;
930 if (!ci::CopyFile(legacy_src, legacy_dst)) {
931 LOG(ERROR) << "Failed to copy test image";
932 return BackendInterface::CommandResult::ERROR;
934 const char* argv[] = {"", "--migrate-extimg", pkgid.c_str(),
935 "-u", uid_str_.c_str()};
936 return CallBackend(SIZEOFARRAY(argv), argv);
939 BackendInterface::CommandResult BackendInterface::RDSUpdate(
940 const bf::path& path,
941 const std::string& pkgid) const {
942 RequestResult tmp_mode = mode_;
943 RequestResult &original_mode = const_cast<RequestResult&>(mode_);
944 original_mode = RequestResult::NORMAL;
945 if (Install(path) != BackendInterface::CommandResult::OK) {
946 LOG(ERROR) << "Failed to install application. Cannot perform RDS";
947 return BackendInterface::CommandResult::UNKNOWN;
949 const char* argv[] = {"", "-r", pkgid.c_str(), "-u",
951 original_mode = tmp_mode;
952 return CallBackend(SIZEOFARRAY(argv), argv);
955 BackendInterface::CommandResult BackendInterface::EnablePackage(
956 const std::string& pkgid) const {
957 const char* argv[] = {"", "-A", pkgid.c_str(), "-u", uid_str_.c_str()};
958 return CallBackend(SIZEOFARRAY(argv), argv);
961 BackendInterface::CommandResult BackendInterface::DisablePackage(
962 const std::string& pkgid) const {
963 const char* argv[] = {"", "-D", pkgid.c_str(), "-u", uid_str_.c_str()};
964 return CallBackend(SIZEOFARRAY(argv), argv);
967 BackendInterface::CommandResult BackendInterface::Recover(
968 const bf::path& recovery_file) const {
969 const char* argv[] = {"", "-b", recovery_file.c_str(), "-u",
971 return CallBackend(SIZEOFARRAY(argv), argv);
974 BackendInterface::CommandResult BackendInterface::ManifestDirectInstall(
975 const std::string& pkgid) const {
976 const char* argv[] = {"", "-y", pkgid.c_str(), "-u", uid_str_.c_str()};
977 return CallBackend(SIZEOFARRAY(argv), argv);
980 BackendInterface::CommandResult BackendInterface::Uninstall(
981 const std::string& pkgid) const {
982 const char* argv[] = {"", "-d", pkgid.c_str(), "-u", uid_str_.c_str()};
983 return CallBackend(SIZEOFARRAY(argv), argv);
986 BackendInterface::CommandResult BackendInterface::UninstallPreload(
987 const std::string& pkgid) const {
988 const char* argv[] = {"", "-d", pkgid.c_str(), "--preload",
990 return CallBackend(SIZEOFARRAY(argv), argv);
993 BackendInterface::CommandResult BackendInterface::InstallSuccess(
994 const bf::path& path) const {
995 RequestResult tmp_mode = mode_;
996 RequestResult &original_mode = const_cast<RequestResult&>(mode_);
997 original_mode = RequestResult::NORMAL;
998 if (Install(path) != BackendInterface::CommandResult::OK) {
999 LOG(ERROR) << "Failed to install application. Cannot update";
1000 return BackendInterface::CommandResult::UNKNOWN;
1002 original_mode = tmp_mode;
1003 return BackendInterface::CommandResult::OK;
1006 BackendInterface::CommandResult BackendInterface::InstallPreloadSuccess(
1007 const bf::path& path) const {
1008 RequestResult tmp_mode = mode_;
1009 RequestResult &original_mode = const_cast<RequestResult&>(mode_);
1010 original_mode = RequestResult::NORMAL;
1011 if (InstallPreload(path) != BackendInterface::CommandResult::OK) {
1012 LOG(ERROR) << "Failed to install application. Cannot update";
1013 return BackendInterface::CommandResult::UNKNOWN;
1015 original_mode = tmp_mode;
1016 return BackendInterface::CommandResult::OK;
1019 BackendInterface::CommandResult BackendInterface::MountInstall(
1020 const bf::path& path) const {
1021 const char* argv[] = {"", "-w", path.c_str(), "-u", uid_str_.c_str()};
1022 return CallBackend(SIZEOFARRAY(argv), argv);
1025 BackendInterface::CommandResult BackendInterface::MountInstallSuccess(
1026 const bf::path& path) const {
1027 RequestResult tmp_mode = mode_;
1028 RequestResult &original_mode = const_cast<RequestResult&>(mode_);
1029 original_mode = RequestResult::NORMAL;
1030 if (MountInstall(path) != BackendInterface::CommandResult::OK) {
1031 LOG(ERROR) << "Failed to mount-install application. Cannot mount-update";
1032 return BackendInterface::CommandResult::UNKNOWN;
1034 original_mode = tmp_mode;
1035 return BackendInterface::CommandResult::OK;
1038 static boost::filesystem::path GetTrashPath(
1039 const boost::filesystem::path& path) {
1040 return path.string() + ".trash";
1043 BackendInterface::SubProcessResult BackendInterface::RunSubprocess(
1044 std::vector<std::string> args) const {
1045 args.push_back("-remove_plugin_steps");
1046 ci::Subprocess backend = CreateSubprocess();
1047 backend.RunWithArgs(args);
1048 int status = backend.Wait();
1049 if (WIFEXITED(status)) {
1050 if (WEXITSTATUS(status) == 0)
1051 return BackendInterface::SubProcessResult::SUCCESS;
1053 return BackendInterface::SubProcessResult::FAIL;
1055 return BackendInterface::SubProcessResult::UnKnown;
1058 BackendInterface::SubProcessResult BackendInterface::RunSubprocessAndKill(
1059 std::vector<std::string> args, useconds_t delay) const {
1060 args.push_back("-remove_plugin_steps");
1061 ci::Subprocess backend = CreateSubprocess();
1062 backend.RunWithArgs(args);
1065 int status = backend.Wait();
1066 if (WIFEXITED(status)) {
1067 if (WEXITSTATUS(status) == 0)
1068 return BackendInterface::SubProcessResult::SUCCESS;
1070 return BackendInterface::SubProcessResult::FAIL;
1072 if (WTERMSIG(status) == SIGKILL)
1073 return BackendInterface::SubProcessResult::KILLED;
1075 return BackendInterface::SubProcessResult::UnKnown;
1079 BackendInterface::SubProcessResult BackendInterface::InstallWithSubprocess(
1080 const bf::path& path) const {
1081 std::vector<std::string> args =
1082 { "-i", path.string(), "-u", uid_str_ };
1083 return RunSubprocess(args);
1086 BackendInterface::SubProcessResult BackendInterface::MountInstallWithSubprocess(
1087 const bf::path& path) const {
1088 std::vector<std::string> args =
1089 { "-w", path.string(), "-u", uid_str_ };
1090 return RunSubprocess(args);
1093 BackendInterface::SubProcessResult BackendInterface::RecoverWithSubprocess(
1094 const bf::path& path) const {
1095 std::vector<std::string> args =
1096 { "-b", path.string(), "-u", uid_str_ };
1097 return RunSubprocess(args);
1100 BackendInterface::SubProcessResult BackendInterface::UninstallWithSubprocess(
1101 const std::string& pkgid) const {
1102 std::vector<std::string> args = { "-d", pkgid, "-u", uid_str_ };
1103 return RunSubprocess(args);
1106 BackendInterface::SubProcessResult
1107 BackendInterface::InstallPreloadWithSubprocess(
1108 const boost::filesystem::path& path) const {
1109 std::vector<std::string> args = { "", "-i", path.string(), "--preload" };
1110 return RunSubprocess(args);
1113 BackendInterface::SubProcessResult
1114 BackendInterface::InstallWithSubprocessAndKill(
1115 const bf::path& path, useconds_t delay) const {
1116 std::vector<std::string> args =
1117 { "-i", path.string(), "-u", uid_str_ };
1118 return RunSubprocessAndKill(args, delay);
1121 BackendInterface::SubProcessResult
1122 BackendInterface::MountInstallWithSubprocessAndKill(
1123 const bf::path& path, useconds_t delay) const {
1124 std::vector<std::string> args =
1125 { "-w", path.string(), "-u", uid_str_ };
1126 return RunSubprocessAndKill(args, delay);
1129 BackendInterface::SubProcessResult
1130 BackendInterface::UninstallWithSubprocessAndKill(
1131 const std::string& pkgid, useconds_t delay) const {
1132 std::vector<std::string> args =
1133 { "-d", pkgid, "-u", uid_str_ };
1134 return RunSubprocessAndKill(args, delay);
1137 BackendInterface::SubProcessResult BackendInterface::InstallPkgsWithSubprocess(
1138 const std::vector<bf::path>& paths) const {
1139 std::vector<std::string> args;
1140 args.emplace_back("-i");
1141 for (const bf::path& p : paths)
1142 args.emplace_back(p.string());
1143 args.emplace_back("-u");
1144 args.emplace_back(uid_str_);
1145 return RunSubprocess(args);
1148 BackendInterface::SubProcessResult
1149 BackendInterface::MountInstallPkgsWithSubprocess(
1150 const std::vector<bf::path>& paths) const {
1151 std::vector<std::string> args;
1152 args.emplace_back("-w");
1153 for (const bf::path& p : paths)
1154 args.emplace_back(p.string());
1155 args.emplace_back("-u");
1156 args.emplace_back(uid_str_);
1157 return RunSubprocess(args);
1160 BackendInterface::SubProcessResult BackendInterface::RecoverPkgsWithSubprocess(
1161 const std::vector<bf::path>& paths) const {
1162 std::vector<std::string> args;
1163 args.emplace_back("-b");
1164 for (const bf::path& p : paths)
1165 args.emplace_back(p.string());
1166 args.emplace_back("-u");
1167 args.emplace_back(uid_str_);
1168 return RunSubprocess(args);
1171 BackendInterface::SubProcessResult
1172 BackendInterface::UninstallPkgsWithSubprocess(
1173 const std::vector<std::string>& pkgids) const {
1174 std::vector<std::string> args;
1175 args.emplace_back("-d");
1176 args.insert(args.end(), pkgids.begin(), pkgids.end());
1177 args.emplace_back("-u");
1178 args.emplace_back(uid_str_);
1179 return RunSubprocess(args);
1182 BackendInterface::SubProcessResult
1183 BackendInterface::InstallPkgsWithSubprocessAndKill(
1184 const std::vector<bf::path>& paths, useconds_t delay) const {
1185 std::vector<std::string> args;
1186 args.emplace_back("-i");
1187 for (const bf::path& p : paths)
1188 args.emplace_back(p.string());
1189 args.emplace_back("-u");
1190 args.emplace_back(uid_str_);
1191 return RunSubprocessAndKill(args, delay);
1194 BackendInterface::SubProcessResult
1195 BackendInterface::MountInstallPkgsWithSubprocessAndKill(
1196 const std::vector<bf::path>& paths, useconds_t delay) const {
1197 std::vector<std::string> args;
1198 args.emplace_back("-w");
1199 for (const bf::path& p : paths)
1200 args.emplace_back(p.string());
1201 args.emplace_back("-u");
1202 args.emplace_back(uid_str_);
1203 return RunSubprocessAndKill(args, delay);
1206 bool CopySmackAccess(const boost::filesystem::path& src,
1207 const boost::filesystem::path& dst) {
1208 if (!bf::exists(src) && !bf::is_symlink(src)) {
1209 LOG(ERROR) << "Failed to copy smack access label";
1213 char* access_label = nullptr;
1214 ret = smack_lgetlabel(src.c_str(), &access_label, SMACK_LABEL_ACCESS);
1216 LOG(ERROR) << "get access label from [" << src << "] fail";
1221 ret = smack_lsetlabel(dst.c_str(), access_label, SMACK_LABEL_ACCESS);
1224 LOG(ERROR) << "set access label to [" << dst << "] fail";
1230 bool CopySmackExec(const boost::filesystem::path& src,
1231 const boost::filesystem::path& dst) {
1232 if (!bf::exists(src) && !bf::is_symlink(src)) {
1233 LOG(ERROR) << "Failed to copy smack exec label";
1237 char *exec_label = nullptr;
1238 ret = smack_lgetlabel(src.c_str(), &exec_label, SMACK_LABEL_EXEC);
1240 LOG(ERROR) << "get exec label from [" << src << "] fail";
1245 ret = smack_lsetlabel(dst.c_str(), exec_label, SMACK_LABEL_EXEC);
1248 LOG(ERROR) << "set exec label to [" << dst << "] fail";
1254 bool CopySmackMmap(const boost::filesystem::path& src,
1255 const boost::filesystem::path& dst) {
1256 if (!bf::exists(src) && !bf::is_symlink(src)) {
1257 LOG(ERROR) << "Failed to copy smack mmap label";
1261 char *mmap_label = nullptr;
1262 ret = smack_lgetlabel(src.c_str(), &mmap_label, SMACK_LABEL_MMAP);
1264 LOG(ERROR) << "get mmap label from [" << src << "] fail";
1269 ret = smack_lsetlabel(dst.c_str(), mmap_label, SMACK_LABEL_MMAP);
1272 LOG(ERROR) << "set mmap label to [" << dst << "] fail";
1278 bool CopySmackTransmute(const boost::filesystem::path& src,
1279 const boost::filesystem::path& dst) {
1280 if (!bf::exists(src)) {
1281 LOG(ERROR) << "Failed to copy smack tranmute label";
1285 char *transmute_label = nullptr;
1286 ret = smack_lgetlabel(src.c_str(), &transmute_label, SMACK_LABEL_TRANSMUTE);
1288 LOG(ERROR) << "get access label from [" << src << "] fail";
1291 if (!transmute_label) {
1292 ret = smack_lsetlabel(dst.c_str(), "0", SMACK_LABEL_TRANSMUTE);
1294 if (strcmp(transmute_label, "TRUE") == 0)
1295 ret = smack_lsetlabel(dst.c_str(), "1", SMACK_LABEL_TRANSMUTE);
1297 ret = smack_lsetlabel(dst.c_str(), "0", SMACK_LABEL_TRANSMUTE);
1298 free(transmute_label);
1300 LOG(ERROR) << "set access label to [" << dst << "] fail";
1308 bool CopySmackLabels(const boost::filesystem::path& src,
1309 const boost::filesystem::path& dst) {
1310 if (!CopySmackAccess(src, dst))
1312 if (!CopySmackExec(src, dst))
1314 if (!CopySmackMmap(src, dst))
1316 if (!bf::is_symlink(src) && bf::is_directory(src)) {
1317 if (!CopySmackTransmute(src, dst))
1323 bool CopyAndRemoveWithSmack(const bf::path& src, const bf::path& dst) {
1324 bs::error_code error;
1325 if (bf::exists(dst)) {
1327 bf::remove_all(dst, error);
1329 std::cout << "Exception occurred during remove [" << dst.string()
1330 << "], and skip this file"<< std::endl;
1333 if (!bf::is_directory(dst)) {
1334 LOG(ERROR) << "remove_all fail";
1340 if (bf::is_symlink(src)) {
1341 bf::copy_symlink(src, dst, error);
1343 LOG(ERROR) << "Failed to copy symlink: " << src << ", "
1347 if (!CopySmackLabels(src, dst)) {
1348 LOG(ERROR) << "copy smack label from [" << src.string()
1349 << "] to [" << dst.string() << "] fail";
1352 } else if (bf::is_directory(src)) {
1353 if (!bf::exists(dst)) {
1354 bf::create_directories(dst, error);
1356 LOG(ERROR) << "create directories fail";
1359 ci::CopyOwnershipAndPermissions(src, dst);
1360 if (!CopySmackLabels(src, dst)) {
1361 LOG(ERROR) << "copy smack label from [" << src.string()
1362 << "] to [" << dst.string() << "] fail";
1366 bool success = true;
1367 for (bf::directory_iterator file(src);
1368 file != bf::directory_iterator();
1370 bf::path current(file->path());
1371 bf::path target = dst / current.filename();
1372 success &= CopyAndRemoveWithSmack(current, target);
1374 bf::remove_all(src);
1378 bf::copy_file(src, dst);
1379 ci::CopyOwnershipAndPermissions(src, dst);
1380 if (!CopySmackLabels(src, dst)) {
1381 LOG(ERROR) << "copy smack label from [" << src.string()
1382 << "] to [" << dst.string() << "] fail";
1385 bf::remove_all(src);
1388 std::cout << "Exception occurred during copy [" << src.string()
1389 << "], and skip this file"<< std::endl;
1396 bool BackupPathCopyAndRemove(const bf::path& path) {
1397 if (!bf::exists(path))
1400 bf::path backup_path = path.string() + ".bck";
1401 std::cout << "Backup path: " << path << " to " << backup_path << std::endl;
1402 if (!CopyAndRemoveWithSmack(path, backup_path)) {
1403 LOG(ERROR) << "Failed to setup test environment. Does some previous"
1404 << " test crashed? Path: "
1405 << backup_path << " should not exist.";
1411 bool BackupPath(const bf::path& path) {
1412 bf::path trash_path = GetTrashPath(path);
1413 if (bf::exists(trash_path)) {
1414 LOG(ERROR) << trash_path << " exists. Please remove "
1415 << trash_path << " manually!";
1418 bf::path backup_path = path.string() + ".bck";
1419 std::cout << "Backup path: " << path << " to " << backup_path << std::endl;
1420 bs::error_code error;
1421 bf::remove_all(backup_path, error);
1423 LOG(ERROR) << "Remove failed: " << backup_path
1424 << " (" << error.message() << ")";
1425 if (bf::exists(path)) {
1426 bf::rename(path, backup_path, error);
1428 LOG(ERROR) << "Failed to setup test environment. Does some previous"
1429 << " test crashed? Path: "
1430 << backup_path << " should not exist.";
1434 if (bf::is_directory(backup_path))
1435 bf::create_directory(path);
1440 void CreateDatabase() {
1441 pkgmgr_parser_create_and_initialize_db(kGlobalUserUid);
1442 pkgmgr_parser_create_and_initialize_db(getuid());
1445 bool RestorePathCopyAndRemove(const bf::path& path) {
1446 bf::path backup_path = path.string() + ".bck";
1447 if (!bf::exists(backup_path))
1450 std::cout << "Restore path: " << path << " from " << backup_path << std::endl;
1451 if (!CopyAndRemoveWithSmack(backup_path, path)) {
1452 LOG(ERROR) << "Failed to restore backup path: " << backup_path;
1458 bool RestorePath(const bf::path& path) {
1459 bf::path backup_path = path.string() + ".bck";
1460 std::cout << "Restore path: " << path << " from " << backup_path << std::endl;
1461 bs::error_code error;
1462 bf::remove_all(path, error);
1464 bf::path trash_path = GetTrashPath(path);
1465 LOG(ERROR) << "Remove failed: " << path << " (" << error.message() << ")";
1466 std::cout << "Moving " << path << " to " << trash_path << std::endl;
1467 bf::rename(path, trash_path, error);
1469 LOG(ERROR) << "Failed to move " << path << " to " << trash_path
1470 << " (" << error.message() << ")";
1472 LOG(ERROR) << trash_path << " should be removed manually!";
1474 if (bf::exists(backup_path)) {
1475 bf::rename(backup_path, path, error);
1477 LOG(ERROR) << "Failed to restore backup path: " << backup_path
1478 << " (" << error.message() << ")";
1485 std::vector<bf::path> SetupBackupDirectories(uid_t test_uid) {
1486 std::vector<bf::path> entries;
1487 bf::path db_dir = bf::path(tzplatform_getenv(TZ_SYS_DB));
1488 if (test_uid != kGlobalUserUid)
1489 db_dir = db_dir / "user" / std::to_string(test_uid);
1490 for (auto e : kDBEntries) {
1491 bf::path path = db_dir / e;
1492 entries.emplace_back(path);
1495 if (getuid() == 0) {
1496 entries.emplace_back(kPreloadApps);
1497 entries.emplace_back(kPreloadManifestDir);
1498 entries.emplace_back(kPreloadIcons);
1501 if (test_uid == kGlobalUserUid) {
1502 entries.emplace_back(kSkelDir);
1503 entries.emplace_back(kGlobalManifestDir);
1504 ci::UserList list = ci::GetUserList();
1505 for (auto l : list) {
1506 bf::path apps = std::get<2>(l) / "apps_rw";
1507 entries.emplace_back(apps);
1510 tzplatform_set_user(test_uid);
1511 bf::path approot = tzplatform_getenv(TZ_USER_APPROOT);
1512 tzplatform_reset_user();
1513 entries.emplace_back(approot);
1516 bf::path apps_rw = ci::GetRootAppPath(false, test_uid);
1517 entries.emplace_back(apps_rw);
1518 entries.emplace_back(kSdkDirectory);
1523 void UninstallAllAppsInDirectory(bf::path dir, bool is_preload,
1524 BackendInterface* backend) {
1525 if (bf::exists(dir)) {
1526 for (auto& dir_entry : boost::make_iterator_range(
1527 bf::directory_iterator(dir), bf::directory_iterator())) {
1528 if (dir_entry.path().string().find("smoke") != std::string::npos &&
1529 bf::is_directory(dir_entry)) {
1530 std::string package = dir_entry.path().filename().string();
1531 std::regex pkg_regex("smoke[a-zA-Z0-9]{5,}");
1532 if (std::regex_match(package, pkg_regex)) {
1533 BackendInterface::CommandResult result =
1534 BackendInterface::CommandResult::OK;
1536 result = backend->UninstallPreload(
1537 dir_entry.path().filename().string());
1539 result = backend->Uninstall(
1540 dir_entry.path().filename().string());
1541 if (result != BackendInterface::CommandResult::OK) {
1542 LOG(ERROR) << "Cannot uninstall smoke test app: "
1543 << dir_entry.path().filename().string();
1551 void UninstallAllSmokeApps(ci::RequestMode request_mode, uid_t test_uid,
1552 BackendInterface *backend) {
1553 std::cout << "Uninstalling all smoke apps" << std::endl;
1554 bf::path apps_rw = ci::GetRootAppPath(false, test_uid);
1555 UninstallAllAppsInDirectory(apps_rw, false, backend);
1556 if (getuid() == 0 && request_mode == ci::RequestMode::GLOBAL) {
1557 bf::path root_path = kPreloadApps;
1558 UninstallAllAppsInDirectory(root_path, true, backend);
1562 int GetAppInstalledTime(const char* appid, uid_t uid) {
1564 int installed_time = 0;
1565 pkgmgrinfo_appinfo_h handle = NULL;
1566 ret = pkgmgrinfo_appinfo_get_usr_appinfo(appid, uid, &handle);
1567 if (ret != PMINFO_R_OK)
1569 ret = pkgmgrinfo_appinfo_get_installed_time(handle, &installed_time);
1570 if (ret != PMINFO_R_OK) {
1571 pkgmgrinfo_appinfo_destroy_appinfo(handle);
1574 pkgmgrinfo_appinfo_destroy_appinfo(handle);
1575 return installed_time;
1578 } // namespace smoke_test