Remove boost dependency
[platform/core/appfw/app-installers.git] / test / smoke_tests / common / smoke_utils.cc
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.
4
5 #include "smoke_tests/common/smoke_utils.h"
6
7 #include <getopt.h>
8 #include <gum/gum-user.h>
9 #include <gum/gum-user-service.h>
10 #include <gum/common/gum-user-types.h>
11 #include <manifest_parser/utils/version_number.h>
12 #include <sys/smack.h>
13 #include <unistd.h>
14 #include <vconf.h>
15 #include <vconf-internal-keys.h>
16
17 #include <gtest/gtest.h>
18
19 #include <common/installer/app_installer.h>
20 #include <common/utils/paths.h>
21 #include <common/pkgmgr_interface.h>
22 #include <common/utils/pkgmgr_query.h>
23 #include <common/tzip_interface.h>
24
25 #include "pkgmgr_parser_db.h"
26
27 #include <filesystem>
28 #include <fstream>
29 #include <list>
30 #include <memory>
31 #include <sstream>
32 #include <string>
33 #include <system_error>
34 #include <vector>
35
36 namespace ci = common_installer;
37 namespace fs = std::filesystem;
38
39 namespace {
40
41 const uid_t kDefaultUserUid = tzplatform_getuid(TZ_SYS_DEFAULT_USER);
42 const gid_t kDefaultUserGid = tzplatform_getgid(TZ_SYS_DEFAULT_USER);
43 const char kNormalUserName[] = "smokeuser";
44 const char kSystemShareGroupName[] = "system_share";
45 const char kMigrateTestDBName[] = "app2sd_migrate.db";
46 // common entries
47 const std::vector<std::string> kDBEntries = {
48   {".pkgmgr_parser.db"},
49   {".pkgmgr_parser.db-journal"},
50   {".pkgmgr_cert.db"},
51   {".pkgmgr_cert.db-journal"},
52   {".app2sd.db"},
53   {".app2sd.db-journal"},
54 };
55 // globaluser entries
56 const char kGlobalManifestDir[] = "/opt/share/packages";
57 const char kSkelDir[] = "/etc/skel/apps_rw";
58 const char kPreloadApps[] = "/usr/apps";
59 const char kPreloadManifestDir[] = "/usr/share/packages";
60 const char kPreloadIcons[] = "/usr/share/icons";
61 const char kData[] = "data";
62 const char kShared[] = ".shared";
63 const char kSharedTmp[] = ".shared_tmp";
64
65 enum RWDirectory {
66   DATA,
67   CACHE,
68   SHARED_CACHE,
69   SHARED_DATA,
70   SHARED_TRUSTED
71 };
72
73 const char* rwDirectories[] = {
74   "data",
75   "cache",
76   "shared/cache",
77   "shared/data",
78   "shared/trusted",
79 };
80
81 }  // namespace
82
83 namespace smoke_test {
84
85 const char kLegacyExtImageDir[] = "legacy_extimage_dir";
86 const std::string& kDefaultUserIdStr = std::to_string(kDefaultUserUid);
87 const uid_t kGlobalUserUid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
88 const uid_t kGlobalUserGid = tzplatform_getgid(TZ_SYS_GLOBALAPP_USER);
89 extern const fs::path kSdkDirectory = "/home/owner/share/tmp/sdk_tools";
90
91 ci::RequestMode ParseRequestMode(int argc,  char** argv) {
92   const struct option long_opts[] = {
93     { "request-mode", required_argument, nullptr, 'r' },
94     { "global-request", no_argument, nullptr, 'g' },
95     { "user-request", no_argument, nullptr, 'u' },
96     { 0, 0, 0, 0 }
97   };
98
99   std::string request_mode;
100   bool is_global_request = false;
101   bool is_user_request = false;
102   while (true) {
103     int opt = getopt_long(argc, argv, "gu", long_opts, nullptr);
104     if (opt == -1)
105       break;
106
107     switch (opt) {
108       case 'r':
109         if (optarg)
110           request_mode = optarg;
111         break;
112       case 'g':
113         is_global_request = true;
114         break;
115       case 'u':
116         is_user_request = true;
117         break;
118       default:
119         break;
120     }
121   }
122
123   if (is_global_request) {
124     std::cout << "Request mode was set to global." << std::endl;
125     return ci::RequestMode::GLOBAL;
126   }
127   if (is_user_request) {
128     std::cout << "Request mode was set to user." << std::endl;
129     return ci::RequestMode::USER;
130   }
131   if (!request_mode.empty()) {
132     if (request_mode.compare("global") == 0) {
133       std::cout << "Request mode was set to global." << std::endl;
134       return ci::RequestMode::GLOBAL;
135     }
136     if (request_mode.compare("user") == 0) {
137       std::cout << "Request mode was set to user." << std::endl;
138       return ci::RequestMode::USER;
139     }
140     std::cout << "Cannot set request mode to "
141               << request_mode << std::endl;
142   }
143   std::cout << "Request mode was set to global." << std::endl;
144   return ci::RequestMode::GLOBAL;
145 }
146
147 static bool AddUser(const char* user_name) {
148   GumUser* user = nullptr;
149   user = gum_user_create_sync(FALSE);
150   if (user == nullptr)
151     LOG(WARNING) << "Failed to create gum user! (user name: "
152                  << user_name << ")";
153   g_object_set(G_OBJECT(user), "username", user_name, "usertype",
154       GUM_USERTYPE_NORMAL, NULL);
155   gboolean rval = FALSE;
156   rval = gum_user_add_sync(user);
157   g_object_unref(user);
158   return rval;
159 }
160
161 static bool DeleteUser(const char* user_name, bool rem_home_dir) {
162   bool rval = FALSE;
163   GumUser* guser = gum_user_get_by_name_sync(user_name, FALSE);
164   if (guser)
165     rval = gum_user_delete_sync(guser, rem_home_dir);
166   return rval;
167 }
168
169 bool AddTestUser(User* test_user) {
170   std::cout << "Adding test user: " << kNormalUserName << std::endl;
171   AddUser(kNormalUserName);
172   if (std::optional<uid_t> uid = ci::GetUidByUserName(kNormalUserName)) {
173     test_user->uid = *uid;
174     std::cout << "User created properly: uid=" << *uid;
175     if (std::optional<gid_t> gid = ci::GetGidByUid(*uid)) {
176       test_user->gid = *gid;
177       std::cout << " gid=" << *gid;
178     }
179     std::cout << std::endl;
180     return true;
181   }
182   LOG(ERROR) << "Adding test user failed";
183   return false;
184 }
185
186 bool DeleteTestUser() {
187   std::cout << "Deleting test user: " << kNormalUserName << std::endl;
188   uid_t test_uid;
189   if (std::optional<uid_t> uid = ci::GetUidByUserName(kNormalUserName))
190     test_uid = *uid;
191   else
192     return false;
193   DeleteUser(kNormalUserName, true);
194   if (!ci::GetUidByUserName(kNormalUserName)) {
195     std::cout << "User deleted properly: user_name=" << kNormalUserName
196               << " uid=" << test_uid << std::endl;
197     return true;
198   }
199   LOG(ERROR) << "Deleting test user failed";
200   return false;
201 }
202
203 bool TouchFile(const fs::path& path) {
204   FILE* f = fopen(path.c_str(), "w+");
205   if (!f)
206     return false;
207   fclose(f);
208   return true;
209 }
210
211 void AddDataFiles(const std::string& pkgid, uid_t uid,
212     std::vector<fs::path>* result) {
213   std::vector<fs::path> files;
214   files.clear();
215   if (uid == kGlobalUserUid) {
216     ci::UserList list = ci::GetUserList();
217     for (auto l : list) {
218       auto pkg_path = GetPackageRoot(pkgid, std::get<0>(l));
219       files.emplace_back(pkg_path / "data" / "file1.txt");
220       files.emplace_back(pkg_path / "data" / "file2.txt");
221     }
222   } else {
223     auto pkg_path = GetPackageRoot(pkgid, uid);
224     files.emplace_back(pkg_path / "data" / "file1.txt");
225     files.emplace_back(pkg_path / "data" / "file2.txt");
226   }
227
228   for (const auto& path : files)
229     ASSERT_TRUE(TouchFile(path));
230
231   if (result)
232     *result = std::move(files);
233 }
234
235 void RemoveAllRecoveryFiles(const std::string& prefix, uid_t uid) {
236   fs::path root_path = ci::GetRootAppPath(false, uid);
237   if (!fs::exists(root_path))
238     return;
239   for (auto& dir_entry : fs::directory_iterator(root_path)) {
240     if (fs::is_regular_file(dir_entry)) {
241       if (dir_entry.path().string().find(prefix) != std::string::npos) {
242         std::error_code error;
243         fs::remove(dir_entry, error);
244         if (error)
245           LOG(ERROR) << "Failed to remove " << dir_entry
246                      << ": " << error.message();
247       }
248     }
249   }
250 }
251
252 fs::path FindRecoveryFile(const std::string& prefix, uid_t uid) {
253   fs::path root_path = ci::GetRootAppPath(false, uid);
254   if (!fs::exists(root_path))
255     return {};
256
257   for (auto& dir_entry : fs::directory_iterator(root_path)) {
258     if (fs::is_regular_file(dir_entry)) {
259       if (dir_entry.path().string().find(prefix) != std::string::npos) {
260         return dir_entry;
261       }
262     }
263   }
264   return {};
265 }
266
267 std::unique_ptr<ci::recovery::RecoveryFile> GetRecoverFileInfo(
268     const fs::path& recovery_file_path) {
269   return ci::recovery::RecoveryFile::OpenRecoveryFile(recovery_file_path);
270 }
271
272 fs::path GetPackageRoot(const std::string& pkgid, uid_t uid) {
273   fs::path root_path = ci::GetRootAppPath(false, uid);
274   return root_path / pkgid;
275 }
276
277 bool ValidateFileContentInPackage(const std::string& pkgid,
278                                   const std::string& relative,
279                                   const std::string& expected,
280                                   const TestParameters& params) {
281   fs::path file_path = ci::GetRootAppPath(params.is_readonly,
282                                           params.test_user.uid);
283   file_path = file_path / pkgid / relative;
284   if (!fs::exists(file_path)) {
285     LOG(ERROR) << file_path << " doesn't exist";
286     return false;
287   }
288   FILE* handle = fopen(file_path.c_str(), "r");
289   if (!handle) {
290     LOG(ERROR) << file_path << " cannot be open";
291     return false;
292   }
293   std::string content;
294   std::array<char, 200> buffer;
295   while (fgets(buffer.data(), buffer.size(), handle)) {
296     content += buffer.data();
297   }
298   fclose(handle);
299   return content == expected;
300 }
301
302 static bool ValidatePackageRWFS(const std::string& pkgid, uid_t uid) {
303   fs::path root_path = ci::GetRootAppPath(false, uid);
304   fs::path package_path = root_path / pkgid;
305   fs::path data_path = package_path / rwDirectories[DATA];
306   fs::path cache_path = package_path / rwDirectories[CACHE];
307   fs::path shared_data_path = package_path / rwDirectories[SHARED_DATA];
308
309   EXTENDED_ASSERT_TRUE(fs::exists(data_path));
310   EXTENDED_ASSERT_TRUE(fs::exists(cache_path));
311
312   struct stat stats;
313   stat(data_path.c_str(), &stats);
314   // gid of RW dirs should be system_share
315   std::optional<gid_t> system_share =
316       ci::GetGidByGroupName(kSystemShareGroupName);
317   EXTENDED_ASSERT_EQ(uid, stats.st_uid);
318   EXTENDED_ASSERT_EQ(*system_share, stats.st_gid);
319   if (fs::exists(shared_data_path)) {
320     stat(shared_data_path.c_str(), &stats);
321     EXTENDED_ASSERT_EQ(uid, stats.st_uid);
322     EXTENDED_ASSERT_EQ(*system_share, stats.st_gid);
323   }
324
325   stat(cache_path.c_str(), &stats);
326   EXTENDED_ASSERT_EQ(uid, stats.st_uid);
327   EXTENDED_ASSERT_EQ(*system_share, stats.st_gid);
328   return true;
329 }
330
331 static bool ValidatePackageFS(const std::string& pkgid, const Apps& apps,
332     const TestParameters& params) {
333   fs::path root_path = ci::GetRootAppPath(params.is_readonly,
334                                           params.test_user.uid);
335   fs::path package_path = root_path / pkgid;
336   fs::path shared_path = package_path / "shared";
337   EXTENDED_ASSERT_TRUE(fs::exists(root_path));
338   EXTENDED_ASSERT_TRUE(fs::exists(package_path));
339   EXTENDED_ASSERT_TRUE(fs::exists(shared_path));
340
341   fs::path manifest_path =
342       fs::path(getUserManifestPath(params.test_user.uid,
343           params.is_readonly)) / (pkgid + ".xml");
344   EXTENDED_ASSERT_TRUE(fs::exists(manifest_path));
345
346   for (auto& app : apps) {
347     const std::string &exec = app.second;
348     fs::path binary_path = package_path / "bin" / exec;
349     EXTENDED_ASSERT_TRUE(fs::exists(binary_path));
350   }
351
352   if (params.pkg_type == PackageType::WGT ||
353       params.pkg_type == PackageType::HYBRID) {
354     fs::path widget_root_path = package_path / "res" / "wgt";
355     fs::path config_path = widget_root_path / "config.xml";
356     EXTENDED_ASSERT_TRUE(fs::exists(widget_root_path));
357     EXTENDED_ASSERT_TRUE(fs::exists(config_path));
358
359     fs::path private_tmp_path = package_path / "tmp";
360     EXTENDED_ASSERT_TRUE(fs::exists(private_tmp_path));
361   }
362
363   // backups should not exist
364   fs::path package_backup = ci::GetBackupPathForPackagePath(package_path);
365   fs::path manifest_backup = ci::GetBackupPathForManifestFile(manifest_path);
366   EXTENDED_ASSERT_FALSE(fs::exists(package_backup));
367   EXTENDED_ASSERT_FALSE(fs::exists(manifest_backup));
368
369   for (fs::recursive_directory_iterator iter(package_path);
370       iter != fs::recursive_directory_iterator(); ++iter) {
371     if (fs::is_symlink(symlink_status(iter->path())))
372       continue;
373     bool is_rw_dir = false;
374     for (const auto rw_dir : rwDirectories) {
375       fs::path rw_dir_path = rw_dir;
376       is_rw_dir |= ci::MakeRelativePath(iter->path(), package_path)
377           == rw_dir_path;
378     }
379     if (is_rw_dir || iter->path().filename() == ".mmc") {
380       iter.disable_recursion_pending();
381       continue;
382     }
383     struct stat stats;
384     stat(iter->path().c_str(), &stats);
385     EXTENDED_ASSERT_EQ(params.test_user.uid, stats.st_uid);
386     EXTENDED_ASSERT_EQ(params.test_user.gid, stats.st_gid);
387   }
388   return true;
389 }
390
391 bool ValidatePackage(const std::string& pkgid, const Apps& apps,
392     const TestParameters& params) {
393   ci::PkgQueryInterface pkg_query(pkgid, params.test_user.uid, true);
394   EXTENDED_ASSERT_TRUE(pkg_query.IsPackageInstalled(
395       ci::GetRequestMode(params.test_user.uid)));
396   EXTENDED_ASSERT_TRUE(ValidatePackageFS(pkgid, apps, params));
397   if (params.test_user.uid == kGlobalUserUid) {
398     ci::UserList list = ci::GetUserList();
399     for (auto& l : list)
400       EXTENDED_ASSERT_TRUE(ValidatePackageRWFS(pkgid, std::get<0>(l)));
401   } else {
402     EXTENDED_ASSERT_TRUE(ValidatePackageRWFS(pkgid, params.test_user.uid));
403   }
404   return true;
405 }
406
407 bool ValidateDataFiles(const std::string& pkgid, uid_t uid) {
408   if (uid == kGlobalUserUid) {
409     ci::UserList list = ci::GetUserList();
410     for (auto l : list) {
411       auto pkg_path = GetPackageRoot(pkgid, std::get<0>(l));
412       EXTENDED_ASSERT_TRUE(fs::exists(pkg_path / "data" / "file1.txt"));
413       EXTENDED_ASSERT_TRUE(fs::exists(pkg_path / "data" / "file2.txt"));
414     }
415   } else {
416     auto pkg_path = GetPackageRoot(pkgid, uid);
417     EXTENDED_ASSERT_TRUE(fs::exists(pkg_path / "data" / "file1.txt"));
418     EXTENDED_ASSERT_TRUE(fs::exists(pkg_path / "data" / "file2.txt"));
419   }
420   return true;
421 }
422
423 static bool ValidateExternalPackageFS(const std::string& pkgid,
424     const Apps& apps, const TestParameters& params) {
425   EXTENDED_ASSERT_EQ(app2ext_usr_enable_external_pkg(pkgid.c_str(),
426       params.test_user.uid), 0);
427   fs::path root_path = ci::GetRootAppPath(false, params.test_user.uid);
428   if (params.pkg_type == PackageType::TPK) {
429     EXTENDED_ASSERT_TRUE(fs::exists(root_path / pkgid / ".mmc" / "bin"));
430     EXTENDED_ASSERT_TRUE(fs::exists(root_path / pkgid / ".mmc" / "lib"));
431   }
432   EXTENDED_ASSERT_TRUE(fs::exists(root_path / pkgid / ".mmc" / "res"));
433   EXTENDED_ASSERT_TRUE(ValidatePackageFS(pkgid, apps, params));
434   EXTENDED_ASSERT_EQ(app2ext_usr_disable_external_pkg(pkgid.c_str(),
435       params.test_user.uid), 0);
436   return true;
437 }
438
439 bool ValidateExternalPackage(const std::string& pkgid, const Apps& apps,
440     const TestParameters& params) {
441   ci::PkgQueryInterface pkg_query(pkgid, params.test_user.uid, true);
442   std::string storage = pkg_query.StorageForPkgId();
443   fs::path ext_mount_path = ci::GetExternalCardPath();
444   if (fs::is_empty(ext_mount_path)) {
445     LOG(INFO) << "Sdcard not exists!";
446     EXTENDED_ASSERT_EQ(storage, "installed_internal");
447   } else {
448     EXTENDED_ASSERT_EQ(storage, "installed_external");
449   }
450   EXTENDED_ASSERT_TRUE(ValidateExternalPackageFS(pkgid, apps, params));
451   return true;
452 }
453
454 bool ValidateExtendedPackage(const std::string& pkgid, const Apps& apps,
455     const TestParameters& params) {
456   ci::PkgQueryInterface pkg_query(pkgid, params.test_user.uid, true);
457   std::string storage = pkg_query.StorageForPkgId();
458   fs::path extended_path =
459       fs::path(ci::GetExtendedRootAppPath(params.test_user.uid)) / pkgid;
460   if (!fs::exists(extended_path)) {
461     LOG(INFO) << "Extended storage not exists!";
462     EXTENDED_ASSERT_EQ(storage, "installed_internal");
463   } else {
464     EXTENDED_ASSERT_EQ(storage, "installed_extended");
465   }
466   EXTENDED_ASSERT_TRUE(ValidatePackage(pkgid, apps, params));
467   return true;
468 }
469
470 static bool PackageCheckCleanup(const std::string& pkgid,
471     const TestParameters& params) {
472   fs::path root_path = ci::GetRootAppPath(params.is_readonly,
473                                           params.test_user.uid);
474   fs::path package_path = root_path / pkgid;
475   EXTENDED_ASSERT_FALSE(fs::exists(package_path));
476
477   fs::path manifest_path = fs::path(getUserManifestPath(params.test_user.uid,
478       params.is_readonly)) / (pkgid + ".xml");
479   EXTENDED_ASSERT_FALSE(fs::exists(manifest_path));
480
481   // backups should not exist
482   fs::path package_backup = ci::GetBackupPathForPackagePath(package_path);
483   fs::path manifest_backup = ci::GetBackupPathForManifestFile(manifest_path);
484   EXTENDED_ASSERT_FALSE(fs::exists(package_backup));
485   EXTENDED_ASSERT_FALSE(fs::exists(manifest_backup));
486   return true;
487 }
488
489 bool CheckPackageNonExistance(const std::string& pkgid,
490                               const TestParameters& params) {
491   ci::PkgQueryInterface pkg_query(pkgid, params.test_user.uid, true);
492   EXTENDED_ASSERT_FALSE(pkg_query.IsPackageInstalled(
493       ci::GetRequestMode(params.test_user.uid)));
494   EXTENDED_ASSERT_TRUE(PackageCheckCleanup(pkgid, params));
495   if (params.test_user.uid == kGlobalUserUid) {
496     fs::path skel_path(kSkelDir);
497     EXTENDED_ASSERT_FALSE(fs::exists(skel_path / pkgid));
498     EXTENDED_ASSERT_FALSE(fs::exists(skel_path / kShared / pkgid));
499     EXTENDED_ASSERT_FALSE(fs::exists(skel_path / kSharedTmp / pkgid));
500     ci::UserList list = ci::GetUserList();
501     for (auto& l : list) {
502       fs::path root_path = ci::GetRootAppPath(false, std::get<0>(l));
503       EXTENDED_ASSERT_FALSE(fs::exists(root_path / kShared / pkgid));
504       EXTENDED_ASSERT_FALSE(fs::exists(root_path / kSharedTmp / pkgid));
505       fs::path package_path = root_path / pkgid;
506       EXTENDED_ASSERT_FALSE(fs::exists(package_path));
507     }
508   }
509   return true;
510 }
511
512 bool CheckAvailableExternalPath() {
513   fs::path ext_mount_path = ci::GetExternalCardPath();
514   LOG(DEBUG) << "ext_mount_path :" << ext_mount_path;
515   if (ext_mount_path.empty()) {
516     LOG(ERROR) << "Sdcard not exists!";
517     return false;
518   }
519   return true;
520 }
521
522 bool CheckAvailableExtendedPath() {
523   fs::path extended_path = fs::path(tzplatform_getenv(TZ_SYS_EXTENDEDSD));
524   LOG(DEBUG) << "extended_path :" << extended_path;
525   // TODO(jeremy.jang): It should be checked by libstorage API.
526   if (!fs::exists(extended_path)) {
527     LOG(ERROR) << "Extended storage not exists!";
528     return false;
529   }
530   return true;
531 }
532
533 bool CheckPackageReadonlyNonExistance(const std::string& pkgid,
534                                       const TestParameters& params) {
535   ci::PkgQueryInterface pkg_query(pkgid, params.test_user.uid, true);
536   EXTENDED_ASSERT_FALSE(pkg_query.IsPackageInstalled(
537       ci::GetRequestMode(params.test_user.uid)));
538   EXTENDED_ASSERT_TRUE(PackageCheckCleanup(pkgid, params));
539   return true;
540 }
541
542 static bool CheckSharedDataExistanceForPath(const fs::path& apps_rw,
543     const std::string& pkgid) {
544   fs::path shared_data_path = apps_rw / pkgid / rwDirectories[SHARED_DATA];
545   fs::path shared = apps_rw / kShared / pkgid / kData;
546   fs::path shared_tmp = apps_rw / kSharedTmp / pkgid;
547   EXTENDED_ASSERT_TRUE(fs::exists(shared_data_path));
548   EXTENDED_ASSERT_TRUE(fs::exists(shared));
549   EXTENDED_ASSERT_TRUE(fs::exists(shared_tmp));
550   return true;
551 }
552
553 static bool CheckSharedDataPermissions(const fs::path& apps_rw,
554     const std::string& pkgid, uid_t uid) {
555   fs::path shared_data_path = apps_rw / pkgid / rwDirectories[SHARED_DATA];
556   fs::path shared = apps_rw / kShared / pkgid / kData;
557   fs::path shared_tmp = apps_rw / kSharedTmp / pkgid;
558   // gid of RW dirs should be system_share
559   std::optional<gid_t> system_share =
560       ci::GetGidByGroupName(kSystemShareGroupName);
561   struct stat stats;
562   stat(shared_data_path.c_str(), &stats);
563   EXTENDED_ASSERT_EQ(uid, stats.st_uid);
564   EXTENDED_ASSERT_EQ(*system_share, stats.st_gid);
565   stat(shared.c_str(), &stats);
566   EXTENDED_ASSERT_EQ(uid, stats.st_uid);
567   EXTENDED_ASSERT_EQ(*system_share, stats.st_gid);
568   stat(shared_tmp.c_str(), &stats);
569   EXTENDED_ASSERT_EQ(uid, stats.st_uid);
570   EXTENDED_ASSERT_EQ(kDefaultUserGid, stats.st_gid);
571   return true;
572 }
573
574 bool CheckSharedDataExistance(const std::string& pkgid,
575     const TestParameters& params) {
576   if (params.test_user.uid == kGlobalUserUid) {
577     fs::path skel_path(kSkelDir);
578     EXTENDED_ASSERT_TRUE(CheckSharedDataExistanceForPath(kSkelDir, pkgid));
579     ci::UserList list = ci::GetUserList();
580     for (auto& l : list) {
581       uid_t uid = std::get<0>(l);
582       fs::path apps_rw = ci::GetRootAppPath(false, uid);
583       EXTENDED_ASSERT_TRUE(CheckSharedDataExistanceForPath(apps_rw, pkgid));
584       EXTENDED_ASSERT_TRUE(CheckSharedDataPermissions(apps_rw, pkgid, uid));
585     }
586   } else {
587     fs::path apps_rw = ci::GetRootAppPath(false, params.test_user.uid);
588     EXTENDED_ASSERT_TRUE(CheckSharedDataExistanceForPath(apps_rw, pkgid));
589     EXTENDED_ASSERT_TRUE(
590         CheckSharedDataPermissions(apps_rw, pkgid, params.test_user.uid));
591   }
592   return true;
593 }
594
595 static bool CheckSharedDataNonExistanceForPath(const fs::path& apps_rw,
596     const std::string pkgid) {
597   fs::path shared_data_path = apps_rw / pkgid / rwDirectories[SHARED_DATA];
598   fs::path shared = apps_rw / kShared / pkgid / kData;
599   fs::path shared_tmp = apps_rw / kSharedTmp / pkgid;
600   EXTENDED_ASSERT_FALSE(fs::exists(shared_data_path));
601   EXTENDED_ASSERT_FALSE(fs::exists(shared));
602   EXTENDED_ASSERT_FALSE(fs::exists(shared_tmp));
603   return true;
604 }
605
606 bool CheckSharedDataNonExistance(const std::string& pkgid,
607     const TestParameters& params) {
608   if (params.test_user.uid == kGlobalUserUid) {
609     fs::path skel_path(kSkelDir);
610     EXTENDED_ASSERT_TRUE(
611         CheckSharedDataNonExistanceForPath(skel_path, pkgid));
612
613     ci::UserList list = ci::GetUserList();
614     for (auto& l : list) {
615       uid_t uid = std::get<0>(l);
616       fs::path apps_rw = ci::GetRootAppPath(false, uid);
617       EXTENDED_ASSERT_TRUE(CheckSharedDataNonExistanceForPath(apps_rw, pkgid));
618     }
619   } else {
620     fs::path apps_rw = ci::GetRootAppPath(false, params.test_user.uid);
621     EXTENDED_ASSERT_TRUE(CheckSharedDataNonExistanceForPath(apps_rw, pkgid));
622   }
623   return true;
624 }
625
626 void FileInfoCollector::AddPath(const fs::path& path) {
627   root_paths_.emplace_back(path);
628 }
629
630 bool FileInfoCollector::CollectFileInfoRecursive() {
631   for (const auto& path : root_paths_) {
632     if (!fs::exists(path) && !fs::is_symlink(path))
633       continue;
634
635     if (!GetFileListTraversal(path))
636       return false;
637   }
638
639   return true;
640 }
641
642 bool FileInfoCollector::GetFileListTraversal(const fs::path& cur) {
643   std::error_code error;
644   fs::file_status file_status = fs::symlink_status(cur, error);
645   if (error) {
646     LOG(ERROR) << "Fail to get symlink_status, " << error.message();
647     return false;
648   }
649
650   struct stat info;
651   if (lstat(cur.c_str(), &info) != 0) {
652     LOG(ERROR) << "Fail to lstat from [" << cur << "]";
653     return false;
654   }
655
656   std::string owner = ci::GetUsernameByUid(info.st_uid);
657   std::string group = ci::GetGroupNameByGid(info.st_gid);
658
659   char* access_label = nullptr;
660   if (smack_lgetlabel(cur.c_str(), &access_label, SMACK_LABEL_ACCESS) < 0) {
661     LOG(ERROR) << "Fail to get access label from [" << cur << "]";
662     return false;
663   }
664
665   if (access_label == nullptr) {
666     LOG(ERROR) << "Fail to get access label from [" << cur << "]";
667     return false;
668   }
669
670   FileInfos_.emplace_back(cur, file_status.type(),
671       file_status.permissions(), owner, group, access_label);
672
673   if (!fs::is_directory(cur) || fs::is_symlink(cur))
674     return true;
675
676   for (fs::directory_iterator file(cur);
677       file != fs::directory_iterator();
678       ++file) {
679     if (!GetFileListTraversal(file->path())) {
680       FileInfos_.clear();
681       return false;
682     }
683   }
684
685   return true;
686 }
687
688 bool FileInfoCollector::FileInfoToFile(const fs::path& path) const {
689   std::ofstream out(path.string());
690
691   for (const auto& info : FileInfos_)
692     out << FileInfoToString(info) << std::endl;
693
694   out.close();
695
696   return true;
697 }
698
699 bool FileInfoCollector::Init() {
700   fs::path skel_apps_rw = fs::path(kSkelDir);
701   fs::path root_path =
702       ci::GetRootAppPath(params_.is_readonly, params_.test_user.uid);
703
704   AddPath(root_path / pkgid_);
705   AddPath(skel_apps_rw / pkgid_);
706
707   if (params_.test_user.uid == tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)) {
708     // per user dir
709     ci::UserList list = ci::GetUserList();
710     for (auto l : list) {
711       fs::path apps_rw = std::get<2>(l) / "apps_rw";
712       AddPath(apps_rw / pkgid_);
713       AddPath(apps_rw / kShared / pkgid_);
714       AddPath(apps_rw / kSharedTmp / pkgid_);
715     }
716   } else {
717     AddPath(root_path / kShared / pkgid_);
718     AddPath(root_path / kSharedTmp / pkgid_);
719   }
720
721   if (!CollectFileInfoRecursive())
722     return false;
723
724   std::sort(FileInfos_.begin(), FileInfos_.end(),
725       [](const FileInfo& l, const FileInfo& r) -> bool {
726         return std::get<0>(l) < std::get<0>(r);
727       });
728
729   return true;
730 }
731
732 bool FileInfoCollector::LoadFromFile(const fs::path& path) {
733   std::ifstream readFile;
734   readFile.open(path.c_str());
735
736   if (!readFile.is_open()) {
737     LOG(ERROR) << "Fail to read file : " << path;
738     return false;
739   }
740
741   std::string line;
742
743   while (std::getline(readFile, line)) {
744     std::istringstream iss(line);
745     fs::path p;
746     int file_permission;
747     int file_type;
748     std::string owner;
749     std::string group;
750     std::string access_label;
751
752     iss >> p >> file_type >> std::oct >> file_permission
753         >> owner >> group >> access_label;
754
755     FileInfos_.emplace_back(p, fs::file_type(file_type),
756         fs::perms(file_permission), owner, group, access_label);
757   }
758
759   readFile.close();
760
761   return true;
762 }
763
764 std::string FileInfoCollector::FileTypeToString(const fs::file_type type) const {
765   switch (type) {
766     case fs::file_type::none:
767       return "none";
768     case fs::file_type::not_found:
769       return "not_found";
770     case fs::file_type::regular:
771       return "regular";
772     case fs::file_type::directory:
773       return "directory";
774     case fs::file_type::symlink:
775       return "symlink";
776     case fs::file_type::block:
777       return "block";
778     case fs::file_type::character:
779       return "character";
780     case fs::file_type::fifo:
781       return "fifo";
782     case fs::file_type::socket:
783       return "socket";
784     case fs::file_type::unknown:
785       return "unknown";
786     default:
787       return "implementation-defined";
788   }
789 }
790
791 int FileInfoCollector::PermsToInt(const fs::perms p) const {
792   int perm_int = 0;
793
794   perm_int |= fs::perms::none == (p & fs::perms::owner_read) ? 0 : 0400;
795   perm_int |= fs::perms::none == (p & fs::perms::owner_write) ? 0 : 0200;
796   perm_int |= fs::perms::none == (p & fs::perms::owner_exec) ? 0 :  0100;
797   perm_int |= fs::perms::none == (p & fs::perms::group_read) ? 0 : 040;
798   perm_int |= fs::perms::none == (p & fs::perms::group_write) ? 0 : 020;
799   perm_int |= fs::perms::none == (p & fs::perms::group_exec) ? 0 : 010;
800   perm_int |= fs::perms::none == (p & fs::perms::others_read) ? 0 :  04;
801   perm_int |= fs::perms::none == (p & fs::perms::others_write) ? 0 : 02;
802   perm_int |= fs::perms::none == (p & fs::perms::others_exec) ? 0 : 01;
803
804   return perm_int;
805 }
806
807 std::string FileInfoCollector::FileInfoToString(
808     const FileInfo& file_info) const {
809   fs::path p = std::get<0>(file_info);
810   fs::file_type file_type = std::get<1>(file_info);
811   std::string file_permission;
812   std::string owner = std::get<3>(file_info);
813   std::string group = std::get<4>(file_info);
814   std::string access_label = std::get<5>(file_info);
815   std::stringstream ss;
816   ss << std::oct << PermsToInt(std::get<2>(file_info));
817   ss >> file_permission;
818
819   std::string res;
820   res += p.string();
821   res += " ";
822   res += FileTypeToString(file_type);
823   res += " ";
824   res += file_permission;
825   res += " ";
826   res += owner;
827   res += " ";
828   res += group;
829   res += " ";
830   res += access_label;
831
832   return res;
833 }
834
835 bool FileInfoCollector::IsEqual(const FileInfoCollector& that,
836     const std::vector<fs::path>* exception_list) const {
837   auto it_l = FileInfos_.begin();
838   auto it_r = that.FileInfos_.begin();
839   bool res = true;
840
841   while (it_l != FileInfos_.end() && it_r != that.FileInfos_.end()) {
842     if (*it_l == *it_r) {
843       it_l++;
844       it_r++;
845       continue;
846     }
847
848     fs::path path_l = std::get<0>(*it_l);
849     fs::path path_r = std::get<0>(*it_r);
850     if (exception_list && path_l == path_r &&
851         std::find(exception_list->begin(), exception_list->end(), path_r)
852             != exception_list->end()) {
853       it_l++;
854       it_r++;
855       continue;
856     }
857
858     res = false;
859
860     if (path_l > path_r) {
861       LOG(ERROR) << "There is an unexpected file [" << path_r << "]";
862       it_r++;
863     } else if (path_l < path_r) {
864       LOG(ERROR) << "There is not exists an expected file [" << path_l << "]";
865       it_l++;
866     } else {
867       LOG(ERROR) << "There is a different status file. expected ["
868           << FileInfoToString(*it_l) << "], result ["
869           << FileInfoToString(*it_r) << "]";
870       it_l++;
871       it_r++;
872     }
873   }
874
875   while (it_l != FileInfos_.end()) {
876     LOG(ERROR) << "There is an unexpected file [" << std::get<0>(*it_l) << "]";
877     it_l++;
878     res = false;
879   }
880
881   while (it_r != that.FileInfos_.end()) {
882     LOG(ERROR) << "There is not exists an expected file ["
883         << std::get<0>(*it_r) << "]";
884     it_r++;
885     res = false;
886   }
887
888   return res;
889 }
890
891 void BackendInterface::TestRollbackAfterEachStep(int argc, const char* argv[],
892     std::function<bool()> validator) const {
893   ci::Subprocess backend_helper = CreateSubprocess();
894   bool result = backend_helper.RunFunc({[&]() -> int {
895     TestPkgmgrInstaller pkgmgr_installer;
896     std::shared_ptr<ci::AppQueryInterface> query_interface =
897         CreateQueryInterface();
898     auto pkgmgr =
899         ci::PkgMgrInterface::Create(argc, const_cast<char**>(argv),
900                                     &pkgmgr_installer,
901                                     query_interface);
902     if (!pkgmgr) {
903       LOG(ERROR) << "Failed to initialize pkgmgr interface";
904       return 1;
905     }
906     AppInstallerPtr backend;
907     unsigned int insert_idx = 0;
908     do {
909       backend = CreateFailExpectedInstaller(pkgmgr, insert_idx);
910       LOG(DEBUG) << "StepFail is inserted at: " << insert_idx;
911       ci::AppInstaller::Result ret = backend->Run();
912       if (ret != ci::AppInstaller::Result::ERROR) {
913         LOG(ERROR) << "StepFail not executed";
914         return 1;
915       }
916       if (!validator()) {
917         LOG(ERROR) << "Fail to validate. index of StepFail : " << insert_idx;
918         break;
919       }
920       insert_idx++;
921     } while (insert_idx < backend->StepCount());
922     if (insert_idx != backend->StepCount())
923       return 1;
924
925     return 0;
926   }});
927   ASSERT_EQ(result, true);
928   int status = backend_helper.Wait();
929   ASSERT_NE(WIFEXITED(status), 0);
930   ASSERT_EQ(WEXITSTATUS(status), 0);
931 }
932
933 void BackendInterface::CrashAfterEachStep(std::vector<std::string>* args,
934     std::function<bool(int iter)> validator, PackageType type) const {
935   ci::Subprocess backend_helper = CreateSubprocess();
936   bool result = backend_helper.RunFunc({[&]() {
937     std::unique_ptr<const char*[]> argv(new const char*[args->size()]);
938     for (size_t i = 0; i < args->size(); ++i) {
939       argv[i] = args->at(i).c_str();
940     }
941     TestPkgmgrInstaller pkgmgr_installer;
942     auto query_interface = CreateQueryInterface();
943     auto pkgmgr = ci::PkgMgrInterface::Create(args->size(),
944         const_cast<char**>(argv.get()), &pkgmgr_installer, query_interface);
945     if (!pkgmgr) {
946       LOG(ERROR) << "Failed to initialize pkgmgr interface";
947       return 1;
948     }
949     auto backend = CreateFailExpectedInstaller(pkgmgr, 0);
950     if (backend->Run() != ci::AppInstaller::Result::ERROR) {
951       LOG(ERROR) << "StepFail not executed";
952       return 1;
953     }
954     int stepCount = backend->StepCount();
955
956     args->push_back("-idx");
957     args->push_back(std::to_string(stepCount));
958     int insert_idx;
959     std::string prefix = (type == PackageType::TPK) ? "tpk" : "wgt";
960     for (insert_idx = 0; insert_idx < stepCount; insert_idx++) {
961       ci::Subprocess backend_crash(
962           "/usr/bin/" + prefix + "-installer-ut/smoke-test-helper");
963       args->back() = std::to_string(insert_idx);
964       backend_crash.Run(*args);
965       if (backend_crash.Wait() == 0) {
966         LOG(ERROR) << "Subprocess exit without crash";
967         return 1;
968       }
969       if (!validator(insert_idx)) {
970         LOG(ERROR) << "Fail to validate. index of StepCrash : " << insert_idx;
971         break;
972       }
973     }
974     if (stepCount != insert_idx)
975       return 1;
976
977     args->push_back("-type_clean");
978     for (insert_idx = stepCount - 1; insert_idx >= 2; insert_idx--) {
979       ci::Subprocess backend_crash(
980           "/usr/bin/" + prefix + "-installer-ut/smoke-test-helper");
981       auto it = args->end();
982       it -= 2;
983       *it = std::to_string(insert_idx);
984       backend_crash.Run(*args);
985       if (backend_crash.Wait() == 0) {
986         LOG(ERROR) << "Subprocess exit without crash";
987         return 1;
988       }
989       if (!validator(insert_idx)) {
990         LOG(ERROR) << "Fail to validate. index of StepCrash : " << insert_idx;
991         break;
992       }
993     }
994     if (insert_idx != 1)
995       return 1;
996
997     return 0;
998   }});
999
1000   ASSERT_EQ(result, true);
1001   int status = backend_helper.Wait();
1002   ASSERT_NE(WIFEXITED(status), 0);
1003   ASSERT_EQ(WEXITSTATUS(status), 0);
1004 }
1005
1006 BackendInterface::CommandResult BackendInterface::RunInstallersWithPkgmgr(
1007     ci::PkgMgrPtr pkgmgr) const {
1008   std::list<AppInstallerPtr> installers;
1009   for (int i = 0; i < pkgmgr->GetRequestInfoCount(); i++) {
1010     AppInstallerPtr installer;
1011     if (mode_ == RequestResult::FAIL && i == pkgmgr->GetRequestInfoCount() - 1)
1012       installer = factory_->CreateFailExpectedInstaller(i, pkgmgr);
1013     else
1014       installer = factory_->CreateInstaller(i, pkgmgr);
1015     if (!installer)
1016       LOG(ERROR) << "Failed to create installer";
1017     else
1018       installers.emplace_back(std::move(installer));
1019   }
1020
1021   // FIXME: I think we should not implement this logic here...
1022   CommandResult result = CommandResult::OK;
1023   std::list<AppInstallerPtr>::iterator it(installers.begin());
1024   for (; it != installers.end(); ++it) {
1025     result = (*it)->Process();
1026     if (result != CommandResult::OK)
1027       break;
1028   }
1029   if (it != installers.end() && result == CommandResult::ERROR) {
1030     do {
1031       CommandResult ret = (*it)->Undo();
1032       if (ret != CommandResult::OK && ret != CommandResult::ERROR)
1033         result = CommandResult::UNDO_ERROR;
1034     } while (it-- != installers.begin());
1035   } else {
1036     --it;
1037     do {
1038       if ((*it)->Clean() != CommandResult::OK)
1039         result = CommandResult::CLEANUP_ERROR;
1040     } while (it-- != installers.begin());
1041   }
1042   return result;
1043 }
1044
1045 BackendInterface::CommandResult BackendInterface::CallBackendWithRunner(
1046     int argc, const char* argv[]) const {
1047   TestPkgmgrInstaller pkgmgr_installer;
1048   auto pkgmgr = ci::PkgMgrInterface::Create(argc, const_cast<char**>(argv),
1049       &pkgmgr_installer);
1050   if (!pkgmgr) {
1051     LOG(ERROR) << "Failed to initialize pkgmgr interface";
1052     return BackendInterface::CommandResult::UNKNOWN;
1053   }
1054   return RunInstallersWithPkgmgr(pkgmgr);
1055 }
1056
1057 BackendInterface::CommandResult BackendInterface::Install(
1058     const std::vector<fs::path>& paths) const {
1059   std::vector<const char*> argv;
1060   argv.emplace_back("");
1061   argv.emplace_back("-i");
1062   for (const auto& p : paths)
1063     argv.emplace_back(p.c_str());
1064   return CallBackendWithRunner(argv.size(), argv.data());
1065 }
1066
1067 BackendInterface::CommandResult BackendInterface::Uninstall(
1068     const std::vector<std::string>& pkgids) const {
1069   std::vector<const char*> argv;
1070   argv.emplace_back("");
1071   argv.emplace_back("-d");
1072   for (const auto& p : pkgids)
1073     argv.emplace_back(p.c_str());
1074   return CallBackendWithRunner(argv.size(), argv.data());
1075 }
1076
1077 BackendInterface::CommandResult BackendInterface::InstallSuccess(
1078     const std::vector<fs::path>& paths) const {
1079   RequestResult tmp_mode = mode_;
1080   RequestResult &original_mode = const_cast<RequestResult&>(mode_);
1081   original_mode = RequestResult::NORMAL;
1082   if (Install(paths) != BackendInterface::CommandResult::OK) {
1083     LOG(ERROR) << "Failed to install application. Cannot update";
1084     return BackendInterface::CommandResult::UNKNOWN;
1085   }
1086   original_mode = tmp_mode;
1087   return BackendInterface::CommandResult::OK;
1088 }
1089
1090 BackendInterface::CommandResult BackendInterface::RunInstallerWithPkgrmgr(
1091     ci::PkgMgrPtr pkgmgr) const {
1092   std::unique_ptr<ci::AppInstaller> installer;
1093   switch (mode_) {
1094   case RequestResult::FAIL:
1095     installer = CreateFailExpectedInstaller(pkgmgr);
1096     break;
1097   default:
1098     installer = CreateInstaller(pkgmgr);
1099     break;
1100   }
1101   return installer->Run();
1102 }
1103
1104 BackendInterface::CommandResult BackendInterface::CallBackend(int argc,
1105     const char* argv[]) const {
1106   TestPkgmgrInstaller pkgmgr_installer;
1107   auto query_interface = CreateQueryInterface();
1108   auto pkgmgr = ci::PkgMgrInterface::Create(argc, const_cast<char**>(argv),
1109       &pkgmgr_installer, query_interface);
1110   if (!pkgmgr) {
1111     LOG(ERROR) << "Failed to initialize pkgmgr interface";
1112     return BackendInterface::CommandResult::UNKNOWN;
1113   }
1114   return RunInstallerWithPkgrmgr(pkgmgr);
1115 }
1116
1117 BackendInterface::CommandResult BackendInterface::Install(
1118     const fs::path& path) const {
1119   const char* argv[] = {"", "-i", path.c_str(), "-u", uid_str_.c_str()};
1120   return CallBackend(SIZEOFARRAY(argv), argv);
1121 }
1122
1123 BackendInterface::CommandResult BackendInterface::InstallPreload(
1124     const fs::path& path) const {
1125   const char* argv[] = {"", "-i", path.c_str(), "--preload"};
1126   return CallBackend(SIZEOFARRAY(argv), argv);
1127 }
1128
1129 BackendInterface::CommandResult BackendInterface::InstallWithStorage(
1130     const fs::path& path, StorageType type) const {
1131   int default_storage = 0;
1132   int storage = 0;
1133   switch (type) {
1134     case StorageType::EXTERNAL:
1135       storage = 1;
1136       break;
1137     case StorageType::EXTENDED:
1138       storage = 2;
1139       break;
1140     default:
1141       LOG(ERROR) << "Unknown storage type";
1142       break;
1143   }
1144   if (vconf_get_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT,
1145       &default_storage) != 0) {
1146     LOG(ERROR) << "Failed to get value of "
1147         "VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT";
1148     return BackendInterface::CommandResult::ERROR;
1149   }
1150   if (vconf_set_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT,
1151       storage) != 0) {
1152     LOG(ERROR) << "Failed to set value of "
1153         "VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT";
1154     return BackendInterface::CommandResult::ERROR;
1155   }
1156
1157   const char* argv[] = {"", "-i", path.c_str(), "-u", uid_str_.c_str()};
1158   BackendInterface::CommandResult result = CallBackend(SIZEOFARRAY(argv), argv);
1159
1160   if (vconf_set_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT,
1161       default_storage) != 0) {
1162     LOG(ERROR) << "Failed to set value of "
1163         "VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT";
1164     return BackendInterface::CommandResult::ERROR;
1165   }
1166
1167   return result;
1168 }
1169
1170 BackendInterface::CommandResult BackendInterface::MigrateLegacyExternalImage(
1171     const std::string& pkgid,
1172     const fs::path& path,
1173     const fs::path& legacy_path) const {
1174   if (InstallWithStorage(path, StorageType::EXTERNAL) !=
1175       BackendInterface::CommandResult::OK) {
1176     LOG(ERROR) << "Failed to install application. Cannot perform Migrate";
1177     return BackendInterface::CommandResult::ERROR;
1178   }
1179
1180   fs::path ext_mount_path = ci::GetExternalCardPath();
1181   if (fs::is_empty(ext_mount_path)) {
1182     LOG(ERROR) << "Sdcard not exists!";
1183     return BackendInterface::CommandResult::ERROR;
1184   }
1185   fs::path app2sd_path = ext_mount_path / "app2sd";
1186
1187   char* image_name = app2ext_usr_getname_image(pkgid.c_str(),
1188                      kGlobalUserUid);
1189   if (!image_name) {
1190     LOG(ERROR) << "Failed to get external image name";
1191     return BackendInterface::CommandResult::ERROR;
1192   }
1193   fs::path org_image = app2sd_path / image_name;
1194   free(image_name);
1195
1196   std::error_code error;
1197   fs::remove(org_image, error);
1198   if (error) {
1199     LOG(ERROR) << "Failed to remove org image";
1200     return BackendInterface::CommandResult::ERROR;
1201   }
1202
1203   fs::path db_path = tzplatform_getenv(TZ_SYS_DB);
1204   fs::path app2sd_db = db_path / ".app2sd.db";
1205   fs::path app2sd_db_journal = db_path / ".app2sd.db-journal";
1206   fs::remove(app2sd_db, error);
1207   if (error) {
1208     LOG(ERROR) << "Failed to remove app2sd db";
1209     return BackendInterface::CommandResult::ERROR;
1210   }
1211   fs::remove(app2sd_db_journal, error);
1212   if (error) {
1213     LOG(ERROR) << "Failed to remove app2sd journal db";
1214     return BackendInterface::CommandResult::ERROR;
1215   }
1216
1217   fs::path app2sd_migrate_db = legacy_path / kMigrateTestDBName;
1218   if (!ci::CopyFile(app2sd_migrate_db, app2sd_db)) {
1219     LOG(ERROR) << "Failed to copy test db";
1220     return BackendInterface::CommandResult::ERROR;
1221   }
1222
1223   fs::path legacy_src = legacy_path / pkgid;
1224   fs::path legacy_dst = app2sd_path / pkgid;
1225   if (!ci::CopyFile(legacy_src, legacy_dst)) {
1226     LOG(ERROR) << "Failed to copy test image";
1227     return BackendInterface::CommandResult::ERROR;
1228   }
1229   const char* argv[] = {"", "--migrate-extimg", pkgid.c_str(),
1230                        "-u", uid_str_.c_str()};
1231   return CallBackend(SIZEOFARRAY(argv), argv);
1232 }
1233
1234 BackendInterface::CommandResult BackendInterface::RDSUpdate(
1235     const fs::path& path,
1236     const std::string& pkgid) const {
1237   RequestResult tmp_mode = mode_;
1238   RequestResult &original_mode = const_cast<RequestResult&>(mode_);
1239   original_mode = RequestResult::NORMAL;
1240   if (Install(path) != BackendInterface::CommandResult::OK) {
1241     LOG(ERROR) << "Failed to install application. Cannot perform RDS";
1242     return BackendInterface::CommandResult::UNKNOWN;
1243   }
1244   const char* argv[] = {"", "-r", pkgid.c_str(), "-u",
1245                         uid_str_.c_str()};
1246   original_mode = tmp_mode;
1247   return CallBackend(SIZEOFARRAY(argv), argv);
1248 }
1249
1250 BackendInterface::CommandResult BackendInterface::EnablePackage(
1251     const std::string& pkgid) const {
1252   const char* argv[] = {"", "-A", pkgid.c_str(), "-u", uid_str_.c_str()};
1253   return CallBackend(SIZEOFARRAY(argv), argv);
1254 }
1255
1256 BackendInterface::CommandResult BackendInterface::DisablePackage(
1257     const std::string& pkgid) const {
1258   const char* argv[] = {"", "-D", pkgid.c_str(), "-u", uid_str_.c_str()};
1259   return CallBackend(SIZEOFARRAY(argv), argv);
1260 }
1261
1262 BackendInterface::CommandResult BackendInterface::Recover(
1263     const fs::path& recovery_file) const {
1264   const char* argv[] = {"", "-b", recovery_file.c_str(), "-u",
1265       uid_str_.c_str()};
1266   return CallBackend(SIZEOFARRAY(argv), argv);
1267 }
1268
1269 BackendInterface::CommandResult BackendInterface::ManifestDirectInstall(
1270     const std::string& pkgid) const {
1271   const char* argv[] = {"", "-y", pkgid.c_str(), "-u", uid_str_.c_str()};
1272   return CallBackend(SIZEOFARRAY(argv), argv);
1273 }
1274
1275 BackendInterface::CommandResult BackendInterface::Uninstall(
1276     const std::string& pkgid) const {
1277   const char* argv[] = {"", "-d", pkgid.c_str(), "-u", uid_str_.c_str()};
1278   return CallBackend(SIZEOFARRAY(argv), argv);
1279 }
1280
1281 BackendInterface::CommandResult BackendInterface::UninstallPreload(
1282     const std::string& pkgid) const {
1283   const char* argv[] = {"", "-d", pkgid.c_str(), "--preload",
1284       "--force-remove"};
1285   return CallBackend(SIZEOFARRAY(argv), argv);
1286 }
1287
1288 BackendInterface::CommandResult BackendInterface::InstallSuccess(
1289     const fs::path& path) const {
1290   RequestResult tmp_mode = mode_;
1291   RequestResult &original_mode = const_cast<RequestResult&>(mode_);
1292   original_mode = RequestResult::NORMAL;
1293   if (Install(path) != BackendInterface::CommandResult::OK) {
1294     LOG(ERROR) << "Failed to install application. Cannot update";
1295     return BackendInterface::CommandResult::UNKNOWN;
1296   }
1297   original_mode = tmp_mode;
1298   return BackendInterface::CommandResult::OK;
1299 }
1300
1301 BackendInterface::CommandResult BackendInterface::InstallPreloadSuccess(
1302     const fs::path& path) const {
1303   RequestResult tmp_mode = mode_;
1304   RequestResult &original_mode = const_cast<RequestResult&>(mode_);
1305   original_mode = RequestResult::NORMAL;
1306   if (InstallPreload(path) != BackendInterface::CommandResult::OK) {
1307     LOG(ERROR) << "Failed to install application. Cannot update";
1308     return BackendInterface::CommandResult::UNKNOWN;
1309   }
1310   original_mode = tmp_mode;
1311   return BackendInterface::CommandResult::OK;
1312 }
1313
1314 BackendInterface::CommandResult BackendInterface::MountInstall(
1315     const fs::path& path) const {
1316   const char* argv[] = {"", "-w", path.c_str(), "-u", uid_str_.c_str()};
1317   return CallBackend(SIZEOFARRAY(argv), argv);
1318 }
1319
1320 BackendInterface::CommandResult BackendInterface::MountInstallSuccess(
1321     const fs::path& path) const {
1322   RequestResult tmp_mode = mode_;
1323   RequestResult &original_mode = const_cast<RequestResult&>(mode_);
1324   original_mode = RequestResult::NORMAL;
1325   if (MountInstall(path) != BackendInterface::CommandResult::OK) {
1326     LOG(ERROR) << "Failed to mount-install application. Cannot mount-update";
1327     return BackendInterface::CommandResult::UNKNOWN;
1328   }
1329   original_mode = tmp_mode;
1330   return BackendInterface::CommandResult::OK;
1331 }
1332
1333 static std::filesystem::path GetTrashPath(
1334     const std::filesystem::path& path) {
1335   return path.string() + ".trash";
1336 }
1337
1338 BackendInterface::SubProcessResult BackendInterface::RunSubprocess(
1339     std::vector<std::string> args) const {
1340   args.push_back("-remove_plugin_steps");
1341   ci::Subprocess backend = CreateSubprocess();
1342   backend.RunWithArgs(args);
1343   int status = backend.Wait();
1344   if (WIFEXITED(status)) {
1345     if (WEXITSTATUS(status) == 0)
1346       return BackendInterface::SubProcessResult::SUCCESS;
1347     else
1348       return BackendInterface::SubProcessResult::FAIL;
1349   }
1350   return BackendInterface::SubProcessResult::UnKnown;
1351 }
1352
1353 BackendInterface::SubProcessResult BackendInterface::RunSubprocessAndKill(
1354     std::vector<std::string> args, useconds_t delay) const {
1355   args.push_back("-remove_plugin_steps");
1356   ci::Subprocess backend = CreateSubprocess();
1357   backend.RunWithArgs(args);
1358   usleep(delay);
1359   backend.Kill();
1360   int status = backend.Wait();
1361   if (WIFEXITED(status)) {
1362     if (WEXITSTATUS(status) == 0)
1363       return BackendInterface::SubProcessResult::SUCCESS;
1364     else
1365       return BackendInterface::SubProcessResult::FAIL;
1366   } else {
1367     if (WTERMSIG(status) == SIGKILL)
1368       return BackendInterface::SubProcessResult::KILLED;
1369     else
1370       return BackendInterface::SubProcessResult::UnKnown;
1371   }
1372 }
1373
1374 BackendInterface::SubProcessResult BackendInterface::InstallWithSubprocess(
1375     const fs::path& path) const {
1376   std::vector<std::string> args =
1377       { "-i", path.string(), "-u", uid_str_ };
1378   return RunSubprocess(args);
1379 }
1380
1381 BackendInterface::SubProcessResult BackendInterface::MountInstallWithSubprocess(
1382     const fs::path& path) const {
1383   std::vector<std::string> args =
1384       { "-w", path.string(), "-u", uid_str_ };
1385   return RunSubprocess(args);
1386 }
1387
1388 BackendInterface::SubProcessResult BackendInterface::RecoverWithSubprocess(
1389     const fs::path& path) const {
1390   std::vector<std::string> args =
1391       { "-b", path.string(), "-u", uid_str_ };
1392   return RunSubprocess(args);
1393 }
1394
1395 BackendInterface::SubProcessResult BackendInterface::UninstallWithSubprocess(
1396     const std::string& pkgid) const {
1397   std::vector<std::string> args = { "-d", pkgid, "-u", uid_str_ };
1398   return RunSubprocess(args);
1399 }
1400
1401 BackendInterface::SubProcessResult
1402 BackendInterface::InstallPreloadWithSubprocess(
1403     const std::filesystem::path& path) const {
1404   std::vector<std::string> args = { "", "-i", path.string(), "--preload" };
1405   return RunSubprocess(args);
1406 }
1407
1408 BackendInterface::SubProcessResult
1409     BackendInterface::InstallWithSubprocessAndKill(
1410         const fs::path& path, useconds_t delay) const {
1411   std::vector<std::string> args =
1412       { "-i", path.string(), "-u", uid_str_ };
1413   return RunSubprocessAndKill(args, delay);
1414 }
1415
1416 BackendInterface::SubProcessResult
1417     BackendInterface::MountInstallWithSubprocessAndKill(
1418         const fs::path& path, useconds_t delay) const {
1419   std::vector<std::string> args =
1420       { "-w", path.string(), "-u", uid_str_ };
1421   return RunSubprocessAndKill(args, delay);
1422 }
1423
1424 BackendInterface::SubProcessResult
1425     BackendInterface::UninstallWithSubprocessAndKill(
1426         const std::string& pkgid, useconds_t delay) const {
1427   std::vector<std::string> args =
1428       { "-d", pkgid, "-u", uid_str_ };
1429   return RunSubprocessAndKill(args, delay);
1430 }
1431
1432 BackendInterface::SubProcessResult BackendInterface::InstallPkgsWithSubprocess(
1433     const std::vector<fs::path>& paths) const {
1434   std::vector<std::string> args;
1435   args.emplace_back("-i");
1436   for (const fs::path& p : paths)
1437     args.emplace_back(p.string());
1438   args.emplace_back("-u");
1439   args.emplace_back(uid_str_);
1440   return RunSubprocess(args);
1441 }
1442
1443 BackendInterface::SubProcessResult
1444     BackendInterface::MountInstallPkgsWithSubprocess(
1445     const std::vector<fs::path>& paths) const {
1446   std::vector<std::string> args;
1447   args.emplace_back("-w");
1448   for (const fs::path& p : paths)
1449     args.emplace_back(p.string());
1450   args.emplace_back("-u");
1451   args.emplace_back(uid_str_);
1452   return RunSubprocess(args);
1453 }
1454
1455 BackendInterface::SubProcessResult BackendInterface::RecoverPkgsWithSubprocess(
1456     const std::vector<fs::path>& paths) const {
1457   std::vector<std::string> args;
1458   args.emplace_back("-b");
1459   for (const fs::path& p : paths)
1460     args.emplace_back(p.string());
1461   args.emplace_back("-u");
1462   args.emplace_back(uid_str_);
1463   return RunSubprocess(args);
1464 }
1465
1466 BackendInterface::SubProcessResult
1467     BackendInterface::UninstallPkgsWithSubprocess(
1468         const std::vector<std::string>& pkgids) const {
1469   std::vector<std::string> args;
1470   args.emplace_back("-d");
1471   args.insert(args.end(), pkgids.begin(), pkgids.end());
1472   args.emplace_back("-u");
1473   args.emplace_back(uid_str_);
1474   return RunSubprocess(args);
1475 }
1476
1477 BackendInterface::SubProcessResult
1478     BackendInterface::InstallPkgsWithSubprocessAndKill(
1479         const std::vector<fs::path>& paths, useconds_t delay) const {
1480   std::vector<std::string> args;
1481   args.emplace_back("-i");
1482   for (const fs::path& p : paths)
1483     args.emplace_back(p.string());
1484   args.emplace_back("-u");
1485   args.emplace_back(uid_str_);
1486   return RunSubprocessAndKill(args, delay);
1487 }
1488
1489 BackendInterface::SubProcessResult
1490     BackendInterface::MountInstallPkgsWithSubprocessAndKill(
1491         const std::vector<fs::path>& paths, useconds_t delay) const {
1492   std::vector<std::string> args;
1493   args.emplace_back("-w");
1494   for (const fs::path& p : paths)
1495     args.emplace_back(p.string());
1496   args.emplace_back("-u");
1497   args.emplace_back(uid_str_);
1498   return RunSubprocessAndKill(args, delay);
1499 }
1500
1501 bool CopySmackAccess(const std::filesystem::path& src,
1502                      const std::filesystem::path& dst) {
1503   if (!fs::exists(src) && !fs::is_symlink(src)) {
1504     LOG(ERROR) << "Failed to copy smack access label";
1505     return false;
1506   }
1507   int ret;
1508   char* access_label = nullptr;
1509   ret = smack_lgetlabel(src.c_str(), &access_label, SMACK_LABEL_ACCESS);
1510   if (ret < 0) {
1511     LOG(ERROR) << "get access label from [" << src << "] fail";
1512     return false;
1513   }
1514   if (!access_label)
1515     return true;
1516   ret = smack_lsetlabel(dst.c_str(), access_label, SMACK_LABEL_ACCESS);
1517   free(access_label);
1518   if (ret < 0) {
1519     LOG(ERROR) << "set access label to [" << dst << "] fail";
1520     return false;
1521   }
1522   return true;
1523 }
1524
1525 bool CopySmackExec(const std::filesystem::path& src,
1526                    const std::filesystem::path& dst) {
1527   if (!fs::exists(src) && !fs::is_symlink(src)) {
1528     LOG(ERROR) << "Failed to copy smack exec label";
1529     return false;
1530   }
1531   int ret;
1532   char *exec_label = nullptr;
1533   ret = smack_lgetlabel(src.c_str(), &exec_label, SMACK_LABEL_EXEC);
1534   if (ret < 0) {
1535     LOG(ERROR) << "get exec label from [" << src << "] fail";
1536     return false;
1537   }
1538   if (!exec_label)
1539     return true;
1540   ret = smack_lsetlabel(dst.c_str(), exec_label, SMACK_LABEL_EXEC);
1541   free(exec_label);
1542   if (ret < 0) {
1543     LOG(ERROR) << "set exec label to [" << dst << "] fail";
1544     return false;
1545   }
1546   return true;
1547 }
1548
1549 bool CopySmackMmap(const std::filesystem::path& src,
1550                    const std::filesystem::path& dst) {
1551   if (!fs::exists(src) && !fs::is_symlink(src)) {
1552     LOG(ERROR) << "Failed to copy smack mmap label";
1553     return false;
1554   }
1555   int ret;
1556   char *mmap_label = nullptr;
1557   ret = smack_lgetlabel(src.c_str(), &mmap_label, SMACK_LABEL_MMAP);
1558   if (ret < 0) {
1559     LOG(ERROR) << "get mmap label from [" << src << "] fail";
1560     return false;
1561   }
1562   if (!mmap_label)
1563     return true;
1564   ret = smack_lsetlabel(dst.c_str(), mmap_label, SMACK_LABEL_MMAP);
1565   free(mmap_label);
1566   if (ret < 0) {
1567     LOG(ERROR) << "set mmap label to [" << dst << "] fail";
1568     return false;
1569   }
1570   return true;
1571 }
1572
1573 bool CopySmackTransmute(const std::filesystem::path& src,
1574                         const std::filesystem::path& dst) {
1575   if (!fs::exists(src)) {
1576     LOG(ERROR) << "Failed to copy smack tranmute label";
1577     return false;
1578   }
1579   int ret;
1580   char *transmute_label = nullptr;
1581   ret = smack_lgetlabel(src.c_str(), &transmute_label, SMACK_LABEL_TRANSMUTE);
1582   if (ret < 0) {
1583     LOG(ERROR) << "get access label from [" << src << "] fail";
1584     return false;
1585   }
1586   if (!transmute_label) {
1587     ret = smack_lsetlabel(dst.c_str(), "0", SMACK_LABEL_TRANSMUTE);
1588   } else {
1589     if (strcmp(transmute_label, "TRUE") == 0)
1590       ret = smack_lsetlabel(dst.c_str(), "1", SMACK_LABEL_TRANSMUTE);
1591     else
1592       ret = smack_lsetlabel(dst.c_str(), "0", SMACK_LABEL_TRANSMUTE);
1593     free(transmute_label);
1594     if (ret < 0) {
1595       LOG(ERROR) << "set access label to [" << dst << "] fail";
1596       return false;
1597     }
1598   }
1599
1600   return true;
1601 }
1602
1603 bool CopySmackLabels(const std::filesystem::path& src,
1604                      const std::filesystem::path& dst) {
1605   if (!CopySmackAccess(src, dst))
1606     return false;
1607   if (!CopySmackExec(src, dst))
1608     return false;
1609   if (!CopySmackMmap(src, dst))
1610     return false;
1611   if (!fs::is_symlink(src) && fs::is_directory(src)) {
1612     if (!CopySmackTransmute(src, dst))
1613       return false;
1614   }
1615   return true;
1616 }
1617
1618 bool CopyAndRemoveWithSmack(const fs::path& src, const fs::path& dst) {
1619   std::error_code error;
1620   if (fs::exists(dst)) {
1621     try {
1622       fs::remove_all(dst, error);
1623     } catch (...) {
1624       std::cout << "Exception occurred during remove [" << dst.string()
1625                 << "], and skip this file"<< std::endl;
1626     }
1627     if (error) {
1628       if (!fs::is_directory(dst)) {
1629         LOG(ERROR) << "remove_all fail";
1630         return false;
1631       }
1632     }
1633   }
1634   try {
1635     if (fs::is_symlink(src)) {
1636       fs::copy_symlink(src, dst, error);
1637       if (error) {
1638         LOG(ERROR) << "Failed to copy symlink: " << src << ", "
1639                    << error.message();
1640         return false;
1641       }
1642       if (!CopySmackLabels(src, dst)) {
1643         LOG(ERROR) << "copy smack label from [" << src.string()
1644                    << "] to [" << dst.string() << "] fail";
1645         return false;
1646       }
1647     } else if (fs::is_directory(src)) {
1648       if (!fs::exists(dst)) {
1649         fs::create_directories(dst, error);
1650         if (error) {
1651           LOG(ERROR) << "create directories fail";
1652           return false;
1653         }
1654         ci::CopyOwnershipAndPermissions(src, dst);
1655         if (!CopySmackLabels(src, dst)) {
1656           LOG(ERROR) << "copy smack label from [" << src.string()
1657                      << "] to [" << dst.string() << "] fail";
1658           return false;
1659         }
1660       }
1661       bool success = true;
1662       for (fs::directory_iterator file(src);
1663           file != fs::directory_iterator();
1664           ++file) {
1665         fs::path current(file->path());
1666         fs::path target = dst / current.filename();
1667         success &= CopyAndRemoveWithSmack(current, target);
1668       }
1669       fs::remove_all(src);
1670       if (!success)
1671         return false;
1672     } else {
1673       fs::copy_file(src, dst);
1674       ci::CopyOwnershipAndPermissions(src, dst);
1675       if (!CopySmackLabels(src, dst)) {
1676         LOG(ERROR) << "copy smack label from [" << src.string()
1677                    << "] to [" << dst.string() << "] fail";
1678         return false;
1679       }
1680       fs::remove_all(src);
1681     }
1682   } catch (...) {
1683     std::cout << "Exception occurred during copy [" << src.string()
1684               << "], and skip this file"<< std::endl;
1685     return true;
1686   }
1687
1688   return true;
1689 }
1690
1691 bool BackupPathCopyAndRemove(const fs::path& path) {
1692   if (!fs::exists(path))
1693     return true;
1694
1695   fs::path backup_path = path.string() + ".bck";
1696   std::cout << "Backup path: " << path << " to " << backup_path << std::endl;
1697   if (!CopyAndRemoveWithSmack(path, backup_path)) {
1698     LOG(ERROR) << "Failed to setup test environment. Does some previous"
1699                << " test crashed? Path: "
1700                << backup_path << " should not exist.";
1701     return false;
1702   }
1703   return true;
1704 }
1705
1706 bool BackupPath(const fs::path& path) {
1707   fs::path trash_path = GetTrashPath(path);
1708   if (fs::exists(trash_path)) {
1709     LOG(ERROR) << trash_path << " exists. Please remove "
1710                << trash_path << " manually!";
1711     return false;
1712   }
1713   fs::path backup_path = path.string() + ".bck";
1714   std::cout << "Backup path: " << path << " to " << backup_path << std::endl;
1715   std::error_code error;
1716   fs::remove_all(backup_path, error);
1717   if (error)
1718     LOG(ERROR) << "Remove failed: " << backup_path
1719                << " (" << error.message() << ")";
1720   if (fs::exists(path)) {
1721     fs::rename(path, backup_path, error);
1722     if (error) {
1723       LOG(ERROR) << "Failed to setup test environment. Does some previous"
1724                  << " test crashed? Path: "
1725                  << backup_path << " should not exist.";
1726       return false;
1727     }
1728     assert(!error);
1729     if (fs::is_directory(backup_path))
1730       fs::create_directory(path);
1731   }
1732   return true;
1733 }
1734
1735 void CreateDatabase() {
1736   pkgmgr_parser_create_and_initialize_db(kGlobalUserUid);
1737   pkgmgr_parser_create_and_initialize_db(getuid());
1738 }
1739
1740 bool RestorePathCopyAndRemove(const fs::path& path) {
1741   fs::path backup_path = path.string() + ".bck";
1742   if (!fs::exists(backup_path))
1743     return true;
1744
1745   std::cout << "Restore path: " << path << " from " << backup_path << std::endl;
1746   if (!CopyAndRemoveWithSmack(backup_path, path)) {
1747     LOG(ERROR) << "Failed to restore backup path: " << backup_path;
1748     return false;
1749   }
1750   return true;
1751 }
1752
1753 bool RestorePath(const fs::path& path) {
1754   fs::path backup_path = path.string() + ".bck";
1755   std::cout << "Restore path: " << path << " from " << backup_path << std::endl;
1756   std::error_code error;
1757   fs::remove_all(path, error);
1758   if (error) {
1759     fs::path trash_path = GetTrashPath(path);
1760     LOG(ERROR) << "Remove failed: " << path << " (" << error.message() << ")";
1761     std::cout << "Moving " << path << " to " << trash_path << std::endl;
1762     fs::rename(path, trash_path, error);
1763     if (error)
1764       LOG(ERROR) << "Failed to move " << path << " to " << trash_path
1765                  << " (" << error.message() << ")";
1766     else
1767       LOG(ERROR) << trash_path << " should be removed manually!";
1768   }
1769   if (fs::exists(backup_path)) {
1770     fs::rename(backup_path, path, error);
1771     if (error) {
1772       LOG(ERROR) << "Failed to restore backup path: " << backup_path
1773                  << " (" << error.message() << ")";
1774       return false;
1775     }
1776   }
1777   return true;
1778 }
1779
1780 std::vector<fs::path> SetupBackupDirectories(uid_t test_uid) {
1781   std::vector<fs::path> entries;
1782   fs::path db_dir = fs::path(tzplatform_getenv(TZ_SYS_DB));
1783   if (test_uid != kGlobalUserUid)
1784     db_dir = db_dir / "user" / std::to_string(test_uid);
1785   for (auto e : kDBEntries) {
1786     fs::path path = db_dir / e;
1787     entries.emplace_back(path);
1788   }
1789
1790   if (getuid() == 0) {
1791     entries.emplace_back(kPreloadApps);
1792     entries.emplace_back(kPreloadManifestDir);
1793     entries.emplace_back(kPreloadIcons);
1794   }
1795
1796   if (test_uid == kGlobalUserUid) {
1797     entries.emplace_back(kSkelDir);
1798     entries.emplace_back(kGlobalManifestDir);
1799     ci::UserList list = ci::GetUserList();
1800     for (auto l : list) {
1801       fs::path apps = std::get<2>(l) / "apps_rw";
1802       entries.emplace_back(apps);
1803     }
1804   } else {
1805     tzplatform_set_user(test_uid);
1806     fs::path approot = tzplatform_getenv(TZ_USER_APPROOT);
1807     tzplatform_reset_user();
1808     entries.emplace_back(approot);
1809   }
1810
1811   fs::path apps_rw = ci::GetRootAppPath(false, test_uid);
1812   entries.emplace_back(apps_rw);
1813   entries.emplace_back(kSdkDirectory);
1814
1815   return entries;
1816 }
1817
1818 void UninstallAllAppsInDirectory(fs::path dir, bool is_preload,
1819     BackendInterface* backend) {
1820   if (fs::exists(dir)) {
1821     for (auto& dir_entry : fs::directory_iterator(dir)) {
1822       if (dir_entry.path().string().find("smoke") != std::string::npos &&
1823           fs::is_directory(dir_entry)) {
1824         std::string package = dir_entry.path().filename().string();
1825         std::regex pkg_regex("smoke[a-zA-Z0-9]{5,}");
1826         if (std::regex_match(package, pkg_regex)) {
1827           BackendInterface::CommandResult result =
1828               BackendInterface::CommandResult::OK;
1829           if (is_preload)
1830             result = backend->UninstallPreload(
1831                 dir_entry.path().filename().string());
1832           else
1833             result = backend->Uninstall(
1834                 dir_entry.path().filename().string());
1835           if (result != BackendInterface::CommandResult::OK) {
1836             LOG(ERROR) << "Cannot uninstall smoke test app: "
1837                 << dir_entry.path().filename().string();
1838           }
1839         }
1840       }
1841     }
1842   }
1843 }
1844
1845 void UninstallAllSmokeApps(ci::RequestMode request_mode, uid_t test_uid,
1846     BackendInterface *backend) {
1847   std::cout << "Uninstalling all smoke apps" << std::endl;
1848   fs::path apps_rw = ci::GetRootAppPath(false, test_uid);
1849   UninstallAllAppsInDirectory(apps_rw, false, backend);
1850   if (getuid() == 0 && request_mode == ci::RequestMode::GLOBAL) {
1851     fs::path root_path = kPreloadApps;
1852     UninstallAllAppsInDirectory(root_path, true, backend);
1853   }
1854 }
1855
1856 int GetAppInstalledTime(const char* appid, uid_t uid) {
1857   int ret = 0;
1858   int installed_time = 0;
1859   pkgmgrinfo_appinfo_h handle = NULL;
1860   ret = pkgmgrinfo_appinfo_get_usr_appinfo(appid, uid, &handle);
1861   if (ret != PMINFO_R_OK)
1862     return -1;
1863   ret = pkgmgrinfo_appinfo_get_installed_time(handle, &installed_time);
1864   if (ret != PMINFO_R_OK) {
1865     pkgmgrinfo_appinfo_destroy_appinfo(handle);
1866     return -1;
1867   }
1868   pkgmgrinfo_appinfo_destroy_appinfo(handle);
1869   return installed_time;
1870 }
1871
1872 bool CompareFileInfo(const std::string& pkgid, const TestParameters& params,
1873     const fs::path& file) {
1874   FileInfoCollector result(pkgid, params);
1875   if (!result.Init())
1876     return false;
1877
1878   fs::path p = "/tmp";
1879   p /= file.filename();
1880
1881   if (!result.FileInfoToFile(p))
1882     return false;
1883
1884   FileInfoCollector expected(pkgid, params);
1885   if (!expected.LoadFromFile(file))
1886     return false;
1887
1888   return result.IsEqual(expected);
1889 }
1890
1891 }  // namespace smoke_test