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 "unit_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>
29 namespace bf = boost::filesystem;
30 namespace bs = boost::system;
31 namespace ci = common_installer;
32 namespace bo = boost::program_options;
36 const uid_t kDefaultUserUid = tzplatform_getuid(TZ_SYS_DEFAULT_USER);
37 const gid_t kDefaultUserGid = tzplatform_getgid(TZ_SYS_DEFAULT_USER);
38 const char kNormalUserName[] = "smokeuser";
39 const char kSystemShareGroupName[] = "system_share";
40 const char kMigrateTestDBName[] = "app2sd_migrate.db";
42 const std::vector<std::string> kDBEntries = {
43 {".pkgmgr_parser.db"},
44 {".pkgmgr_parser.db-journal"},
46 {".pkgmgr_cert.db-journal"},
48 {".app2sd.db-journal"},
51 const char kGlobalManifestDir[] = "/opt/share/packages";
52 const char kSkelDir[] = "/etc/skel/apps_rw";
53 const char kPreloadApps[] = "/usr/apps";
54 const char kPreloadManifestDir[] = "/usr/share/packages";
55 const char kPreloadIcons[] = "/usr/share/icons";
56 const char kData[] = "data";
57 const char kShared[] = ".shared";
58 const char kSharedTmp[] = ".shared_tmp";
68 const char* rwDirectories[] = {
78 namespace smoke_test {
80 const char kLegacyExtImageDir[] = "legacy_extimage_dir";
81 const std::string& kDefaultUserIdStr = std::to_string(kDefaultUserUid);
82 const uid_t kGlobalUserUid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
83 const uid_t kGlobalUserGid = tzplatform_getgid(TZ_SYS_GLOBALAPP_USER);
84 extern const bf::path kSdkDirectory = "/home/owner/share/tmp/sdk_tools";
86 ci::RequestMode ParseRequestMode(int argc, char** argv) {
87 bo::options_description desc("Available options");
89 ("request-mode", bo::value<std::string>(), "set request mode")
90 ("global-request,g", "set request mode to global")
91 ("user-request,u", "set request mode to user");
94 bo::store(bo::command_line_parser(argc, argv).
95 options(desc).allow_unregistered().run(), vm);
98 if (vm.count("global-request")) {
99 std::cout << "Request mode was set to global." << std::endl;
100 return ci::RequestMode::GLOBAL;
102 if (vm.count("user-request")) {
103 std::cout << "Request mode was set to user." << std::endl;
104 return ci::RequestMode::USER;
106 if (vm.count("request-mode")) {
107 if (vm["request-mode"].as<std::string>() == "global") {
108 std::cout << "Request mode was set to global." << std::endl;
109 return ci::RequestMode::GLOBAL;
111 if (vm["request-mode"].as<std::string>() == "user") {
112 std::cout << "Request mode was set to user." << std::endl;
113 return ci::RequestMode::USER;
115 std::cout << "Cannot set request mode to "
116 << vm["request-mode"].as<std::string>() << std::endl;
118 std::cout << "Request mode was set to global." << std::endl;
119 return ci::RequestMode::GLOBAL;
122 static bool AddUser(const char* user_name) {
123 GumUser* user = nullptr;
124 user = gum_user_create_sync(FALSE);
126 LOG(WARNING) << "Failed to create gum user! (user name: "
128 g_object_set(G_OBJECT(user), "username", user_name, "usertype",
129 GUM_USERTYPE_NORMAL, NULL);
130 gboolean rval = FALSE;
131 rval = gum_user_add_sync(user);
132 g_object_unref(user);
136 static bool DeleteUser(const char* user_name, bool rem_home_dir) {
138 GumUser* guser = gum_user_get_by_name_sync(user_name, FALSE);
140 rval = gum_user_delete_sync(guser, rem_home_dir);
144 bool AddTestUser(User* test_user) {
145 std::cout << "Adding test user: " << kNormalUserName << std::endl;
146 AddUser(kNormalUserName);
147 if (boost::optional<uid_t> uid = ci::GetUidByUserName(kNormalUserName)) {
148 test_user->uid = *uid;
149 std::cout << "User created properly: uid=" << *uid;
150 if (boost::optional<gid_t> gid = ci::GetGidByUid(*uid)) {
151 test_user->gid = *gid;
152 std::cout << " gid=" << *gid;
154 std::cout << std::endl;
157 LOG(ERROR) << "Adding test user failed";
161 bool DeleteTestUser() {
162 std::cout << "Deleting test user: " << kNormalUserName << std::endl;
164 if (boost::optional<uid_t> uid = ci::GetUidByUserName(kNormalUserName))
168 DeleteUser(kNormalUserName, true);
169 if (!ci::GetUidByUserName(kNormalUserName)) {
170 std::cout << "User deleted properly: user_name=" << kNormalUserName
171 << " uid=" << test_uid << std::endl;
174 LOG(ERROR) << "Deleting test user failed";
178 bool TouchFile(const bf::path& path) {
179 FILE* f = fopen(path.c_str(), "w+");
186 void AddDataFiles(const std::string& pkgid, uid_t uid) {
187 if (uid == kGlobalUserUid) {
188 ci::UserList list = ci::GetUserList();
189 for (auto l : list) {
190 auto pkg_path = GetPackageRoot(pkgid, std::get<0>(l));
191 ASSERT_TRUE(TouchFile(pkg_path / "data" / "file1.txt"));
192 ASSERT_TRUE(TouchFile(pkg_path / "data" / "file2.txt"));
195 auto pkg_path = GetPackageRoot(pkgid, uid);
196 ASSERT_TRUE(TouchFile(pkg_path / "data" / "file1.txt"));
197 ASSERT_TRUE(TouchFile(pkg_path / "data" / "file2.txt"));
201 void RemoveAllRecoveryFiles(const std::string& prefix, uid_t uid) {
202 bf::path root_path = ci::GetRootAppPath(false, uid);
203 if (!bf::exists(root_path))
205 for (auto& dir_entry : boost::make_iterator_range(
206 bf::directory_iterator(root_path), bf::directory_iterator())) {
207 if (bf::is_regular_file(dir_entry)) {
208 if (dir_entry.path().string().find(prefix) != std::string::npos) {
209 bs::error_code error;
210 bf::remove(dir_entry.path(), error);
212 LOG(ERROR) << "Failed to remove " << dir_entry.path()
213 << ": " << error.message();
219 bf::path FindRecoveryFile(const std::string& prefix, uid_t uid) {
220 bf::path root_path = ci::GetRootAppPath(false, uid);
221 if (!bf::exists(root_path))
224 for (auto& dir_entry : boost::make_iterator_range(
225 bf::directory_iterator(root_path), bf::directory_iterator())) {
226 if (bf::is_regular_file(dir_entry)) {
227 if (dir_entry.path().string().find(prefix) != std::string::npos) {
228 return dir_entry.path();
235 std::unique_ptr<ci::recovery::RecoveryFile> GetRecoverFileInfo(
236 const bf::path& recovery_file_path) {
237 return ci::recovery::RecoveryFile::OpenRecoveryFile(recovery_file_path);
240 bf::path GetPackageRoot(const std::string& pkgid, uid_t uid) {
241 bf::path root_path = ci::GetRootAppPath(false, uid);
242 return root_path / pkgid;
245 bool ValidateFileContentInPackage(const std::string& pkgid,
246 const std::string& relative,
247 const std::string& expected,
248 const TestParameters& params) {
249 bf::path file_path = ci::GetRootAppPath(params.is_readonly,
250 params.test_user.uid);
251 file_path = file_path / pkgid / relative;
252 if (!bf::exists(file_path)) {
253 LOG(ERROR) << file_path << " doesn't exist";
256 FILE* handle = fopen(file_path.c_str(), "r");
258 LOG(ERROR) << file_path << " cannot be open";
262 std::array<char, 200> buffer;
263 while (fgets(buffer.data(), buffer.size(), handle)) {
264 content += buffer.data();
267 return content == expected;
270 static 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 static bool ValidatePackageFS(const std::string& pkgid, const Apps& apps,
300 const TestParameters& params) {
301 bf::path root_path = ci::GetRootAppPath(params.is_readonly,
302 params.test_user.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(params.test_user.uid,
311 params.is_readonly)) / (pkgid + ".xml");
312 EXTENDED_ASSERT_TRUE(bf::exists(manifest_path));
314 for (auto& app : apps) {
315 const std::string &exec = app.second;
316 bf::path binary_path = package_path / "bin" / exec;
317 EXTENDED_ASSERT_TRUE(bf::exists(binary_path));
320 if (params.pkg_type == PackageType::WGT ||
321 params.pkg_type == PackageType::HYBRID) {
322 bf::path widget_root_path = package_path / "res" / "wgt";
323 bf::path config_path = widget_root_path / "config.xml";
324 EXTENDED_ASSERT_TRUE(bf::exists(widget_root_path));
325 EXTENDED_ASSERT_TRUE(bf::exists(config_path));
327 bf::path private_tmp_path = package_path / "tmp";
328 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(params.test_user.uid, stats.st_uid);
354 EXTENDED_ASSERT_EQ(params.test_user.gid, stats.st_gid);
359 bool ValidatePackage(const std::string& pkgid, const Apps& apps,
360 const TestParameters& params) {
361 ci::PkgQueryInterface pkg_query(pkgid, params.test_user.uid, true);
362 EXTENDED_ASSERT_TRUE(pkg_query.IsPackageInstalled(
363 ci::GetRequestMode(params.test_user.uid)));
364 EXTENDED_ASSERT_TRUE(ValidatePackageFS(pkgid, apps, params));
365 if (params.test_user.uid == kGlobalUserUid) {
366 ci::UserList list = ci::GetUserList();
368 EXTENDED_ASSERT_TRUE(ValidatePackageRWFS(pkgid, std::get<0>(l)));
370 EXTENDED_ASSERT_TRUE(ValidatePackageRWFS(pkgid, params.test_user.uid));
375 bool ValidateDataFiles(const std::string& pkgid, uid_t uid) {
376 if (uid == kGlobalUserUid) {
377 ci::UserList list = ci::GetUserList();
378 for (auto l : list) {
379 auto pkg_path = GetPackageRoot(pkgid, std::get<0>(l));
380 EXTENDED_ASSERT_TRUE(bf::exists(pkg_path / "data" / "file1.txt"));
381 EXTENDED_ASSERT_TRUE(bf::exists(pkg_path / "data" / "file2.txt"));
384 auto pkg_path = GetPackageRoot(pkgid, uid);
385 EXTENDED_ASSERT_TRUE(bf::exists(pkg_path / "data" / "file1.txt"));
386 EXTENDED_ASSERT_TRUE(bf::exists(pkg_path / "data" / "file2.txt"));
391 static bool ValidateExternalPackageFS(const std::string& pkgid,
392 const Apps& apps, const TestParameters& params) {
393 EXTENDED_ASSERT_EQ(app2ext_usr_enable_external_pkg(pkgid.c_str(),
394 params.test_user.uid), 0);
395 bf::path root_path = ci::GetRootAppPath(false, params.test_user.uid);
396 if (params.pkg_type == PackageType::TPK) {
397 EXTENDED_ASSERT_TRUE(bf::exists(root_path / pkgid / ".mmc" / "bin"));
398 EXTENDED_ASSERT_TRUE(bf::exists(root_path / pkgid / ".mmc" / "lib"));
400 EXTENDED_ASSERT_TRUE(bf::exists(root_path / pkgid / ".mmc" / "res"));
401 EXTENDED_ASSERT_TRUE(ValidatePackageFS(pkgid, apps, params));
402 EXTENDED_ASSERT_EQ(app2ext_usr_disable_external_pkg(pkgid.c_str(),
403 params.test_user.uid), 0);
407 bool ValidateExternalPackage(const std::string& pkgid, const Apps& apps,
408 const TestParameters& params) {
409 ci::PkgQueryInterface pkg_query(pkgid, params.test_user.uid, true);
410 std::string storage = pkg_query.StorageForPkgId();
411 bf::path ext_mount_path = ci::GetExternalCardPath();
412 if (bf::is_empty(ext_mount_path)) {
413 LOG(INFO) << "Sdcard not exists!";
414 EXTENDED_ASSERT_EQ(storage, "installed_internal");
416 EXTENDED_ASSERT_EQ(storage, "installed_external");
418 EXTENDED_ASSERT_TRUE(ValidateExternalPackageFS(pkgid, apps, params));
422 bool ValidateExtendedPackage(const std::string& pkgid, const Apps& apps,
423 const TestParameters& params) {
424 ci::PkgQueryInterface pkg_query(pkgid, params.test_user.uid, true);
425 std::string storage = pkg_query.StorageForPkgId();
426 bf::path extended_path =
427 bf::path(ci::GetExtendedRootAppPath(params.test_user.uid)) / pkgid;
428 if (!bf::exists(extended_path)) {
429 LOG(INFO) << "Extended storage not exists!";
430 EXTENDED_ASSERT_EQ(storage, "installed_internal");
432 EXTENDED_ASSERT_EQ(storage, "installed_extended");
434 EXTENDED_ASSERT_TRUE(ValidatePackage(pkgid, apps, params));
438 static bool PackageCheckCleanup(const std::string& pkgid,
439 const TestParameters& params) {
440 bf::path root_path = ci::GetRootAppPath(params.is_readonly,
441 params.test_user.uid);
442 bf::path package_path = root_path / pkgid;
443 EXTENDED_ASSERT_FALSE(bf::exists(package_path));
445 bf::path manifest_path = bf::path(getUserManifestPath(params.test_user.uid,
446 params.is_readonly)) / (pkgid + ".xml");
447 EXTENDED_ASSERT_FALSE(bf::exists(manifest_path));
449 // backups should not exist
450 bf::path package_backup = ci::GetBackupPathForPackagePath(package_path);
451 bf::path manifest_backup = ci::GetBackupPathForManifestFile(manifest_path);
452 EXTENDED_ASSERT_FALSE(bf::exists(package_backup));
453 EXTENDED_ASSERT_FALSE(bf::exists(manifest_backup));
457 bool CheckPackageNonExistance(const std::string& pkgid,
458 const TestParameters& params) {
459 ci::PkgQueryInterface pkg_query(pkgid, params.test_user.uid, true);
460 EXTENDED_ASSERT_FALSE(pkg_query.IsPackageInstalled(
461 ci::GetRequestMode(params.test_user.uid)));
462 EXTENDED_ASSERT_TRUE(PackageCheckCleanup(pkgid, params));
463 if (params.test_user.uid == kGlobalUserUid) {
464 bf::path skel_path(kSkelDir);
465 EXTENDED_ASSERT_FALSE(bf::exists(skel_path / pkgid));
466 EXTENDED_ASSERT_FALSE(bf::exists(skel_path / kShared / pkgid));
467 EXTENDED_ASSERT_FALSE(bf::exists(skel_path / kSharedTmp / pkgid));
468 ci::UserList list = ci::GetUserList();
469 for (auto& l : list) {
470 bf::path root_path = ci::GetRootAppPath(false, std::get<0>(l));
471 EXTENDED_ASSERT_FALSE(bf::exists(root_path / kShared / pkgid));
472 EXTENDED_ASSERT_FALSE(bf::exists(root_path / kSharedTmp / pkgid));
473 bf::path package_path = root_path / pkgid;
474 EXTENDED_ASSERT_FALSE(bf::exists(package_path));
480 bool CheckAvailableExternalPath() {
481 bf::path ext_mount_path = ci::GetExternalCardPath();
482 LOG(DEBUG) << "ext_mount_path :" << ext_mount_path;
483 if (ext_mount_path.empty()) {
484 LOG(ERROR) << "Sdcard not exists!";
490 bool CheckAvailableExtendedPath() {
491 bf::path extended_path = bf::path(tzplatform_getenv(TZ_SYS_EXTENDEDSD));
492 LOG(DEBUG) << "extended_path :" << extended_path;
493 // TODO(jeremy.jang): It should be checked by libstorage API.
494 if (!bf::exists(extended_path)) {
495 LOG(ERROR) << "Extended storage not exists!";
501 bool CheckPackageReadonlyNonExistance(const std::string& pkgid,
502 const TestParameters& params) {
503 ci::PkgQueryInterface pkg_query(pkgid, params.test_user.uid, true);
504 EXTENDED_ASSERT_FALSE(pkg_query.IsPackageInstalled(
505 ci::GetRequestMode(params.test_user.uid)));
506 EXTENDED_ASSERT_TRUE(PackageCheckCleanup(pkgid, params));
510 static bool CheckSharedDataExistanceForPath(const bf::path& apps_rw,
511 const std::string& pkgid) {
512 bf::path shared_data_path = apps_rw / pkgid / rwDirectories[SHARED_DATA];
513 bf::path shared = apps_rw / kShared / pkgid / kData;
514 bf::path shared_tmp = apps_rw / kSharedTmp / pkgid;
515 EXTENDED_ASSERT_TRUE(bf::exists(shared_data_path));
516 EXTENDED_ASSERT_TRUE(bf::exists(shared));
517 EXTENDED_ASSERT_TRUE(bf::exists(shared_tmp));
521 static bool CheckSharedDataPermissions(const bf::path& apps_rw,
522 const std::string& pkgid, uid_t uid) {
523 bf::path shared_data_path = apps_rw / pkgid / rwDirectories[SHARED_DATA];
524 bf::path shared = apps_rw / kShared / pkgid / kData;
525 bf::path shared_tmp = apps_rw / kSharedTmp / pkgid;
526 // gid of RW dirs should be system_share
527 boost::optional<gid_t> system_share =
528 ci::GetGidByGroupName(kSystemShareGroupName);
530 stat(shared_data_path.c_str(), &stats);
531 EXTENDED_ASSERT_EQ(uid, stats.st_uid);
532 EXTENDED_ASSERT_EQ(*system_share, stats.st_gid);
533 stat(shared.c_str(), &stats);
534 EXTENDED_ASSERT_EQ(uid, stats.st_uid);
535 EXTENDED_ASSERT_EQ(*system_share, stats.st_gid);
536 stat(shared_tmp.c_str(), &stats);
537 EXTENDED_ASSERT_EQ(uid, stats.st_uid);
538 EXTENDED_ASSERT_EQ(kDefaultUserGid, stats.st_gid);
542 bool CheckSharedDataExistance(const std::string& pkgid,
543 const TestParameters& params) {
544 if (params.test_user.uid == kGlobalUserUid) {
545 bf::path skel_path(kSkelDir);
546 EXTENDED_ASSERT_TRUE(CheckSharedDataExistanceForPath(kSkelDir, pkgid));
547 ci::UserList list = ci::GetUserList();
548 for (auto& l : list) {
549 uid_t uid = std::get<0>(l);
550 bf::path apps_rw = ci::GetRootAppPath(false, uid);
551 EXTENDED_ASSERT_TRUE(CheckSharedDataExistanceForPath(apps_rw, pkgid));
552 EXTENDED_ASSERT_TRUE(CheckSharedDataPermissions(apps_rw, pkgid, uid));
555 bf::path apps_rw = ci::GetRootAppPath(false, params.test_user.uid);
556 EXTENDED_ASSERT_TRUE(CheckSharedDataExistanceForPath(apps_rw, pkgid));
557 EXTENDED_ASSERT_TRUE(
558 CheckSharedDataPermissions(apps_rw, pkgid, params.test_user.uid));
563 static bool CheckSharedDataNonExistanceForPath(const bf::path& apps_rw,
564 const std::string pkgid) {
565 bf::path shared_data_path = apps_rw / pkgid / rwDirectories[SHARED_DATA];
566 bf::path shared = apps_rw / kShared / pkgid / kData;
567 bf::path shared_tmp = apps_rw / kSharedTmp / pkgid;
568 EXTENDED_ASSERT_FALSE(bf::exists(shared_data_path));
569 EXTENDED_ASSERT_FALSE(bf::exists(shared));
570 EXTENDED_ASSERT_FALSE(bf::exists(shared_tmp));
574 bool CheckSharedDataNonExistance(const std::string& pkgid,
575 const TestParameters& params) {
576 if (params.test_user.uid == kGlobalUserUid) {
577 bf::path skel_path(kSkelDir);
578 EXTENDED_ASSERT_TRUE(
579 CheckSharedDataNonExistanceForPath(skel_path, pkgid));
581 ci::UserList list = ci::GetUserList();
582 for (auto& l : list) {
583 uid_t uid = std::get<0>(l);
584 bf::path apps_rw = ci::GetRootAppPath(false, uid);
585 EXTENDED_ASSERT_TRUE(CheckSharedDataNonExistanceForPath(apps_rw, pkgid));
588 bf::path apps_rw = ci::GetRootAppPath(false, params.test_user.uid);
589 EXTENDED_ASSERT_TRUE(CheckSharedDataNonExistanceForPath(apps_rw, pkgid));
594 void BackendInterface::TestRollbackAfterEachStep(int argc, const char* argv[],
595 std::function<bool()> validator) const {
596 TestPkgmgrInstaller pkgmgr_installer;
597 std::unique_ptr<ci::AppQueryInterface> query_interface =
598 CreateQueryInterface();
600 ci::PkgMgrInterface::Create(argc, const_cast<char**>(argv),
602 query_interface.get());
604 LOG(ERROR) << "Failed to initialize pkgmgr interface";
607 AppInstallerPtr backend;
608 unsigned int insert_idx = 0;
610 backend = CreateFailExpectedInstaller(pkgmgr, insert_idx);
611 LOG(DEBUG) << "StepFail is inserted at: " << insert_idx;
612 ASSERT_EQ(ci::AppInstaller::Result::ERROR, backend->Run());
616 } while (insert_idx < backend->StepCount());
617 ASSERT_EQ(insert_idx, backend->StepCount());
620 void BackendInterface::CrashAfterEachStep(std::vector<std::string>* args,
621 std::function<bool(int iter)> validator, PackageType type) const {
622 std::unique_ptr<const char*[]> argv(new const char*[args->size()]);
623 for (size_t i = 0; i < args->size(); ++i) {
624 argv[i] = args->at(i).c_str();
626 TestPkgmgrInstaller pkgmgr_installer;
627 auto query_interface = CreateQueryInterface();
629 ci::PkgMgrInterface::Create(args->size(), const_cast<char**>(argv.get()),
631 query_interface.get());
633 LOG(ERROR) << "Failed to initialize pkgmgr interface";
636 auto backend = CreateFailExpectedInstaller(pkgmgr, 0);
637 ASSERT_EQ(backend->Run(), ci::AppInstaller::Result::ERROR);
638 int stepCount = backend->StepCount();
640 args->push_back("-idx");
641 args->push_back(std::to_string(stepCount));
643 std::string prefix = (type == PackageType::TPK) ? "tpk" : "wgt";
644 for (i = 0; i < stepCount; i++) {
645 ci::Subprocess backend_crash(
646 "/usr/bin/" + prefix + "-installer-ut/smoke-test-helper");
647 args->back() = std::to_string(i);
648 backend_crash.Run(*args);
649 ASSERT_NE(backend_crash.Wait(), 0);
653 ASSERT_EQ(stepCount, i);
655 args->push_back("-type_clean");
656 for (i = stepCount - 1; i >= 2; i--) {
657 ci::Subprocess backend_crash(
658 "/usr/bin/" + prefix + "-installer-ut/smoke-test-helper");
659 auto it = args->end();
661 *it = std::to_string(i);
662 backend_crash.Run(*args);
663 ASSERT_NE(backend_crash.Wait(), 0);
670 BackendInterface::CommandResult BackendInterface::RunInstallersWithPkgmgr(
671 ci::PkgMgrPtr pkgmgr) const {
672 std::list<AppInstallerPtr> installers;
673 for (int i = 0; i < pkgmgr->GetRequestInfoCount(); i++) {
674 AppInstallerPtr installer;
675 if (mode_ == RequestResult::FAIL && i == pkgmgr->GetRequestInfoCount() - 1)
676 installer = factory_->CreateFailExpectedInstaller(i, pkgmgr);
678 installer = factory_->CreateInstaller(i, pkgmgr);
680 LOG(ERROR) << "Failed to create installer";
682 installers.emplace_back(std::move(installer));
685 // FIXME: I think we should not implement this logic here...
686 CommandResult result = CommandResult::OK;
687 std::list<AppInstallerPtr>::iterator it(installers.begin());
688 for (; it != installers.end(); ++it) {
689 result = (*it)->Process();
690 if (result != CommandResult::OK)
693 if (it != installers.end() && result == CommandResult::ERROR) {
695 CommandResult ret = (*it)->Undo();
696 if (ret != CommandResult::OK && ret != CommandResult::ERROR)
697 result = CommandResult::UNDO_ERROR;
698 } while (it-- != installers.begin());
702 if ((*it)->Clean() != CommandResult::OK)
703 result = CommandResult::CLEANUP_ERROR;
704 } while (it-- != installers.begin());
709 BackendInterface::CommandResult BackendInterface::CallBackendWithRunner(
710 int argc, const char* argv[]) const {
711 TestPkgmgrInstaller pkgmgr_installer;
712 auto pkgmgr = ci::PkgMgrInterface::Create(argc, const_cast<char**>(argv),
715 LOG(ERROR) << "Failed to initialize pkgmgr interface";
716 return BackendInterface::CommandResult::UNKNOWN;
718 return RunInstallersWithPkgmgr(pkgmgr);
721 BackendInterface::CommandResult BackendInterface::Install(
722 const std::vector<bf::path>& paths) const {
723 std::vector<const char*> argv;
724 argv.emplace_back("");
725 argv.emplace_back("-i");
726 for (const auto& p : paths)
727 argv.emplace_back(p.string().c_str());
728 return CallBackendWithRunner(argv.size(), argv.data());
731 BackendInterface::CommandResult BackendInterface::Uninstall(
732 const std::vector<std::string>& pkgids) const {
733 std::vector<const char*> argv;
734 argv.emplace_back("");
735 argv.emplace_back("-d");
736 for (const auto& p : pkgids)
737 argv.emplace_back(p.c_str());
738 return CallBackendWithRunner(argv.size(), argv.data());
741 BackendInterface::CommandResult BackendInterface::InstallSuccess(
742 const std::vector<bf::path>& paths) const {
743 RequestResult tmp_mode = mode_;
744 RequestResult &original_mode = const_cast<RequestResult&>(mode_);
745 original_mode = RequestResult::NORMAL;
746 if (Install(paths) != BackendInterface::CommandResult::OK) {
747 LOG(ERROR) << "Failed to install application. Cannot update";
748 return BackendInterface::CommandResult::UNKNOWN;
750 original_mode = tmp_mode;
751 return BackendInterface::CommandResult::OK;
754 BackendInterface::CommandResult BackendInterface::RunInstallerWithPkgrmgr(
755 ci::PkgMgrPtr pkgmgr) const {
756 std::unique_ptr<ci::AppInstaller> installer;
758 case RequestResult::FAIL:
759 installer = CreateFailExpectedInstaller(pkgmgr);
762 installer = CreateInstaller(pkgmgr);
765 return installer->Run();
768 BackendInterface::CommandResult BackendInterface::CallBackend(int argc,
769 const char* argv[]) const {
770 TestPkgmgrInstaller pkgmgr_installer;
771 auto query_interface = CreateQueryInterface();
772 auto pkgmgr = ci::PkgMgrInterface::Create(argc, const_cast<char**>(argv),
773 &pkgmgr_installer, query_interface.get());
775 LOG(ERROR) << "Failed to initialize pkgmgr interface";
776 return BackendInterface::CommandResult::UNKNOWN;
778 return RunInstallerWithPkgrmgr(pkgmgr);
781 BackendInterface::CommandResult BackendInterface::Install(
782 const bf::path& path) const {
783 const char* argv[] = {"", "-i", path.c_str(), "-u", uid_str_.c_str()};
784 return CallBackend(SIZEOFARRAY(argv), argv);
787 BackendInterface::CommandResult BackendInterface::InstallPreload(
788 const bf::path& path) const {
789 const char* argv[] = {"", "-i", path.c_str(), "--preload"};
790 return CallBackend(SIZEOFARRAY(argv), argv);
793 BackendInterface::CommandResult BackendInterface::InstallWithStorage(
794 const bf::path& path, StorageType type) const {
795 int default_storage = 0;
798 case StorageType::EXTERNAL:
801 case StorageType::EXTENDED:
805 LOG(ERROR) << "Unknown storage type";
808 vconf_get_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT,
810 vconf_set_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT, storage);
812 const char* argv[] = {"", "-i", path.c_str(), "-u", uid_str_.c_str()};
813 BackendInterface::CommandResult result = CallBackend(SIZEOFARRAY(argv), argv);
815 vconf_set_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT,
820 BackendInterface::CommandResult BackendInterface::MigrateLegacyExternalImage(
821 const std::string& pkgid,
822 const bf::path& path,
823 const bf::path& legacy_path) const {
824 if (InstallWithStorage(path, StorageType::EXTERNAL) !=
825 BackendInterface::CommandResult::OK) {
826 LOG(ERROR) << "Failed to install application. Cannot perform Migrate";
827 return BackendInterface::CommandResult::ERROR;
830 bf::path ext_mount_path = ci::GetExternalCardPath();
831 if (bf::is_empty(ext_mount_path)) {
832 LOG(ERROR) << "Sdcard not exists!";
833 return BackendInterface::CommandResult::ERROR;
835 bf::path app2sd_path = ext_mount_path / "app2sd";
837 char* image_name = app2ext_usr_getname_image(pkgid.c_str(),
840 LOG(ERROR) << "Failed to get external image name";
841 return BackendInterface::CommandResult::ERROR;
843 bf::path org_image = app2sd_path / image_name;
846 bs::error_code error;
847 bf::remove(org_image, error);
849 LOG(ERROR) << "Failed to remove org image";
850 return BackendInterface::CommandResult::ERROR;
853 bf::path db_path = tzplatform_getenv(TZ_SYS_DB);
854 bf::path app2sd_db = db_path / ".app2sd.db";
855 bf::path app2sd_db_journal = db_path / ".app2sd.db-journal";
856 bf::remove(app2sd_db, error);
858 LOG(ERROR) << "Failed to remove app2sd db";
859 return BackendInterface::CommandResult::ERROR;
861 bf::remove(app2sd_db_journal, error);
863 LOG(ERROR) << "Failed to remove app2sd journal db";
864 return BackendInterface::CommandResult::ERROR;
867 bf::path app2sd_migrate_db = legacy_path / kMigrateTestDBName;
868 if (!ci::CopyFile(app2sd_migrate_db, app2sd_db)) {
869 LOG(ERROR) << "Failed to copy test db";
870 return BackendInterface::CommandResult::ERROR;
873 bf::path legacy_src = legacy_path / pkgid;
874 bf::path legacy_dst = app2sd_path / pkgid;
875 if (!ci::CopyFile(legacy_src, legacy_dst)) {
876 LOG(ERROR) << "Failed to copy test image";
877 return BackendInterface::CommandResult::ERROR;
879 const char* argv[] = {"", "--migrate-extimg", pkgid.c_str(),
880 "-u", uid_str_.c_str()};
881 return CallBackend(SIZEOFARRAY(argv), argv);
884 BackendInterface::CommandResult BackendInterface::RDSUpdate(
885 const bf::path& path,
886 const std::string& pkgid) const {
887 RequestResult tmp_mode = mode_;
888 RequestResult &original_mode = const_cast<RequestResult&>(mode_);
889 original_mode = RequestResult::NORMAL;
890 if (Install(path) != BackendInterface::CommandResult::OK) {
891 LOG(ERROR) << "Failed to install application. Cannot perform RDS";
892 return BackendInterface::CommandResult::UNKNOWN;
894 const char* argv[] = {"", "-r", pkgid.c_str(), "-u",
896 original_mode = tmp_mode;
897 return CallBackend(SIZEOFARRAY(argv), argv);
900 BackendInterface::CommandResult BackendInterface::EnablePackage(
901 const std::string& pkgid) const {
902 const char* argv[] = {"", "-A", pkgid.c_str(), "-u", uid_str_.c_str()};
903 return CallBackend(SIZEOFARRAY(argv), argv);
906 BackendInterface::CommandResult BackendInterface::DisablePackage(
907 const std::string& pkgid) const {
908 const char* argv[] = {"", "-D", pkgid.c_str(), "-u", uid_str_.c_str()};
909 return CallBackend(SIZEOFARRAY(argv), argv);
912 BackendInterface::CommandResult BackendInterface::Recover(
913 const bf::path& recovery_file) const {
914 const char* argv[] = {"", "-b", recovery_file.c_str(), "-u",
916 return CallBackend(SIZEOFARRAY(argv), argv);
919 BackendInterface::CommandResult BackendInterface::ManifestDirectInstall(
920 const std::string& pkgid) const {
921 const char* argv[] = {"", "-y", pkgid.c_str(), "-u", uid_str_.c_str()};
922 return CallBackend(SIZEOFARRAY(argv), argv);
925 BackendInterface::CommandResult BackendInterface::Uninstall(
926 const std::string& pkgid) const {
927 const char* argv[] = {"", "-d", pkgid.c_str(), "-u", uid_str_.c_str()};
928 return CallBackend(SIZEOFARRAY(argv), argv);
931 BackendInterface::CommandResult BackendInterface::UninstallPreload(
932 const std::string& pkgid) const {
933 const char* argv[] = {"", "-d", pkgid.c_str(), "--preload",
935 return CallBackend(SIZEOFARRAY(argv), argv);
938 BackendInterface::CommandResult BackendInterface::InstallSuccess(
939 const bf::path& path) const {
940 RequestResult tmp_mode = mode_;
941 RequestResult &original_mode = const_cast<RequestResult&>(mode_);
942 original_mode = RequestResult::NORMAL;
943 if (Install(path) != BackendInterface::CommandResult::OK) {
944 LOG(ERROR) << "Failed to install application. Cannot update";
945 return BackendInterface::CommandResult::UNKNOWN;
947 original_mode = tmp_mode;
948 return BackendInterface::CommandResult::OK;
951 BackendInterface::CommandResult BackendInterface::InstallPreloadSuccess(
952 const bf::path& path) const {
953 RequestResult tmp_mode = mode_;
954 RequestResult &original_mode = const_cast<RequestResult&>(mode_);
955 original_mode = RequestResult::NORMAL;
956 if (InstallPreload(path) != BackendInterface::CommandResult::OK) {
957 LOG(ERROR) << "Failed to install application. Cannot update";
958 return BackendInterface::CommandResult::UNKNOWN;
960 original_mode = tmp_mode;
961 return BackendInterface::CommandResult::OK;
964 BackendInterface::CommandResult BackendInterface::MountInstall(
965 const bf::path& path) const {
966 const char* argv[] = {"", "-w", path.c_str(), "-u", uid_str_.c_str()};
967 return CallBackend(SIZEOFARRAY(argv), argv);
970 BackendInterface::CommandResult BackendInterface::MountInstallSuccess(
971 const bf::path& path) const {
972 RequestResult tmp_mode = mode_;
973 RequestResult &original_mode = const_cast<RequestResult&>(mode_);
974 original_mode = RequestResult::NORMAL;
975 if (MountInstall(path) != BackendInterface::CommandResult::OK) {
976 LOG(ERROR) << "Failed to mount-install application. Cannot mount-update";
977 return BackendInterface::CommandResult::UNKNOWN;
979 original_mode = tmp_mode;
980 return BackendInterface::CommandResult::OK;
983 static boost::filesystem::path GetTrashPath(
984 const boost::filesystem::path& path) {
985 return path.string() + ".trash";
988 SmokeTestHelperRunner::Result SmokeTestHelperRunner::RunSubprocess(
989 std::vector<std::string> args) const {
990 args.push_back("-remove_plugin_steps");
991 ci::Subprocess backend = CreateSubprocess();
992 backend.RunWithArgs(args);
993 int status = backend.Wait();
994 if (WIFEXITED(status)) {
995 if (WEXITSTATUS(status) == 0)
996 return SmokeTestHelperRunner::Result::SUCCESS;
998 return SmokeTestHelperRunner::Result::FAIL;
1000 return SmokeTestHelperRunner::Result::UnKnown;
1003 SmokeTestHelperRunner::Result SmokeTestHelperRunner::RunSubprocessAndKill(
1004 std::vector<std::string> args, useconds_t delay) const {
1005 args.push_back("-remove_plugin_steps");
1006 ci::Subprocess backend = CreateSubprocess();
1007 backend.RunWithArgs(args);
1010 int status = backend.Wait();
1011 if (WIFEXITED(status)) {
1012 if (WEXITSTATUS(status) == 0)
1013 return SmokeTestHelperRunner::Result::SUCCESS;
1015 return SmokeTestHelperRunner::Result::FAIL;
1017 if (WTERMSIG(status) == SIGKILL)
1018 return SmokeTestHelperRunner::Result::KILLED;
1020 return SmokeTestHelperRunner::Result::UnKnown;
1024 SmokeTestHelperRunner::Result SmokeTestHelperRunner::InstallWithSubprocess(
1025 const bf::path& path, uid_t uid) const {
1026 std::vector<std::string> args =
1027 { "-i", path.string(), "-u", std::to_string(uid) };
1028 return RunSubprocess(args);
1031 SmokeTestHelperRunner::Result SmokeTestHelperRunner::MountInstallWithSubprocess(
1032 const bf::path& path, uid_t uid) const {
1033 std::vector<std::string> args =
1034 { "-w", path.string(), "-u", std::to_string(uid) };
1035 return RunSubprocess(args);
1038 SmokeTestHelperRunner::Result SmokeTestHelperRunner::RecoveryWithSubprocess(
1039 const bf::path& path, uid_t uid) const {
1040 std::vector<std::string> args =
1041 { "-b", path.string(), "-u", std::to_string(uid) };
1042 return RunSubprocess(args);
1045 SmokeTestHelperRunner::Result SmokeTestHelperRunner::UninstallWithSubprocess(
1046 const std::string& pkgid, uid_t uid) const {
1047 std::vector<std::string> args = { "-d", pkgid, "-u", std::to_string(uid) };
1048 return RunSubprocess(args);
1051 SmokeTestHelperRunner::Result
1052 SmokeTestHelperRunner::InstallWithSubprocessAndKill(
1053 const bf::path& path, uid_t uid, useconds_t delay) const {
1054 std::vector<std::string> args =
1055 { "-i", path.string(), "-u", std::to_string(uid) };
1056 return RunSubprocessAndKill(args, delay);
1059 SmokeTestHelperRunner::Result
1060 SmokeTestHelperRunner::MountInstallWithSubprocessAndKill(
1061 const bf::path& path, uid_t uid, useconds_t delay) const {
1062 std::vector<std::string> args =
1063 { "-w", path.string(), "-u", std::to_string(uid) };
1064 return RunSubprocessAndKill(args, delay);
1067 SmokeTestHelperRunner::Result
1068 SmokeTestHelperRunner::UninstallWithSubprocessAndKill(
1069 const std::string& pkgid, uid_t uid, useconds_t delay) const {
1070 std::vector<std::string> args =
1071 { "-d", pkgid, "-u", std::to_string(uid) };
1072 return RunSubprocessAndKill(args, delay);
1075 SmokeTestHelperRunner::Result SmokeTestHelperRunner::InstallPkgsWithSubprocess(
1076 const std::vector<bf::path>& paths, uid_t uid) const {
1077 std::vector<std::string> args;
1078 args.emplace_back("-i");
1079 for (const bf::path& p : paths)
1080 args.emplace_back(p.string());
1081 args.emplace_back("-u");
1082 args.emplace_back(std::to_string(uid));
1083 return RunSubprocess(args);
1086 SmokeTestHelperRunner::Result
1087 SmokeTestHelperRunner::MountInstallPkgsWithSubprocess(
1088 const std::vector<bf::path>& paths, uid_t uid) const {
1089 std::vector<std::string> args;
1090 args.emplace_back("-w");
1091 for (const bf::path& p : paths)
1092 args.emplace_back(p.string());
1093 args.emplace_back("-u");
1094 args.emplace_back(std::to_string(uid));
1095 return RunSubprocess(args);
1098 SmokeTestHelperRunner::Result SmokeTestHelperRunner::RecoveryPkgsWithSubprocess(
1099 const std::vector<bf::path>& paths, uid_t uid) const {
1100 std::vector<std::string> args;
1101 args.emplace_back("-b");
1102 for (const bf::path& p : paths)
1103 args.emplace_back(p.string());
1104 args.emplace_back("-u");
1105 args.emplace_back(std::to_string(uid));
1106 return RunSubprocess(args);
1109 SmokeTestHelperRunner::Result
1110 SmokeTestHelperRunner::UninstallPkgsWithSubprocess(
1111 const std::vector<std::string>& pkgids, uid_t uid) const {
1112 std::vector<std::string> args;
1113 args.emplace_back("-d");
1114 args.insert(args.end(), pkgids.begin(), pkgids.end());
1115 args.emplace_back("-u");
1116 args.emplace_back(std::to_string(uid));
1117 return RunSubprocess(args);
1120 SmokeTestHelperRunner::Result
1121 SmokeTestHelperRunner::InstallPkgsWithSubprocessAndKill(
1122 const std::vector<bf::path>& paths, uid_t uid, useconds_t delay) const {
1123 std::vector<std::string> args;
1124 args.emplace_back("-i");
1125 for (const bf::path& p : paths)
1126 args.emplace_back(p.string());
1127 args.emplace_back("-u");
1128 args.emplace_back(std::to_string(uid));
1129 return RunSubprocessAndKill(args, delay);
1132 SmokeTestHelperRunner::Result
1133 SmokeTestHelperRunner::MountInstallPkgsWithSubprocessAndKill(
1134 const std::vector<bf::path>& paths, uid_t uid, useconds_t delay) const {
1135 std::vector<std::string> args;
1136 args.emplace_back("-w");
1137 for (const bf::path& p : paths)
1138 args.emplace_back(p.string());
1139 args.emplace_back("-u");
1140 args.emplace_back(std::to_string(uid));
1141 return RunSubprocessAndKill(args, delay);
1144 bool CopySmackAccess(const boost::filesystem::path& src,
1145 const boost::filesystem::path& dst) {
1146 if (!bf::exists(src) && !bf::is_symlink(src)) {
1147 LOG(ERROR) << "Failed to copy smack access label";
1151 char* access_label = nullptr;
1152 ret = smack_lgetlabel(src.c_str(), &access_label, SMACK_LABEL_ACCESS);
1154 LOG(ERROR) << "get access label from [" << src << "] fail";
1159 ret = smack_lsetlabel(dst.c_str(), access_label, SMACK_LABEL_ACCESS);
1162 LOG(ERROR) << "set access label to [" << dst << "] fail";
1168 bool CopySmackExec(const boost::filesystem::path& src,
1169 const boost::filesystem::path& dst) {
1170 if (!bf::exists(src) && !bf::is_symlink(src)) {
1171 LOG(ERROR) << "Failed to copy smack exec label";
1175 char *exec_label = nullptr;
1176 ret = smack_lgetlabel(src.c_str(), &exec_label, SMACK_LABEL_EXEC);
1178 LOG(ERROR) << "get exec label from [" << src << "] fail";
1183 ret = smack_lsetlabel(dst.c_str(), exec_label, SMACK_LABEL_EXEC);
1186 LOG(ERROR) << "set exec label to [" << dst << "] fail";
1192 bool CopySmackMmap(const boost::filesystem::path& src,
1193 const boost::filesystem::path& dst) {
1194 if (!bf::exists(src) && !bf::is_symlink(src)) {
1195 LOG(ERROR) << "Failed to copy smack mmap label";
1199 char *mmap_label = nullptr;
1200 ret = smack_lgetlabel(src.c_str(), &mmap_label, SMACK_LABEL_MMAP);
1202 LOG(ERROR) << "get mmap label from [" << src << "] fail";
1207 ret = smack_lsetlabel(dst.c_str(), mmap_label, SMACK_LABEL_MMAP);
1210 LOG(ERROR) << "set mmap label to [" << dst << "] fail";
1216 bool CopySmackTransmute(const boost::filesystem::path& src,
1217 const boost::filesystem::path& dst) {
1218 if (!bf::exists(src)) {
1219 LOG(ERROR) << "Failed to copy smack tranmute label";
1223 char *transmute_label = nullptr;
1224 ret = smack_lgetlabel(src.c_str(), &transmute_label, SMACK_LABEL_TRANSMUTE);
1226 LOG(ERROR) << "get access label from [" << src << "] fail";
1229 if (!transmute_label) {
1230 ret = smack_lsetlabel(dst.c_str(), "0", SMACK_LABEL_TRANSMUTE);
1232 if (strcmp(transmute_label, "TRUE") == 0)
1233 ret = smack_lsetlabel(dst.c_str(), "1", SMACK_LABEL_TRANSMUTE);
1235 ret = smack_lsetlabel(dst.c_str(), "0", SMACK_LABEL_TRANSMUTE);
1236 free(transmute_label);
1238 LOG(ERROR) << "set access label to [" << dst << "] fail";
1246 bool CopySmackLabels(const boost::filesystem::path& src,
1247 const boost::filesystem::path& dst) {
1248 if (!CopySmackAccess(src, dst))
1250 if (!CopySmackExec(src, dst))
1252 if (!CopySmackMmap(src, dst))
1254 if (!bf::is_symlink(src) && bf::is_directory(src)) {
1255 if (!CopySmackTransmute(src, dst))
1261 bool CopyAndRemoveWithSmack(const bf::path& src, const bf::path& dst) {
1262 bs::error_code error;
1263 if (bf::exists(dst)) {
1265 bf::remove_all(dst, error);
1267 std::cout << "Exception occurred during remove [" << dst.string()
1268 << "], and skip this file"<< std::endl;
1271 if (!bf::is_directory(dst)) {
1272 LOG(ERROR) << "remove_all fail";
1278 if (bf::is_symlink(src)) {
1279 bf::copy_symlink(src, dst, error);
1281 LOG(ERROR) << "Failed to copy symlink: " << src << ", "
1285 if (!CopySmackLabels(src, dst)) {
1286 LOG(ERROR) << "copy smack label from [" << src.string()
1287 << "] to [" << dst.string() << "] fail";
1290 } else if (bf::is_directory(src)) {
1291 if (!bf::exists(dst)) {
1292 bf::create_directories(dst, error);
1294 LOG(ERROR) << "create directories fail";
1297 ci::CopyOwnershipAndPermissions(src, dst);
1298 if (!CopySmackLabels(src, dst)) {
1299 LOG(ERROR) << "copy smack label from [" << src.string()
1300 << "] to [" << dst.string() << "] fail";
1304 bool success = true;
1305 for (bf::directory_iterator file(src);
1306 file != bf::directory_iterator();
1308 bf::path current(file->path());
1309 bf::path target = dst / current.filename();
1310 success &= CopyAndRemoveWithSmack(current, target);
1312 bf::remove_all(src);
1316 bf::copy_file(src, dst);
1317 ci::CopyOwnershipAndPermissions(src, dst);
1318 if (!CopySmackLabels(src, dst)) {
1319 LOG(ERROR) << "copy smack label from [" << src.string()
1320 << "] to [" << dst.string() << "] fail";
1323 bf::remove_all(src);
1326 std::cout << "Exception occurred during copy [" << src.string()
1327 << "], and skip this file"<< std::endl;
1334 bool BackupPathCopyAndRemove(const bf::path& path) {
1335 if (!bf::exists(path))
1338 bf::path backup_path = path.string() + ".bck";
1339 std::cout << "Backup path: " << path << " to " << backup_path << std::endl;
1340 if (!CopyAndRemoveWithSmack(path, backup_path)) {
1341 LOG(ERROR) << "Failed to setup test environment. Does some previous"
1342 << " test crashed? Path: "
1343 << backup_path << " should not exist.";
1349 bool BackupPath(const bf::path& path) {
1350 bf::path trash_path = GetTrashPath(path);
1351 if (bf::exists(trash_path)) {
1352 LOG(ERROR) << trash_path << " exists. Please remove "
1353 << trash_path << " manually!";
1356 bf::path backup_path = path.string() + ".bck";
1357 std::cout << "Backup path: " << path << " to " << backup_path << std::endl;
1358 bs::error_code error;
1359 bf::remove_all(backup_path, error);
1361 LOG(ERROR) << "Remove failed: " << backup_path
1362 << " (" << error.message() << ")";
1363 if (bf::exists(path)) {
1364 bf::rename(path, backup_path, error);
1366 LOG(ERROR) << "Failed to setup test environment. Does some previous"
1367 << " test crashed? Path: "
1368 << backup_path << " should not exist.";
1372 if (bf::is_directory(backup_path))
1373 bf::create_directory(path);
1378 bool RestorePathCopyAndRemove(const bf::path& path) {
1379 bf::path backup_path = path.string() + ".bck";
1380 if (!bf::exists(backup_path))
1383 std::cout << "Restore path: " << path << " from " << backup_path << std::endl;
1384 if (!CopyAndRemoveWithSmack(backup_path, path)) {
1385 LOG(ERROR) << "Failed to restore backup path: " << backup_path;
1391 bool RestorePath(const bf::path& path) {
1392 bf::path backup_path = path.string() + ".bck";
1393 std::cout << "Restore path: " << path << " from " << backup_path << std::endl;
1394 bs::error_code error;
1395 bf::remove_all(path, error);
1397 bf::path trash_path = GetTrashPath(path);
1398 LOG(ERROR) << "Remove failed: " << path << " (" << error.message() << ")";
1399 std::cout << "Moving " << path << " to " << trash_path << std::endl;
1400 bf::rename(path, trash_path, error);
1402 LOG(ERROR) << "Failed to move " << path << " to " << trash_path
1403 << " (" << error.message() << ")";
1405 LOG(ERROR) << trash_path << " should be removed manually!";
1407 if (bf::exists(backup_path)) {
1408 bf::rename(backup_path, path, error);
1410 LOG(ERROR) << "Failed to restore backup path: " << backup_path
1411 << " (" << error.message() << ")";
1418 std::vector<bf::path> SetupBackupDirectories(uid_t test_uid) {
1419 std::vector<bf::path> entries;
1420 bf::path db_dir = bf::path(tzplatform_getenv(TZ_SYS_DB));
1421 if (test_uid != kGlobalUserUid)
1422 db_dir = db_dir / "user" / std::to_string(test_uid);
1423 for (auto e : kDBEntries) {
1424 bf::path path = db_dir / e;
1425 entries.emplace_back(path);
1428 if (getuid() == 0) {
1429 entries.emplace_back(kPreloadApps);
1430 entries.emplace_back(kPreloadManifestDir);
1431 entries.emplace_back(kPreloadIcons);
1434 if (test_uid == kGlobalUserUid) {
1435 entries.emplace_back(kSkelDir);
1436 entries.emplace_back(kGlobalManifestDir);
1437 ci::UserList list = ci::GetUserList();
1438 for (auto l : list) {
1439 bf::path apps = std::get<2>(l) / "apps_rw";
1440 entries.emplace_back(apps);
1443 tzplatform_set_user(test_uid);
1444 bf::path approot = tzplatform_getenv(TZ_USER_APPROOT);
1445 tzplatform_reset_user();
1446 entries.emplace_back(approot);
1449 bf::path apps_rw = ci::GetRootAppPath(false, test_uid);
1450 entries.emplace_back(apps_rw);
1451 entries.emplace_back(kSdkDirectory);
1456 void UninstallAllAppsInDirectory(bf::path dir, bool is_preload,
1457 BackendInterface* backend) {
1458 if (bf::exists(dir)) {
1459 for (auto& dir_entry : boost::make_iterator_range(
1460 bf::directory_iterator(dir), bf::directory_iterator())) {
1461 if (dir_entry.path().string().find("smoke") != std::string::npos &&
1462 bf::is_directory(dir_entry)) {
1463 std::string package = dir_entry.path().filename().string();
1464 std::regex pkg_regex("smoke[a-zA-Z0-9]{5,}");
1465 if (std::regex_match(package, pkg_regex)) {
1466 BackendInterface::CommandResult result =
1467 BackendInterface::CommandResult::OK;
1469 result = backend->UninstallPreload(
1470 dir_entry.path().filename().string());
1472 result = backend->Uninstall(
1473 dir_entry.path().filename().string());
1474 if (result != BackendInterface::CommandResult::OK) {
1475 LOG(ERROR) << "Cannot uninstall smoke test app: "
1476 << dir_entry.path().filename().string();
1484 void UninstallAllSmokeApps(ci::RequestMode request_mode, uid_t test_uid,
1485 BackendInterface *backend) {
1486 std::cout << "Uninstalling all smoke apps" << std::endl;
1487 bf::path apps_rw = ci::GetRootAppPath(false, test_uid);
1488 UninstallAllAppsInDirectory(apps_rw, false, backend);
1489 if (getuid() == 0 && request_mode == ci::RequestMode::GLOBAL) {
1490 bf::path root_path = kPreloadApps;
1491 UninstallAllAppsInDirectory(root_path, true, backend);
1495 int GetAppInstalledTime(const char* appid, uid_t uid) {
1497 int installed_time = 0;
1498 pkgmgrinfo_appinfo_h handle = NULL;
1499 ret = pkgmgrinfo_appinfo_get_usr_appinfo(appid, uid, &handle);
1500 if (ret != PMINFO_R_OK)
1502 ret = pkgmgrinfo_appinfo_get_installed_time(handle, &installed_time);
1503 if (ret != PMINFO_R_OK) {
1504 pkgmgrinfo_appinfo_destroy_appinfo(handle);
1507 pkgmgrinfo_appinfo_destroy_appinfo(handle);
1508 return installed_time;
1511 } // namespace smoke_test