[SmokeTest] Add valid packages
[platform/core/appfw/wgt-backend.git] / src / unit_tests / smoke_test.cc
1 // Copyright (c) 2015 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 <boost/filesystem/operations.hpp>
6 #include <boost/filesystem/path.hpp>
7 #include <boost/range/iterator_range.hpp>
8 #include <boost/system/error_code.hpp>
9 #include <boost/format.hpp>
10
11 #include <common/paths.h>
12 #include <common/pkgmgr_interface.h>
13 #include <common/pkgmgr_query.h>
14 #include <common/request.h>
15 #include <common/step/configuration/step_fail.h>
16 #include <common/tzip_interface.h>
17 #include <common/utils/file_util.h>
18 #include <common/utils/subprocess.h>
19 #include <common/utils/user_util.h>
20
21 #include <gtest/gtest.h>
22 #include <gtest/gtest-death-test.h>
23 #include <pkgmgr-info.h>
24 #include <signal.h>
25 #include <unistd.h>
26 #include <tzplatform_config.h>
27 #include <vconf.h>
28 #include <vconf-internal-keys.h>
29 #include <getopt.h>
30
31 #include <array>
32 #include <cstdio>
33 #include <cstdlib>
34 #include <vector>
35 #include <regex>
36
37 #include "hybrid/hybrid_installer.h"
38 #include "wgt/wgt_app_query_interface.h"
39 #include "wgt/wgt_installer.h"
40
41 #define SIZEOFARRAY(ARR)                                                       \
42   sizeof(ARR) / sizeof(ARR[0])                                                 \
43
44 namespace bf = boost::filesystem;
45 namespace bs = boost::system;
46 namespace ci = common_installer;
47
48 namespace {
49 ci::RequestMode kRequestMode = ci::RequestMode::GLOBAL;
50 const char *short_opts = "g:u";
51 const struct option long_opts[] = {
52     { "request_mode", 1, NULL, 'r' },
53     { 0, 0, 0, 0 }  /* sentinel */
54 };
55 const char *request_modes[] {
56      "global",
57      "user"
58 };
59 void ParseRequestMode(int argc,  char** argv) {
60   int c;
61   int opt_idx = 0;
62   do {
63     c = getopt_long(argc, argv, short_opts, long_opts, &opt_idx);
64     switch (c) {
65     case 'r':
66       if (strncmp(optarg, request_modes[0], strlen(request_modes[0])) == 0)
67         kRequestMode = ci::RequestMode::GLOBAL;
68       else if (strncmp(optarg, request_modes[1], strlen(request_modes[1])) == 0)
69         kRequestMode = ci::RequestMode::USER;
70       else
71         LOG(ERROR) << "Wrong request mode " << optarg
72                    << ". Available: \"global\" or \"user\"";
73       break;
74     case 'g':
75       kRequestMode = ci::RequestMode::GLOBAL;
76       break;
77     case 'u':
78       kRequestMode = ci::RequestMode::USER;
79       break;
80     default:
81       break;
82     }
83   } while (c != -1);
84 }
85
86 const uid_t kGlobalUserUid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
87 const uid_t kGlobalUserGid = tzplatform_getgid(TZ_SYS_GLOBALAPP_USER);
88 const uid_t kDefaultUserUid = tzplatform_getuid(TZ_SYS_DEFAULT_USER);
89 uid_t kTestUserId = kGlobalUserUid;
90 gid_t kTestGroupId = kGlobalUserGid;
91 std::string kTestUserIdStr = std::to_string(kTestUserId);
92 const char kNormalUserName[] = "smokeuser";
93 const char kSystemShareGroupName[] = "system_share";
94 const std::string& kDefaultUserIdStr = std::to_string(kDefaultUserUid);
95 const char kLegacyExtImageDir[] = "legacy_extimage_dir";
96 const char kMigrateTestDBName[] = "app2sd_migrate.db";
97
98 const bf::path kSmokePackagesDirectory =
99     "/usr/share/wgt-backend-ut/test_samples/smoke/";
100
101 enum RWDirectory {
102     DATA,
103     CACHE,
104     SHARED_CACHE,
105     SHARED_DATA,
106     SHARED_TRUSTED
107 };
108
109 const char* rwDirectories[] = {
110   "data",
111   "cache",
112   "shared/cache",
113   "shared/data",
114   "shared/trusted",
115 };
116
117 // common entries
118 const std::vector<std::string> kDBEntries = {
119   {".pkgmgr_parser.db"},
120   {".pkgmgr_parser.db-journal"},
121   {".pkgmgr_cert.db"},
122   {".pkgmgr_cert.db-journal"},
123   {".app2sd.db"},
124   {".app2sd.db-journal"},
125 };
126 // globaluser entries
127 const char kGlobalManifestDir[] = "/opt/share/packages";
128 const char kSkelDir[] = "/etc/skel/apps_rw";
129 const char kPreloadApps[] = "/usr/apps";
130 const char kPreloadManifestDir[] = "/usr/share/packages";
131 const char kPreloadIcons[] = "/usr/share/icons";
132
133 enum class RequestResult {
134   NORMAL,
135   FAIL
136 };
137
138 class ScopedTzipInterface {
139  public:
140   explicit ScopedTzipInterface(const std::string& pkgid)
141       : pkg_path_(bf::path(ci::GetRootAppPath(false,
142             kTestUserId)) / pkgid),
143         interface_(ci::GetMountLocation(pkg_path_)),
144         mounted_(true) {
145     interface_.MountZip(ci::GetZipPackageLocation(pkg_path_, pkgid));
146   }
147
148   void Release() {
149     if (mounted_) {
150       interface_.UnmountZip();
151       mounted_ = false;
152     }
153   }
154
155   ~ScopedTzipInterface() {
156     Release();
157   }
158
159  private:
160   bf::path pkg_path_;
161   ci::TzipInterface interface_;
162   bool mounted_;
163 };
164
165 class TestPkgmgrInstaller : public ci::PkgmgrInstallerInterface {
166  public:
167   bool CreatePkgMgrInstaller(pkgmgr_installer** installer,
168                              ci::InstallationMode* mode) {
169     *installer = pkgmgr_installer_offline_new();
170     if (!*installer)
171       return false;
172     *mode = ci::InstallationMode::ONLINE;
173     return true;
174   }
175
176   bool ShouldCreateSignal() const {
177     return false;
178   }
179 };
180
181 enum class PackageType {
182   WGT,
183   HYBRID
184 };
185
186 bool TouchFile(const bf::path& path) {
187   FILE* f = fopen(path.c_str(), "w+");
188   if (!f)
189     return false;
190   fclose(f);
191   return true;
192 }
193
194 bool AddTestUser(const char *user_name) {
195   std::cout << "Adding test user: " << user_name << std::endl;
196   gboolean ret = ci::AddUser(user_name);
197   if (boost::optional<uid_t> uid = ci::GetUidByUserName(user_name)) {
198     kTestUserId = *uid;
199     kTestUserIdStr = std::to_string(kTestUserId);
200     std::cout << "User created properly: uid=" << *uid;
201     if (boost::optional<gid_t> gid = ci::GetGidByUid(*uid)) {
202       kTestGroupId = *gid;
203       std::cout << " gid=" << *gid;
204     }
205     std::cout << std::endl;
206     return true;
207   }
208   LOG(ERROR) << "Adding test user failed";
209   return false;
210 }
211
212 bool DeleteTestUser(const char *user_name) {
213   std::cout << "Deleting test user: " << user_name << std::endl;
214   uid_t test_uid;
215   if (boost::optional<uid_t> uid = ci::GetUidByUserName(user_name))
216     test_uid = *uid;
217   gboolean ret = ci::DeleteUser(user_name, true);
218   if (boost::optional<uid_t> uid = ci::GetUidByUserName(user_name));
219   else {
220     std::cout << "User deleted properly: user_name=" << user_name
221               << " uid=" << test_uid << std::endl;
222     return true;
223   }
224   LOG(ERROR) << "Deleting test user failed";
225   return false;
226 }
227
228 void RemoveAllRecoveryFiles() {
229   bf::path root_path = ci::GetRootAppPath(false,
230       kTestUserId);
231   if (!bf::exists(root_path))
232     return;
233   for (auto& dir_entry : boost::make_iterator_range(
234          bf::directory_iterator(root_path), bf::directory_iterator())) {
235     if (bf::is_regular_file(dir_entry)) {
236       if (dir_entry.path().string().find("/recovery") != std::string::npos) {
237         bs::error_code error;
238         bf::remove(dir_entry.path(), error);
239       }
240     }
241   }
242 }
243
244 bf::path FindRecoveryFile() {
245   bf::path root_path = ci::GetRootAppPath(false,
246       kTestUserId);
247   for (auto& dir_entry : boost::make_iterator_range(
248          bf::directory_iterator(root_path), bf::directory_iterator())) {
249     if (bf::is_regular_file(dir_entry)) {
250       if (dir_entry.path().string().find("/recovery") != std::string::npos) {
251         return dir_entry.path();
252       }
253     }
254   }
255   return {};
256 }
257
258 bf::path GetPackageRoot(const std::string& pkgid, uid_t uid) {
259   bf::path root_path = ci::GetRootAppPath(false, uid);
260   return root_path / pkgid;
261 }
262
263 bool ValidateFileContentInPackage(const std::string& pkgid,
264                                   const std::string& relative,
265                                   const std::string& expected,
266                                   bool is_readonly = false) {
267   bf::path file_path = ci::GetRootAppPath(is_readonly, kTestUserId);
268   file_path = file_path / pkgid / relative;
269   if (!bf::exists(file_path)) {
270     LOG(ERROR) << file_path << " doesn't exist";
271     return false;
272   }
273   FILE* handle = fopen(file_path.c_str(), "r");
274   if (!handle) {
275     LOG(ERROR) << file_path << " cannot  be open";
276     return false;
277   }
278   std::string content;
279   std::array<char, 200> buffer;
280   while (fgets(buffer.data(), buffer.size(), handle)) {
281     content += buffer.data();
282   }
283   fclose(handle);
284   return content == expected;
285 }
286
287 void AddDataFiles(const std::string& pkgid, uid_t uid) {
288   if (uid == kGlobalUserUid) {
289     ci::UserList list = ci::GetUserList();
290     for (auto l : list) {
291       auto pkg_path = GetPackageRoot(pkgid, std::get<0>(l));
292       ASSERT_TRUE(TouchFile(pkg_path / "data" / "file1.txt"));
293       ASSERT_TRUE(TouchFile(pkg_path / "data" / "file2.txt"));
294     }
295   } else {
296     auto pkg_path = GetPackageRoot(pkgid, uid);
297     ASSERT_TRUE(TouchFile(pkg_path / "data" / "file1.txt"));
298     ASSERT_TRUE(TouchFile(pkg_path / "data" / "file2.txt"));
299   }
300 }
301
302 void ValidateDataFiles(const std::string& pkgid, uid_t uid) {
303   if (uid == kGlobalUserUid) {
304     ci::UserList list = ci::GetUserList();
305     for (auto l : list) {
306       auto pkg_path = GetPackageRoot(pkgid, std::get<0>(l));
307       ASSERT_TRUE(bf::exists(pkg_path / "data" / "file1.txt"));
308       ASSERT_TRUE(bf::exists(pkg_path / "data" / "file2.txt"));
309     }
310   } else {
311     auto pkg_path = GetPackageRoot(pkgid, uid);
312     ASSERT_TRUE(bf::exists(pkg_path / "data" / "file1.txt"));
313     ASSERT_TRUE(bf::exists(pkg_path / "data" / "file2.txt"));
314   }
315 }
316
317 void ValidatePackageRWFS(const std::string& pkgid, uid_t uid) {
318   bf::path root_path = ci::GetRootAppPath(false, uid);
319   bf::path package_path = root_path / pkgid;
320   bf::path data_path = package_path / rwDirectories[DATA];
321   bf::path cache_path = package_path / rwDirectories[CACHE];
322   bf::path shared_data_path = package_path / rwDirectories[SHARED_DATA];
323
324   ASSERT_TRUE(bf::exists(data_path));
325   ASSERT_TRUE(bf::exists(cache_path));
326
327   struct stat stats;
328   stat(data_path.c_str(), &stats);
329   // gid of RW dirs should be system_share
330   boost::optional<gid_t> system_share =
331     ci::GetGidByGroupName(kSystemShareGroupName);
332   ASSERT_EQ(uid, stats.st_uid) << "Invalid gid: " << data_path;
333   ASSERT_EQ(*system_share, stats.st_gid) << "Invalid gid: " << data_path;
334   if (bf::exists(shared_data_path)) {
335     stat(shared_data_path.c_str(), &stats);
336     ASSERT_EQ(uid, stats.st_uid) << "Invalid gid: " << shared_data_path;
337     ASSERT_EQ(*system_share, stats.st_gid) << "Invalid gid: "
338       << shared_data_path;
339   }
340
341   stat(cache_path.c_str(), &stats);
342   ASSERT_EQ(uid, stats.st_uid) << "Invalid gid: " << cache_path;
343   ASSERT_EQ(*system_share, stats.st_gid) << "Invalid gid: " << cache_path;
344 }
345
346 void ValidatePackageFS(const std::string& pkgid,
347                        const std::vector<std::string>& appids,
348                        uid_t uid, gid_t gid, bool is_readonly) {
349   bf::path root_path = ci::GetRootAppPath(is_readonly, uid);
350   bf::path package_path = root_path / pkgid;
351   bf::path shared_path = package_path / "shared";
352   ASSERT_TRUE(bf::exists(root_path));
353   ASSERT_TRUE(bf::exists(package_path));
354   ASSERT_TRUE(bf::exists(shared_path));
355
356   bf::path manifest_path =
357       bf::path(getUserManifestPath(uid, is_readonly)) / (pkgid + ".xml");
358   ASSERT_TRUE(bf::exists(manifest_path));
359
360   for (auto& appid : appids) {
361     bf::path binary_path = package_path / "bin" / appid;
362     ASSERT_TRUE(bf::exists(binary_path));
363   }
364
365   bf::path widget_root_path = package_path / "res" / "wgt";
366   bf::path config_path = widget_root_path / "config.xml";
367   ASSERT_TRUE(bf::exists(widget_root_path));
368   ASSERT_TRUE(bf::exists(config_path));
369
370   bf::path private_tmp_path = package_path / "tmp";
371   ASSERT_TRUE(bf::exists(private_tmp_path));
372
373   // backups should not exist
374   bf::path package_backup = ci::GetBackupPathForPackagePath(package_path);
375   bf::path manifest_backup = ci::GetBackupPathForManifestFile(manifest_path);
376   ASSERT_FALSE(bf::exists(package_backup));
377   ASSERT_FALSE(bf::exists(manifest_backup));
378
379   for (bf::recursive_directory_iterator iter(package_path);
380       iter != bf::recursive_directory_iterator(); ++iter) {
381     if (bf::is_symlink(symlink_status(iter->path())))
382       continue;
383     bool is_rw_dir = false;
384     for(const auto rw_dir : rwDirectories) {
385       bf::path rw_dir_path = rw_dir;
386       is_rw_dir |= ci::MakeRelativePath(iter->path(), package_path) == rw_dir_path;
387     }
388     if (is_rw_dir || iter->path().filename() == ".mmc") {
389       iter.no_push();
390       continue;
391     }
392     struct stat stats;
393     stat(iter->path().c_str(), &stats);
394     ASSERT_EQ(uid, stats.st_uid) << "Invalid uid: " << iter->path();
395     ASSERT_EQ(gid, stats.st_gid) << "Invalid gid: " << iter->path();
396   }
397 }
398
399 void PackageCheckCleanup(const std::string& pkgid,
400     const std::vector<std::string>&, bool is_readonly = false) {
401   bf::path root_path = ci::GetRootAppPath(is_readonly, kTestUserId);
402   bf::path package_path = root_path / pkgid;
403   ASSERT_FALSE(bf::exists(package_path));
404
405   bf::path manifest_path = bf::path(getUserManifestPath(kTestUserId,
406       is_readonly)) / (pkgid + ".xml");
407   ASSERT_FALSE(bf::exists(manifest_path));
408
409   // backups should not exist
410   bf::path package_backup = ci::GetBackupPathForPackagePath(package_path);
411   bf::path manifest_backup = ci::GetBackupPathForManifestFile(manifest_path);
412   ASSERT_FALSE(bf::exists(package_backup));
413   ASSERT_FALSE(bf::exists(manifest_backup));
414 }
415
416 void ValidatePackage(const std::string& pkgid,
417     const std::vector<std::string>& appids, bool is_readonly = false) {
418   ASSERT_TRUE(ci::QueryIsPackageInstalled(
419       pkgid, ci::GetRequestMode(kTestUserId), kTestUserId));
420   ValidatePackageFS(pkgid, appids, kTestUserId, kTestGroupId, is_readonly);
421   if (kTestUserId == kGlobalUserUid) {
422     ci::UserList list = ci::GetUserList();
423     for (auto& l : list)
424       ValidatePackageRWFS(pkgid, std::get<0>(l));
425   } else {
426     ValidatePackageRWFS(pkgid, kTestUserId);
427   }
428 }
429
430 void ValidateExternalPackageFS(const std::string& pkgid,
431                                const std::vector<std::string>& appids,
432                                uid_t uid, gid_t gid) {
433   ASSERT_EQ(app2ext_usr_enable_external_pkg(pkgid.c_str(), uid), 0);
434   bf::path root_path = ci::GetRootAppPath(false, uid);
435   ASSERT_TRUE(bf::exists(root_path / pkgid / ".mmc" / "res"));
436   ValidatePackageFS(pkgid, appids, uid, gid, false);
437   ASSERT_EQ(app2ext_usr_disable_external_pkg(pkgid.c_str(), uid), 0);
438 }
439
440 void ValidateExternalPackage(const std::string& pkgid,
441                              const std::vector<std::string>& appids) {
442   ASSERT_TRUE(ci::QueryIsPackageInstalled(
443       pkgid, ci::GetRequestMode(kTestUserId),
444       kTestUserId));
445   std::string storage = ci::QueryStorageForPkgId(pkgid, kTestUserId);
446   bf::path ext_mount_path = ci::GetExternalCardPath();
447   if (bf::is_empty(ext_mount_path)) {
448     LOG(INFO) << "Sdcard not exists!";
449     ASSERT_EQ(storage, "installed_internal");
450   } else {
451     ASSERT_EQ(storage, "installed_external");
452   }
453   ValidateExternalPackageFS(pkgid, appids, kTestUserId, kTestGroupId);
454   if (kTestUserId == kGlobalUserUid) {
455     ci::UserList list = ci::GetUserList();
456     for (auto& l : list)
457       ValidatePackageRWFS(pkgid, std::get<0>(l));
458   } else {
459     ValidatePackageRWFS(pkgid, kTestUserId);
460   }
461 }
462
463 void CheckPackageNonExistance(const std::string& pkgid,
464                               const std::vector<std::string>& appids) {
465   ASSERT_FALSE(ci::QueryIsPackageInstalled(
466       pkgid, ci::GetRequestMode(kTestUserId),
467       kTestUserId));
468   PackageCheckCleanup(pkgid, appids);
469   if (kTestUserId == kGlobalUserUid) {
470       ci::UserList list = ci::GetUserList();
471       bf::path skel_path(kSkelDir);
472       ASSERT_FALSE(bf::exists(skel_path / pkgid));
473       for (auto& l : list) {
474         bf::path root_path = ci::GetRootAppPath(false, std::get<0>(l));
475         bf::path package_path = root_path / pkgid;
476         ASSERT_FALSE(bf::exists(package_path));
477       }
478   }
479 }
480
481 void CheckPackageReadonlyNonExistance(const std::string& pkgid,
482                                       const std::vector<std::string>& appids) {
483   ASSERT_FALSE(ci::QueryIsPackageInstalled(
484       pkgid, ci::GetRequestMode(kTestUserId), kTestUserId));
485   PackageCheckCleanup(pkgid, appids, true);
486 }
487
488 std::unique_ptr<ci::AppQueryInterface> CreateQueryInterface() {
489   std::unique_ptr<ci::AppQueryInterface> query_interface(
490       new wgt::WgtAppQueryInterface());
491   return query_interface;
492 }
493
494 std::unique_ptr<ci::AppInstaller> CreateInstaller(ci::PkgMgrPtr pkgmgr,
495                                                   PackageType type) {
496   switch (type) {
497     case PackageType::WGT:
498       return std::unique_ptr<ci::AppInstaller>(new wgt::WgtInstaller(pkgmgr));
499     case PackageType::HYBRID:
500       return std::unique_ptr<ci::AppInstaller>(
501           new hybrid::HybridInstaller(pkgmgr));
502     default:
503       LOG(ERROR) << "Unknown installer type";
504       return nullptr;
505   }
506 }
507
508 ci::AppInstaller::Result RunInstallerWithPkgrmgr(ci::PkgMgrPtr pkgmgr,
509                                                  PackageType type,
510                                                  RequestResult mode) {
511   std::unique_ptr<ci::AppInstaller> installer = CreateInstaller(pkgmgr, type);
512   switch (mode) {
513   case RequestResult::FAIL:
514     installer->AddStep<ci::configuration::StepFail>();
515     break;
516   default:
517     break;
518   }
519   return installer->Run();
520 }
521 ci::AppInstaller::Result CallBackend(int argc,
522                                      const char* argv[],
523                                      PackageType type,
524                                      RequestResult mode = RequestResult::NORMAL
525                                      ) {
526   TestPkgmgrInstaller pkgmgr_installer;
527   std::unique_ptr<ci::AppQueryInterface> query_interface =
528       CreateQueryInterface();
529   auto pkgmgr =
530       ci::PkgMgrInterface::Create(argc, const_cast<char**>(argv),
531                                   &pkgmgr_installer, query_interface.get());
532   if (!pkgmgr) {
533     LOG(ERROR) << "Failed to initialize pkgmgr interface";
534     return ci::AppInstaller::Result::UNKNOWN;
535   }
536   return RunInstallerWithPkgrmgr(pkgmgr, type, mode);
537 }
538
539 ci::AppInstaller::Result Install(const bf::path& path,
540                                  PackageType type,
541                                  RequestResult mode = RequestResult::NORMAL) {
542   const char* argv[] = {"", "-i", path.c_str(), "-u", kTestUserIdStr.c_str()};
543   return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
544 }
545
546 ci::AppInstaller::Result InstallPreload(const bf::path& path, PackageType type,
547     RequestResult mode = RequestResult::NORMAL) {
548   const char* argv[] = {"", "-i", path.c_str(), "--preload"};
549   return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
550 }
551
552 bool CheckAvailableExternalPath() {
553   bf::path ext_mount_path = ci::GetExternalCardPath();
554   LOG(DEBUG) << "ext_mount_path :" << ext_mount_path;
555   if (ext_mount_path.empty()) {
556     LOG(ERROR) << "Sdcard not exists!";
557     return false;
558   }
559   return true;
560 }
561
562 ci::AppInstaller::Result InstallExternal(const bf::path& path,
563                                  PackageType type,
564                                  RequestResult mode = RequestResult::NORMAL) {
565   int default_storage = 0;
566   vconf_get_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT,
567                 &default_storage);
568   vconf_set_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT, 1);
569
570   const char* argv[] = {"", "-i", path.c_str(), "-u", kTestUserIdStr.c_str()};
571   ci::AppInstaller::Result result =
572                           CallBackend(SIZEOFARRAY(argv), argv, type, mode);
573
574   vconf_set_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT,
575                 default_storage);
576   return result;
577 }
578
579 ci::AppInstaller::Result MigrateLegacyExternalImage(const std::string& pkgid,
580                                  const bf::path& path,
581                                  const bf::path& legacy_path,
582                                  PackageType type,
583                                  RequestResult mode = RequestResult::NORMAL) {
584   if (InstallExternal(path, type) != ci::AppInstaller::Result::OK) {
585     LOG(ERROR) << "Failed to install application. Cannot perform Migrate";
586     return ci::AppInstaller::Result::ERROR;
587   }
588
589   bf::path ext_mount_path = ci::GetExternalCardPath();
590   if (bf::is_empty(ext_mount_path)) {
591     LOG(ERROR) << "Sdcard not exists!";
592     return ci::AppInstaller::Result::ERROR;
593   }
594   bf::path app2sd_path = ext_mount_path / "app2sd";
595
596   char* image_name = app2ext_usr_getname_image(pkgid.c_str(),
597                      kGlobalUserUid);
598   if (!image_name) {
599     LOG(ERROR) << "Failed to get external image name";
600     return ci::AppInstaller::Result::ERROR;
601   }
602   bf::path org_image = app2sd_path / image_name;
603   free(image_name);
604
605   bs::error_code error;
606   bf::remove(org_image, error);
607   if (error) {
608     LOG(ERROR) << "Failed to remove org image";
609     return ci::AppInstaller::Result::ERROR;
610   }
611
612   bf::path db_path = tzplatform_getenv(TZ_SYS_DB);
613   bf::path app2sd_db = db_path / ".app2sd.db";
614   bf::path app2sd_db_journal = db_path / ".app2sd.db-journal";
615   bf::remove(app2sd_db, error);
616   if (error) {
617     LOG(ERROR) << "Failed to remove app2sd db";
618     return ci::AppInstaller::Result::ERROR;
619   }
620   bf::remove(app2sd_db_journal, error);
621   if (error) {
622     LOG(ERROR) << "Failed to remove app2sd journal db";
623     return ci::AppInstaller::Result::ERROR;
624   }
625
626   bf::path app2sd_migrate_db = legacy_path / kMigrateTestDBName;
627   if (!ci::CopyFile(app2sd_migrate_db, app2sd_db)) {
628     LOG(ERROR) << "Failed to copy test db";
629     return ci::AppInstaller::Result::ERROR;
630   }
631
632   bf::path legacy_src = legacy_path / pkgid;
633   bf::path legacy_dst = app2sd_path / pkgid;
634   if (!ci::CopyFile(legacy_src, legacy_dst)) {
635     LOG(ERROR) << "Failed to copy test image";
636     return ci::AppInstaller::Result::ERROR;
637   }
638   const char* argv[] = {"", "--migrate-extimg", pkgid.c_str(),
639                        "-u", kDefaultUserIdStr.c_str()};
640   return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
641 }
642
643 ci::AppInstaller::Result MountInstall(const bf::path& path,
644     PackageType type, RequestResult mode = RequestResult::NORMAL) {
645   const char* argv[] = {"", "-w", path.c_str(), "-u", kTestUserIdStr.c_str()};
646   return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
647 }
648
649 ci::AppInstaller::Result Uninstall(const std::string& pkgid,
650                                    PackageType type,
651                                    bool is_preload,
652                                    RequestResult mode = RequestResult::NORMAL) {
653   if (is_preload) {
654     const char* argv[] = {"", "-d", pkgid.c_str(), "--preload",
655         "--force-remove"};
656     return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
657   } else {
658     const char* argv[] = {"", "-d", pkgid.c_str(), "-u",
659         kTestUserIdStr.c_str()};
660     return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
661   }
662 }
663
664 ci::AppInstaller::Result RDSUpdate(const bf::path& path,
665                                    const std::string& pkgid,
666                                    PackageType type,
667                                    RequestResult mode = RequestResult::NORMAL) {
668   if (Install(path, type) != ci::AppInstaller::Result::OK) {
669     LOG(ERROR) << "Failed to install application. Cannot perform RDS";
670     return ci::AppInstaller::Result::UNKNOWN;
671   }
672   const char* argv[] = {"", "-r", pkgid.c_str(), "-u",
673                         kTestUserIdStr.c_str()};
674   return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
675 }
676
677 ci::AppInstaller::Result DeltaInstall(const bf::path& path,
678     const bf::path& delta_package, PackageType type) {
679   if (Install(path, type) != ci::AppInstaller::Result::OK) {
680     LOG(ERROR) << "Failed to install application. Cannot perform delta update";
681     return ci::AppInstaller::Result::UNKNOWN;
682   }
683   return Install(delta_package, type);
684 }
685
686 ci::AppInstaller::Result EnablePackage(const std::string& pkgid,
687                                   PackageType type,
688                                   RequestResult mode = RequestResult::NORMAL) {
689   const char* argv[] = {"", "-A", pkgid.c_str(), "-u", kTestUserIdStr.c_str()};
690   return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
691 }
692
693 ci::AppInstaller::Result DisablePackage(const std::string& pkgid,
694                                   PackageType type,
695                                   RequestResult mode = RequestResult::NORMAL) {
696   const char* argv[] = {"", "-D", pkgid.c_str(), "-u", kTestUserIdStr.c_str()};
697   return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
698 }
699
700 ci::AppInstaller::Result Recover(const bf::path& recovery_file,
701                                  PackageType type,
702                                  RequestResult mode = RequestResult::NORMAL) {
703   const char* argv[] = {"", "-b", recovery_file.c_str(), "-u",
704                         kTestUserIdStr.c_str()};
705   return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
706 }
707
708 void BackupPath(const bf::path& path) {
709   bf::path backup_path = path.string() + ".bck";
710   std::cout << "Backup path: " << path << " to " << backup_path << std::endl;
711   bs::error_code error;
712   bf::remove_all(backup_path, error);
713   if (error)
714     LOG(ERROR) << "Remove failed: " << backup_path
715                << " (" << error.message() << ")";
716   if (bf::exists(path)) {
717     bf::rename(path, backup_path, error);
718     if (error)
719       LOG(ERROR) << "Failed to setup test environment. Does some previous"
720                  << " test crashed? Path: "
721                  << backup_path << " should not exist.";
722     assert(!error);
723   }
724 }
725
726 void RestorePath(const bf::path& path) {
727   bf::path backup_path = path.string() + ".bck";
728   std::cout << "Restore path: " << path << " from " << backup_path << std::endl;
729   bs::error_code error;
730   bf::remove_all(path, error);
731   if (error)
732     LOG(ERROR) << "Remove failed: " << path
733                << " (" << error.message() << ")";
734   if (bf::exists(backup_path)) {
735     bf::rename(backup_path, path, error);
736     if (error)
737       LOG(ERROR) << "Failed to restore backup path: " << backup_path
738                  << " (" << error.message() << ")";
739   }
740 }
741
742 std::vector<bf::path> SetupBackupDirectories() {
743   std::vector<bf::path> entries;
744   bf::path db_dir = bf::path(tzplatform_getenv(TZ_SYS_DB));
745   if (kTestUserId != kGlobalUserUid)
746     db_dir = db_dir / "user" / std::to_string(kTestUserId);
747   for (auto e : kDBEntries) {
748     bf::path path = db_dir / e;
749     entries.emplace_back(path);
750   }
751
752   if (getuid() == 0) {
753     entries.emplace_back(kPreloadApps);
754     entries.emplace_back(kPreloadManifestDir);
755     entries.emplace_back(kPreloadIcons);
756   }
757
758   if (kTestUserId == kGlobalUserUid) {
759     entries.emplace_back(kSkelDir);
760     entries.emplace_back(kGlobalManifestDir);
761     ci::UserList list = ci::GetUserList();
762     for (auto l : list) {
763       bf::path apps = std::get<2>(l) / "apps_rw";
764       entries.emplace_back(apps);
765     }
766   } else {
767     tzplatform_set_user(kTestUserId);
768     bf::path approot = tzplatform_getenv(TZ_USER_APPROOT);
769     tzplatform_reset_user();
770     entries.emplace_back(approot);
771   }
772
773   bf::path apps_rw = ci::GetRootAppPath(false, kTestUserId);
774   entries.emplace_back(apps_rw);
775
776   return entries;
777 }
778
779 void UninstallAllAppsInDirectory(bf::path dir, bool is_preload) {
780   if(bf::exists(dir)) {
781     for (auto& dir_entry : boost::make_iterator_range(
782         bf::directory_iterator(dir), bf::directory_iterator())) {
783       if (dir_entry.path().string().find("smoke") != std::string::npos &&
784           bf::is_directory(dir_entry)) {
785         std::string package = dir_entry.path().filename().string();
786         std::regex pkg_regex("smoke[a-zA-Z]{3,}[1-9]{2,}");
787         if (std::regex_match(package, pkg_regex)) {
788           if(Uninstall(dir_entry.path().filename().string(), PackageType::WGT,
789               is_preload, RequestResult::NORMAL) !=
790               ci::AppInstaller::Result::OK) {
791             LOG(ERROR) << "Cannot uninstall smoke test app: "
792                 << dir_entry.path().filename().string();
793           }
794         }
795       }
796     }
797   }
798 }
799
800 void UninstallAllSmokeApps() {
801   if (getuid() == 0 && kRequestMode == ci::RequestMode::GLOBAL) {
802     bf::path root_path = kPreloadApps;
803     UninstallAllAppsInDirectory(root_path, true);
804   }
805   bf::path apps_rw = ci::GetRootAppPath(false, kTestUserId);
806   UninstallAllAppsInDirectory(apps_rw, false);
807 }
808
809 }  // namespace
810
811 namespace common_installer {
812
813 class SmokeEnvironment : public testing::Environment {
814  public:
815   explicit SmokeEnvironment() {
816   }
817   void SetUp() override {
818     if (kRequestMode == ci::RequestMode::USER)
819       ASSERT_TRUE(AddTestUser(kNormalUserName));
820     else {
821       kTestUserId = kGlobalUserUid;
822       kTestGroupId = kGlobalUserGid;
823       kTestUserIdStr = std::to_string(kTestUserId);
824     }
825     backups_ = SetupBackupDirectories();
826     for (auto& path : backups_)
827       BackupPath(path);
828   }
829   void TearDown() override {
830     ASSERT_TRUE(kRequestMode == ci::RequestMode::GLOBAL ||
831                 (kRequestMode == ci::RequestMode::USER &&
832                 kGlobalUserUid != kTestUserId));
833     UninstallAllSmokeApps();
834     for (auto& path : backups_)
835       RestorePath(path);
836     if (kRequestMode == ci::RequestMode::USER)
837       ASSERT_TRUE(DeleteTestUser(kNormalUserName));
838   }
839
840  private:
841   std::vector<bf::path> backups_;
842 };
843
844 class SmokeTest : public testing::Test {
845 };
846
847 class PreloadSmokeTest : public testing::Test {
848   void SetUp() override {
849     ASSERT_TRUE(kRequestMode == ci::RequestMode::GLOBAL);
850   }
851 };
852
853 TEST_F(SmokeTest, InstallationMode) {
854   bf::path path = kSmokePackagesDirectory / "InstallationMode.wgt";
855   std::string pkgid = "smokewgt03";
856   std::string appid = "smokewgt03.InstallationMode";
857   ASSERT_EQ(Install(path, PackageType::WGT), ci::AppInstaller::Result::OK);
858   ValidatePackage(pkgid, {appid});
859 }
860
861 TEST_F(SmokeTest, UpdateMode) {
862   bf::path path_old = kSmokePackagesDirectory / "UpdateMode.wgt";
863   bf::path path_new = kSmokePackagesDirectory / "UpdateMode_2.wgt";
864   std::string pkgid = "smokewgt04";
865   std::string appid = "smokewgt04.UpdateMode";
866   ASSERT_EQ(Install(path_old, PackageType::WGT), ci::AppInstaller::Result::OK);
867   AddDataFiles(pkgid, kTestUserId);
868   ASSERT_EQ(Install(path_new, PackageType::WGT), ci::AppInstaller::Result::OK);
869   ValidatePackage(pkgid, {appid});
870
871   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "2\n"));
872   ValidateDataFiles(pkgid, kTestUserId);
873 }
874
875 TEST_F(SmokeTest, DeinstallationMode) {
876   bf::path path = kSmokePackagesDirectory / "DeinstallationMode.wgt";
877   std::string pkgid = "smokewgt05";
878   std::string appid = "smokewgt05.DeinstallationMode";
879   ASSERT_EQ(Install(path, PackageType::WGT),
880             ci::AppInstaller::Result::OK);
881   ASSERT_EQ(Uninstall(pkgid, PackageType::WGT, false),
882             ci::AppInstaller::Result::OK);
883   CheckPackageNonExistance(pkgid, {appid});
884 }
885
886 TEST_F(SmokeTest, RDSMode) {
887   bf::path path = kSmokePackagesDirectory / "RDSMode.wgt";
888   std::string pkgid = "smokewgt11";
889   std::string appid = "smokewgt11.RDSMode";
890   bf::path delta_directory = kSmokePackagesDirectory / "delta_dir/";
891   bf::path sdk_expected_directory =
892       bf::path(ci::GetRootAppPath(false, kTestUserId)) / "tmp" / pkgid;
893   bs::error_code error;
894   bf::create_directories(sdk_expected_directory.parent_path(), error);
895   ASSERT_FALSE(error);
896   ASSERT_TRUE(CopyDir(delta_directory, sdk_expected_directory));
897   ASSERT_EQ(RDSUpdate(path, pkgid, PackageType::WGT),
898             ci::AppInstaller::Result::OK);
899   ValidatePackage(pkgid, {appid});
900
901   // Check delta modifications
902   ASSERT_FALSE(bf::exists(GetPackageRoot(pkgid, kTestUserId) /
903       "res" / "wgt" / "DELETED"));
904   ASSERT_TRUE(bf::exists(GetPackageRoot(pkgid, kTestUserId) /
905       "res" / "wgt" / "ADDED"));
906   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/MODIFIED", "2\n"));
907 }
908
909 TEST_F(SmokeTest, EnablePkg) {
910   bf::path path = kSmokePackagesDirectory / "EnablePkg.wgt";
911   std::string pkgid = "smokewgt22";
912   ASSERT_EQ(Install(path, PackageType::WGT),
913             ci::AppInstaller::Result::OK);
914   ASSERT_EQ(DisablePackage(pkgid, PackageType::WGT),
915             ci::AppInstaller::Result::OK);
916   ASSERT_EQ(EnablePackage(pkgid, PackageType::WGT),
917             ci::AppInstaller::Result::OK);
918
919   ASSERT_TRUE(ci::QueryIsPackageInstalled(pkgid,
920       ci::GetRequestMode(kTestUserId),
921       kTestUserId));
922 }
923
924 TEST_F(SmokeTest, DisablePkg) {
925   bf::path path = kSmokePackagesDirectory / "DisablePkg.wgt";
926   std::string pkgid = "smokewgt21";
927   std::string appid = "smokewgt21.DisablePkg";
928   ASSERT_EQ(Install(path, PackageType::WGT),
929             ci::AppInstaller::Result::OK);
930   ASSERT_EQ(DisablePackage(pkgid, PackageType::WGT),
931             ci::AppInstaller::Result::OK);
932   ASSERT_TRUE(ci::QueryIsDisabledPackage(pkgid, kTestUserId));
933   ValidatePackage(pkgid, {appid});
934 }
935
936 TEST_F(SmokeTest, DeltaMode) {
937   bf::path path = kSmokePackagesDirectory / "DeltaMode.wgt";
938   bf::path delta_package = kSmokePackagesDirectory / "DeltaMode.delta";
939   std::string pkgid = "smokewgt17";
940   std::string appid = "smokewgt17.DeltaMode";
941   ASSERT_EQ(DeltaInstall(path, delta_package, PackageType::WGT),
942             ci::AppInstaller::Result::OK);
943   ValidatePackage(pkgid, {appid});
944
945   // Check delta modifications
946   ASSERT_FALSE(bf::exists(GetPackageRoot(pkgid, kTestUserId) /
947       "res" / "wgt" / "DELETED"));
948   ASSERT_TRUE(bf::exists(GetPackageRoot(pkgid, kTestUserId) /
949       "res" / "wgt" / "ADDED"));
950   ASSERT_TRUE(bf::exists(GetPackageRoot(pkgid, kTestUserId) /
951       "res" / "wgt" / "css" / "style.css"));
952   ASSERT_TRUE(bf::exists(GetPackageRoot(pkgid, kTestUserId) /
953       "res" / "wgt" / "images" / "tizen_32.png"));
954   ASSERT_TRUE(bf::exists(GetPackageRoot(pkgid, kTestUserId) /
955       "res" / "wgt" / "js" / "main.js"));
956   ASSERT_TRUE(ValidateFileContentInPackage(
957       pkgid, "res/wgt/MODIFIED", "version 2\n"));
958 }
959
960 TEST_F(SmokeTest, RecoveryMode_ForInstallation) {
961   bf::path path = kSmokePackagesDirectory / "RecoveryMode_ForInstallation.wgt";
962   Subprocess backend_crash("/usr/bin/wgt-backend-ut/smoke-test-helper");
963   backend_crash.Run("-i", path.string(), "-u", kTestUserIdStr.c_str());
964   ASSERT_NE(backend_crash.Wait(), 0);
965
966   std::string pkgid = "smokewgt09";
967   std::string appid = "smokewgt09.RecoveryModeForInstallation";
968   bf::path recovery_file = FindRecoveryFile();
969   ASSERT_FALSE(recovery_file.empty());
970   ASSERT_EQ(Recover(recovery_file, PackageType::WGT),
971       ci::AppInstaller::Result::OK);
972   CheckPackageNonExistance(pkgid, {appid});
973 }
974
975 TEST_F(SmokeTest, RecoveryMode_ForUpdate) {
976   bf::path path_old = kSmokePackagesDirectory / "RecoveryMode_ForUpdate.wgt";
977   bf::path path_new = kSmokePackagesDirectory / "RecoveryMode_ForUpdate_2.wgt";
978   RemoveAllRecoveryFiles();
979   ASSERT_EQ(Install(path_old, PackageType::WGT), ci::AppInstaller::Result::OK);
980   std::string pkgid = "smokewgt10";
981   std::string appid = "smokewgt10.RecoveryModeForUpdate";
982   AddDataFiles(pkgid, kTestUserId);
983   Subprocess backend_crash("/usr/bin/wgt-backend-ut/smoke-test-helper");
984   backend_crash.Run("-i", path_new.string(), "-u", kTestUserIdStr.c_str());
985   ASSERT_NE(backend_crash.Wait(), 0);
986
987   bf::path recovery_file = FindRecoveryFile();
988   ASSERT_FALSE(recovery_file.empty());
989   ASSERT_EQ(Recover(recovery_file, PackageType::WGT),
990             ci::AppInstaller::Result::OK);
991   ValidatePackage(pkgid, {appid});
992
993   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "1\n"));
994   ValidateDataFiles(pkgid, kTestUserId);
995 }
996
997 TEST_F(SmokeTest, RecoveryMode_ForDelta) {
998   bf::path path_old = kSmokePackagesDirectory / "RecoveryMode_ForDelta.wgt";
999   bf::path path_new = kSmokePackagesDirectory / "RecoveryMode_ForDelta.delta";
1000   RemoveAllRecoveryFiles();
1001   ASSERT_EQ(Install(path_old, PackageType::WGT), ci::AppInstaller::Result::OK);
1002   Subprocess backend_crash("/usr/bin/wgt-backend-ut/smoke-test-helper");
1003   backend_crash.Run("-i", path_new.string(), "-u", kTestUserIdStr.c_str());
1004   ASSERT_NE(backend_crash.Wait(), 0);
1005
1006   std::string pkgid = "smokewgt30";
1007   std::string appid = "smokewgt30.RecoveryModeForDelta";
1008   bf::path recovery_file = FindRecoveryFile();
1009   ASSERT_FALSE(recovery_file.empty());
1010   ASSERT_EQ(Recover(recovery_file, PackageType::WGT),
1011             ci::AppInstaller::Result::OK);
1012   ValidatePackage(pkgid, {appid});
1013
1014   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "1\n"));
1015 }
1016
1017 TEST_F(SmokeTest, RecoveryMode_ForMountInstall) {
1018   bf::path path = kSmokePackagesDirectory / "RecoveryMode_ForMountInstall.wgt";
1019   RemoveAllRecoveryFiles();
1020   Subprocess backend_crash("/usr/bin/wgt-backend-ut/smoke-test-helper");
1021   backend_crash.Run("-w", path.string(), "-u", kTestUserIdStr.c_str());
1022   ASSERT_NE(backend_crash.Wait(), 0);
1023
1024   std::string pkgid = "smokewgt31";
1025   std::string appid = "smokewgt31.RecoveryModeForMountInstall";
1026   bf::path recovery_file = FindRecoveryFile();
1027   ASSERT_FALSE(recovery_file.empty());
1028   ASSERT_EQ(Recover(recovery_file, PackageType::WGT),
1029             ci::AppInstaller::Result::OK);
1030   CheckPackageNonExistance(pkgid, {appid});
1031 }
1032
1033 TEST_F(SmokeTest, RecoveryMode_ForMountUpdate) {
1034   bf::path path_old =
1035       kSmokePackagesDirectory / "RecoveryMode_ForMountUpdate.wgt";
1036   bf::path path_new =
1037       kSmokePackagesDirectory / "RecoveryMode_ForMountUpdate_2.wgt";
1038   std::string pkgid = "smokewgt32";
1039   std::string appid = "smokewgt32.RecoveryModeForMountUpdate";
1040   RemoveAllRecoveryFiles();
1041   ASSERT_EQ(MountInstall(path_old, PackageType::WGT),
1042             ci::AppInstaller::Result::OK);
1043   AddDataFiles(pkgid, kTestUserId);
1044   Subprocess backend_crash("/usr/bin/wgt-backend-ut/smoke-test-helper");
1045   backend_crash.Run("-w", path_new.string(), "-u", kTestUserIdStr.c_str());
1046   ASSERT_NE(backend_crash.Wait(), 0);
1047
1048   // Filesystem may be mounted after crash
1049   ScopedTzipInterface poweroff_unmount_interface(pkgid);
1050   poweroff_unmount_interface.Release();
1051
1052   bf::path recovery_file = FindRecoveryFile();
1053   ASSERT_FALSE(recovery_file.empty());
1054   ASSERT_EQ(Recover(recovery_file, PackageType::WGT),
1055             ci::AppInstaller::Result::OK);
1056
1057   ScopedTzipInterface interface(pkgid);
1058   ValidatePackage(pkgid, {appid});
1059   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "1\n"));
1060   ValidateDataFiles(pkgid, kTestUserId);
1061 }
1062
1063 TEST_F(SmokeTest, InstallationMode_GoodSignature) {
1064   // pkgid: smokewgt08
1065   bf::path path = kSmokePackagesDirectory / "InstallationMode_GoodSignature.wgt";  // NOLINT
1066   ASSERT_EQ(Install(path, PackageType::WGT), ci::AppInstaller::Result::OK);
1067 }
1068
1069 TEST_F(SmokeTest, InstallationMode_WrongSignature) {
1070   // pkgid: smokewgt12
1071   bf::path path = kSmokePackagesDirectory / "InstallationMode_WrongSignature.wgt";  // NOLINT
1072   ASSERT_EQ(Install(path, PackageType::WGT), ci::AppInstaller::Result::ERROR);
1073 }
1074
1075 TEST_F(SmokeTest, InstallationMode_Rollback) {
1076   bf::path path = kSmokePackagesDirectory / "InstallationMode_Rollback.wgt";
1077   std::string pkgid = "smokewgt06";
1078   std::string appid = "smokewgt06.InstallationModeRollback";
1079   ASSERT_EQ(Install(path, PackageType::WGT, RequestResult::FAIL),
1080             ci::AppInstaller::Result::ERROR);
1081   CheckPackageNonExistance(pkgid, {appid});
1082 }
1083
1084 TEST_F(SmokeTest, UpdateMode_Rollback) {
1085   bf::path path_old = kSmokePackagesDirectory / "UpdateMode_Rollback.wgt";
1086   bf::path path_new = kSmokePackagesDirectory / "UpdateMode_Rollback_2.wgt";
1087   std::string pkgid = "smokewgt07";
1088   std::string appid = "smokewgt07.UpdateModeRollback";
1089   ASSERT_EQ(Install(path_old, PackageType::WGT), ci::AppInstaller::Result::OK);
1090   AddDataFiles(pkgid, kTestUserId);
1091   ASSERT_EQ(Install(path_new, PackageType::WGT, RequestResult::FAIL),
1092                     ci::AppInstaller::Result::ERROR);
1093   ValidatePackage(pkgid, {appid});
1094
1095   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "1\n"));
1096   ValidateDataFiles(pkgid, kTestUserId);
1097 }
1098
1099 TEST_F(SmokeTest, DeltaMode_Rollback) {
1100   bf::path path = kSmokePackagesDirectory / "DeltaMode_Rollback.wgt";
1101   bf::path delta_package = kSmokePackagesDirectory / "DeltaMode_Rollback.delta";
1102   std::string pkgid = "smokewgt01";
1103   std::string appid = "smokewgt01.DeltaMode";
1104   ASSERT_EQ(Install(path, PackageType::WGT), ci::AppInstaller::Result::OK);
1105   AddDataFiles(pkgid, kTestUserId);
1106   ASSERT_EQ(Install(delta_package, PackageType::WGT, RequestResult::FAIL),
1107             ci::AppInstaller::Result::ERROR);
1108
1109   ValidatePackage(pkgid, {appid});
1110   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/MODIFIED",
1111                                            "version 1\n"));
1112   ValidateDataFiles(pkgid, kTestUserId);
1113   ASSERT_TRUE(bf::exists(GetPackageRoot(pkgid, kTestUserId) /
1114                          "res/wgt/DELETED"));
1115   ASSERT_FALSE(bf::exists(GetPackageRoot(pkgid, kTestUserId) /
1116                           "res/wgt/ADDED"));
1117 }
1118
1119 TEST_F(SmokeTest, InstallationMode_Hybrid) {
1120   bf::path path = kSmokePackagesDirectory / "InstallationMode_Hybrid.wgt";
1121   std::string pkgid = "smokehyb01";
1122   // Excutable for native app doesn't create symlink
1123   std::string appid1 = "smokehyb01.Web";
1124   ASSERT_EQ(Install(path, PackageType::HYBRID), ci::AppInstaller::Result::OK);
1125   ValidatePackage(pkgid, {appid1});
1126 }
1127
1128 TEST_F(SmokeTest, UpdateMode_Hybrid) {
1129   bf::path path_old = kSmokePackagesDirectory / "UpdateMode_Hybrid.wgt";
1130   bf::path path_new = kSmokePackagesDirectory / "UpdateMode_Hybrid_2.wgt";
1131   std::string pkgid = "smokehyb02";
1132   std::string appid1 = "smokehyb02.Web";
1133   ASSERT_EQ(Install(path_old, PackageType::HYBRID),
1134             ci::AppInstaller::Result::OK);
1135 //  AddDataFiles(pkgid, kTestUserId);
1136   ASSERT_EQ(Install(path_new, PackageType::HYBRID),
1137             ci::AppInstaller::Result::OK);
1138   ValidatePackage(pkgid, {appid1});
1139
1140   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "2\n"));
1141   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "VERSION", "2\n"));
1142 //  ValidateDataFiles(pkgid, kTestUserId);
1143 }
1144
1145 TEST_F(SmokeTest, DeinstallationMode_Hybrid) {
1146   bf::path path = kSmokePackagesDirectory / "DeinstallationMode_Hybrid.wgt";
1147   std::string pkgid = "smokehyb03";
1148   std::string appid1 = "smokehyb03.Web";
1149   ASSERT_EQ(Install(path, PackageType::HYBRID),
1150             ci::AppInstaller::Result::OK);
1151   ASSERT_EQ(Uninstall(pkgid, PackageType::HYBRID, false),
1152             ci::AppInstaller::Result::OK);
1153   CheckPackageNonExistance(pkgid, {appid1});
1154 }
1155
1156 TEST_F(SmokeTest, DeltaMode_Hybrid) {
1157   bf::path path = kSmokePackagesDirectory / "DeltaMode_Hybrid.wgt";
1158   bf::path delta_package = kSmokePackagesDirectory / "DeltaMode_Hybrid.delta";
1159   std::string pkgid = "smokehyb04";
1160   std::string appid1 = "smokehyb04.Web";
1161   ASSERT_EQ(DeltaInstall(path, delta_package, PackageType::HYBRID),
1162             ci::AppInstaller::Result::OK);
1163   ValidatePackage(pkgid, {appid1});
1164
1165   // Check delta modifications
1166   bf::path root_path = ci::GetRootAppPath(false,
1167       kTestUserId);
1168   ASSERT_FALSE(bf::exists(root_path / pkgid / "res" / "wgt" / "DELETED"));
1169   ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "ADDED"));
1170   ASSERT_FALSE(bf::exists(root_path / pkgid / "lib" / "DELETED"));
1171   ASSERT_TRUE(bf::exists(root_path / pkgid / "lib" / "ADDED"));
1172   ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "css" / "style.css"));  // NOLINT
1173   ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "images" / "tizen_32.png"));  // NOLINT
1174   ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "js" / "main.js"));
1175   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/MODIFIED", "version 2\n"));  // NOLINT
1176   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "lib/MODIFIED", "version 2\n"));  // NOLINT
1177 }
1178
1179 TEST_F(SmokeTest, MountInstallationMode_Hybrid) {
1180   bf::path path = kSmokePackagesDirectory / "MountInstallationMode_Hybrid.wgt";
1181   std::string pkgid = "smokehyb05";
1182   std::string appid1 = "smokehyb05.web";
1183   ASSERT_EQ(MountInstall(path, PackageType::HYBRID),
1184             ci::AppInstaller::Result::OK);
1185   ScopedTzipInterface interface(pkgid);
1186   ValidatePackage(pkgid, {appid1});
1187 }
1188
1189 TEST_F(SmokeTest, MountUpdateMode_Hybrid) {
1190   bf::path path_old = kSmokePackagesDirectory / "MountUpdateMode_Hybrid.wgt";
1191   bf::path path_new = kSmokePackagesDirectory / "MountUpdateMode_Hybrid_2.wgt";
1192   std::string pkgid = "smokehyb06";
1193   std::string appid1 = "smokehyb06.web";
1194   ASSERT_EQ(MountInstall(path_old, PackageType::HYBRID),
1195             ci::AppInstaller::Result::OK);
1196   AddDataFiles(pkgid, kTestUserId);
1197   ASSERT_EQ(MountInstall(path_new, PackageType::HYBRID),
1198             ci::AppInstaller::Result::OK);
1199   ScopedTzipInterface interface(pkgid);
1200   ValidatePackage(pkgid, {appid1});
1201
1202   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "2\n"));
1203   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "lib/VERSION", "2\n"));
1204   ValidateDataFiles(pkgid, kTestUserId);
1205 }
1206
1207 TEST_F(SmokeTest, InstallationMode_Rollback_Hybrid) {
1208   bf::path path = kSmokePackagesDirectory /
1209       "InstallationMode_Rollback_Hybrid.wgt";
1210   std::string pkgid = "smokehyb07";
1211   std::string appid1 = "smokehyb07.web";
1212   ASSERT_EQ(Install(path, PackageType::HYBRID, RequestResult::FAIL),
1213             ci::AppInstaller::Result::ERROR);
1214   CheckPackageNonExistance(pkgid, {appid1});
1215 }
1216
1217 TEST_F(SmokeTest, UpdateMode_Rollback_Hybrid) {
1218   bf::path path_old = kSmokePackagesDirectory /
1219       "UpdateMode_Rollback_Hybrid.wgt";
1220   bf::path path_new = kSmokePackagesDirectory /
1221       "UpdateMode_Rollback_Hybrid_2.wgt";
1222   std::string pkgid = "smokehyb08";
1223   std::string appid1 = "smokehyb08.web";
1224   ASSERT_EQ(Install(path_old, PackageType::HYBRID),
1225             ci::AppInstaller::Result::OK);
1226   AddDataFiles(pkgid, kTestUserId);
1227   ASSERT_EQ(Install(path_new, PackageType::HYBRID,
1228       RequestResult::FAIL), ci::AppInstaller::Result::ERROR);
1229   ValidatePackage(pkgid, {appid1});
1230
1231   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "1\n"));
1232   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "lib/VERSION", "1\n"));
1233   ValidateDataFiles(pkgid, kTestUserId);
1234 }
1235
1236 TEST_F(SmokeTest, DeltaMode_Rollback_Hybrid) {
1237   bf::path path = kSmokePackagesDirectory / "DeltaMode_Rollback_Hybrid.wgt";
1238   bf::path delta_package = kSmokePackagesDirectory /
1239       "DeltaMode_Rollback_Hybrid.delta";
1240   std::string pkgid = "smokehyb11";
1241   std::string appid1 = "smokehyb11.web";
1242   ASSERT_EQ(Install(path, PackageType::HYBRID), ci::AppInstaller::Result::OK);
1243   AddDataFiles(pkgid, kTestUserId);
1244   ASSERT_EQ(Install(delta_package, PackageType::HYBRID, RequestResult::FAIL),
1245             ci::AppInstaller::Result::ERROR);
1246
1247   ValidatePackage(pkgid, {appid1});
1248   // Check delta modifications
1249   bf::path root_path = GetPackageRoot(pkgid, kTestUserId);
1250   ASSERT_TRUE(bf::exists(root_path / "res" / "wgt" / "DELETED"));
1251   ASSERT_FALSE(bf::exists(root_path / "res" / "wgt" / "ADDED"));
1252   ASSERT_TRUE(bf::exists(root_path / "lib" / "DELETED"));
1253   ASSERT_FALSE(bf::exists(root_path / "lib" / "ADDED"));
1254   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/MODIFIED",
1255                                            "version 1\n"));
1256   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "lib/MODIFIED",
1257                                            "version 1\n"));
1258   ValidateDataFiles(pkgid, kTestUserId);
1259 }
1260
1261 TEST_F(SmokeTest, MountInstallationMode_Rollback_Hybrid) {
1262   bf::path path = kSmokePackagesDirectory /
1263       "MountInstallationMode_Rollback_Hybrid.wgt";
1264   std::string pkgid = "smokehyb09";
1265   std::string appid1 = "smokehyb09.web";
1266   ASSERT_EQ(MountInstall(path, PackageType::HYBRID, RequestResult::FAIL),
1267       ci::AppInstaller::Result::ERROR);
1268   ScopedTzipInterface interface(pkgid);
1269   CheckPackageNonExistance(pkgid, {appid1});
1270 }
1271
1272 TEST_F(SmokeTest, MountUpdateMode_Rollback_Hybrid) {
1273   bf::path path_old = kSmokePackagesDirectory /
1274       "MountUpdateMode_Rollback_Hybrid.wgt";
1275   bf::path path_new = kSmokePackagesDirectory /
1276       "MountUpdateMode_Rollback_Hybrid_2.wgt";
1277   std::string pkgid = "smokehyb10";
1278   std::string appid1 = "smokehyb10.web";
1279   ASSERT_EQ(MountInstall(path_old, PackageType::HYBRID),
1280             ci::AppInstaller::Result::OK);
1281   AddDataFiles(pkgid, kTestUserId);
1282   ASSERT_EQ(MountInstall(path_new, PackageType::HYBRID,
1283       RequestResult::FAIL), ci::AppInstaller::Result::ERROR);
1284   ScopedTzipInterface interface(pkgid);
1285   ValidatePackage(pkgid, {appid1});
1286
1287   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "1\n"));
1288   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "lib/VERSION", "1\n"));
1289   ValidateDataFiles(pkgid, kTestUserId);
1290 }
1291
1292 TEST_F(SmokeTest, MountInstallationMode) {
1293   bf::path path = kSmokePackagesDirectory / "MountInstallationMode.wgt";
1294   std::string pkgid = "smokewgt28";
1295   std::string appid = "smokewgt28.InstallationMode";
1296   ASSERT_EQ(MountInstall(path, PackageType::WGT), ci::AppInstaller::Result::OK);
1297   ScopedTzipInterface interface(pkgid);
1298   ValidatePackage(pkgid, {appid});
1299 }
1300
1301 TEST_F(SmokeTest, MountUpdateMode) {
1302   bf::path path_old = kSmokePackagesDirectory / "MountUpdateMode.wgt";
1303   bf::path path_new = kSmokePackagesDirectory / "MountUpdateMode_2.wgt";
1304   std::string pkgid = "smokewgt29";
1305   std::string appid = "smokewgt29.UpdateMode";
1306   ASSERT_EQ(MountInstall(path_old, PackageType::WGT),
1307             ci::AppInstaller::Result::OK);
1308   AddDataFiles(pkgid, kTestUserId);
1309   ASSERT_EQ(MountInstall(path_new, PackageType::WGT),
1310             ci::AppInstaller::Result::OK);
1311   ScopedTzipInterface interface(pkgid);
1312   ValidatePackage(pkgid, {appid});
1313
1314   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "2\n"));
1315   ValidateDataFiles(pkgid, kTestUserId);
1316 }
1317
1318 TEST_F(SmokeTest, MountInstallationMode_Rollback) {
1319   bf::path path =
1320       kSmokePackagesDirectory / "MountInstallationMode_Rollback.wgt";
1321   std::string pkgid = "smokewgt33";
1322   std::string appid = "smokewgt33.web";
1323   ASSERT_EQ(MountInstall(path, PackageType::WGT, RequestResult::FAIL),
1324             ci::AppInstaller::Result::ERROR);
1325   ScopedTzipInterface interface(pkgid);
1326   CheckPackageNonExistance(pkgid, {appid});
1327 }
1328
1329 TEST_F(SmokeTest, MountUpdateMode_Rollback) {
1330   bf::path path_old = kSmokePackagesDirectory / "MountUpdateMode_Rollback.wgt";
1331   bf::path path_new =
1332       kSmokePackagesDirectory / "MountUpdateMode_Rollback_2.wgt";
1333   std::string pkgid = "smokewgt34";
1334   std::string appid = "smokewgt34.web";
1335   ASSERT_EQ(MountInstall(path_old, PackageType::WGT),
1336             ci::AppInstaller::Result::OK);
1337   AddDataFiles(pkgid, kTestUserId);
1338   ASSERT_EQ(MountInstall(path_new, PackageType::WGT,
1339       RequestResult::FAIL), ci::AppInstaller::Result::ERROR);
1340   ScopedTzipInterface interface(pkgid);
1341   ValidatePackage(pkgid, {appid});
1342
1343   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "1\n"));
1344   ValidateDataFiles(pkgid, kTestUserId);
1345 }
1346
1347 TEST_F(SmokeTest, UserDefinedPlugins) {
1348   bf::path path = kSmokePackagesDirectory / "SimpleEchoPrivilege.wgt";
1349   std::string pkgid = "smokewgt02";
1350   std::string appid = "smokewgt02.SimpleEcho";
1351   std::string call_privilege = "http://tizen.org/privilege/call";
1352   std::string location_privilege = "http://tizen.org/privilege/location";
1353   std::string power_privilege = "http://tizen.org/privilege/power";
1354
1355   ASSERT_EQ(Install(path, PackageType::WGT), ci::AppInstaller::Result::OK);
1356   ValidatePackage(pkgid, {appid});
1357   std::vector<std::string> res;
1358   ASSERT_TRUE(ci::QueryPrivilegesForPkgId(pkgid, kTestUserId, &res));
1359   ASSERT_TRUE(std::find(res.begin(), res.end(), call_privilege) != res.end());
1360   ASSERT_TRUE(std::find(res.begin(), res.end(), location_privilege)
1361           != res.end());
1362   ASSERT_TRUE(std::find(res.begin(), res.end(), power_privilege) != res.end());
1363 }
1364
1365 TEST_F(SmokeTest, InstallExternalMode) {
1366   ASSERT_TRUE(CheckAvailableExternalPath());
1367   bf::path path = kSmokePackagesDirectory / "InstallExternalMode.wgt";
1368   std::string pkgid = "smokewgt35";
1369   std::string appid = "smokewgt35.web";
1370   ASSERT_EQ(InstallExternal(path, PackageType::WGT),
1371       ci::AppInstaller::Result::OK);
1372   ValidateExternalPackage(pkgid, {appid});
1373 }
1374
1375 TEST_F(SmokeTest, MigrateLegacyExternalImageMode) {
1376   ASSERT_TRUE(CheckAvailableExternalPath());
1377   bf::path path =
1378       kSmokePackagesDirectory / "MigrateLegacyExternalImageMode.wgt";
1379   std::string pkgid = "smokewgt36";
1380   std::string appid = "smokewgt36.web";
1381   bf::path legacy_path = kSmokePackagesDirectory / kLegacyExtImageDir;
1382   ASSERT_EQ(MigrateLegacyExternalImage(pkgid, path, legacy_path,
1383       PackageType::WGT), ci::AppInstaller::Result::OK);
1384   ValidateExternalPackage(pkgid, {appid});
1385 }
1386
1387 TEST_F(PreloadSmokeTest, InstallationMode_Preload) {
1388   ASSERT_EQ(getuid(), 0) << "Test cannot be run by normal user";
1389   bf::path path = kSmokePackagesDirectory / "InstallationMode_Preload.wgt";
1390   std::string pkgid = "smokewgt37";
1391   std::string appid = "smokewgt37.InstallationModePreload";
1392   ASSERT_EQ(InstallPreload(path, PackageType::WGT),
1393             ci::AppInstaller::Result::OK);
1394   ValidatePackage(pkgid, {appid}, true);
1395 }
1396
1397 TEST_F(PreloadSmokeTest, UpdateMode_Preload) {
1398   ASSERT_EQ(getuid(), 0) << "Test cannot be run by normal user";
1399   bf::path path_old = kSmokePackagesDirectory / "UpdateMode_Preload.wgt";
1400   bf::path path_new = kSmokePackagesDirectory / "UpdateMode_Preload2.wgt";
1401   std::string pkgid = "smokewgt38";
1402   std::string appid = "smokewgt38.UpdateModePreload";
1403   ASSERT_EQ(InstallPreload(path_old, PackageType::WGT),
1404             ci::AppInstaller::Result::OK);
1405   AddDataFiles(pkgid, kTestUserId);
1406   ASSERT_EQ(InstallPreload(path_new, PackageType::WGT),
1407             ci::AppInstaller::Result::OK);
1408   ValidatePackage(pkgid, {appid}, true);
1409
1410   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "2",
1411                                            true));
1412   ValidateDataFiles(pkgid, kTestUserId);
1413 }
1414
1415 TEST_F(PreloadSmokeTest, DeinstallationMode_Preload) {
1416   ASSERT_EQ(getuid(), 0) << "Test cannot be run by normal user";
1417   bf::path path = kSmokePackagesDirectory / "DeinstallationMode_Preload.wgt";
1418   std::string pkgid = "smokewgt39";
1419   std::string appid = "smokewgt39.DeinstallationModePreload";
1420   ASSERT_EQ(InstallPreload(path, PackageType::WGT),
1421             ci::AppInstaller::Result::OK);
1422   ASSERT_EQ(Uninstall(pkgid, PackageType::WGT, true),
1423             ci::AppInstaller::Result::OK);
1424   CheckPackageReadonlyNonExistance(pkgid, {appid});
1425 }
1426
1427 }  // namespace common_installer
1428
1429 int main(int argc,  char** argv) {
1430   testing::InitGoogleTest(&argc, argv);
1431   testing::Environment *env = testing::AddGlobalTestEnvironment(
1432       new common_installer::SmokeEnvironment());
1433   ParseRequestMode(argc, argv);
1434   return RUN_ALL_TESTS();
1435 }