Add package file ownership checking to smoke tests
[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 <common/paths.h>
10 #include <common/pkgmgr_interface.h>
11 #include <common/pkgmgr_query.h>
12 #include <common/request.h>
13 #include <common/step/configuration/step_fail.h>
14 #include <common/tzip_interface.h>
15 #include <common/utils/subprocess.h>
16 #include <gtest/gtest.h>
17 #include <gtest/gtest-death-test.h>
18 #include <pkgmgr-info.h>
19 #include <signal.h>
20 #include <unistd.h>
21 #include <tzplatform_config.h>
22
23 #include <array>
24 #include <cstdio>
25 #include <cstdlib>
26 #include <vector>
27
28 #include "hybrid/hybrid_installer.h"
29 #include "wgt/wgt_app_query_interface.h"
30 #include "wgt/wgt_installer.h"
31
32 #define SIZEOFARRAY(ARR)                                                       \
33   sizeof(ARR) / sizeof(ARR[0])                                                 \
34
35 namespace bf = boost::filesystem;
36 namespace bs = boost::system;
37 namespace ci = common_installer;
38
39 namespace {
40
41 const uid_t kTestUserId = tzplatform_getuid(TZ_SYS_DEFAULT_USER);
42 const gid_t kTestGroupId = tzplatform_getgid(TZ_SYS_DEFAULT_USER);
43 const std::string kTestUserIdStr =
44     std::to_string(kTestUserId);
45
46 const bf::path kSmokePackagesDirectory =
47     "/usr/share/wgt-backend-ut/test_samples/smoke/";
48
49 const char kApplicationDir[] = ".applications";
50 const char kApplicationDirBackup[] = ".applications.bck";
51 const char KUserAppsDir[] = "apps_rw";
52 const char KUserAppsDirBackup[] = "apps_rw.bck";
53 const char kUserDataBaseDir[] = "/opt/dbspace/user";
54
55 enum class RequestResult {
56   NORMAL,
57   FAIL
58 };
59
60 class ScopedTzipInterface {
61  public:
62   explicit ScopedTzipInterface(const std::string& pkgid)
63       : pkg_path_(bf::path(ci::GetRootAppPath(false,
64             kTestUserId)) / pkgid),
65         interface_(ci::GetMountLocation(pkg_path_)),
66         mounted_(true) {
67     interface_.MountZip(ci::GetZipPackageLocation(pkg_path_, pkgid));
68   }
69
70   void Release() {
71     if (mounted_) {
72       interface_.UnmountZip();
73       mounted_ = false;
74     }
75   }
76
77   ~ScopedTzipInterface() {
78     Release();
79   }
80
81  private:
82   bf::path pkg_path_;
83   ci::TzipInterface interface_;
84   bool mounted_;
85 };
86
87 class TestPkgmgrInstaller : public ci::PkgmgrInstallerInterface {
88  public:
89   bool CreatePkgMgrInstaller(pkgmgr_installer** installer,
90                              ci::InstallationMode* mode) {
91     *installer = pkgmgr_installer_offline_new();
92     if (!*installer)
93       return false;
94     *mode = ci::InstallationMode::ONLINE;
95     return true;
96   }
97
98   bool ShouldCreateSignal() const {
99     return false;
100   }
101 };
102
103 enum class PackageType {
104   WGT,
105   HYBRID
106 };
107
108 bool TouchFile(const bf::path& path) {
109   FILE* f = fopen(path.c_str(), "w+");
110   if (!f)
111     return false;
112   fclose(f);
113   return true;
114 }
115
116 void RemoveAllRecoveryFiles() {
117   bf::path root_path = ci::GetRootAppPath(false,
118       kTestUserId);
119   if (!bf::exists(root_path))
120     return;
121   for (auto& dir_entry : boost::make_iterator_range(
122          bf::directory_iterator(root_path), bf::directory_iterator())) {
123     if (bf::is_regular_file(dir_entry)) {
124       if (dir_entry.path().string().find("/recovery") != std::string::npos) {
125         bs::error_code error;
126         bf::remove(dir_entry.path(), error);
127       }
128     }
129   }
130 }
131
132 bf::path FindRecoveryFile() {
133   bf::path root_path = ci::GetRootAppPath(false,
134       kTestUserId);
135   for (auto& dir_entry : boost::make_iterator_range(
136          bf::directory_iterator(root_path), bf::directory_iterator())) {
137     if (bf::is_regular_file(dir_entry)) {
138       if (dir_entry.path().string().find("/recovery") != std::string::npos) {
139         return dir_entry.path();
140       }
141     }
142   }
143   return {};
144 }
145
146 bool ValidateFileContentInPackage(const std::string& pkgid,
147                                   const std::string& relative,
148                                   const std::string& expected) {
149   bf::path root_path = ci::GetRootAppPath(false,
150       kTestUserId);
151   bf::path file_path = root_path / pkgid / relative;
152   if (!bf::exists(file_path)) {
153     LOG(ERROR) << file_path << " doesn't exist";
154     return false;
155   }
156   FILE* handle = fopen(file_path.c_str(), "r");
157   if (!handle) {
158     LOG(ERROR) << file_path << " cannot  be open";
159     return false;
160   }
161   std::string content;
162   std::array<char, 200> buffer;
163   while (fgets(buffer.data(), buffer.size(), handle)) {
164     content += buffer.data();
165   }
166   fclose(handle);
167   return content == expected;
168 }
169
170 void ValidatePackageFS(const std::string& pkgid,
171                        const std::vector<std::string>& appids) {
172   bf::path root_path = ci::GetRootAppPath(false,
173       kTestUserId);
174   bf::path package_path = root_path / pkgid;
175   bf::path data_path = package_path / "data";
176   bf::path shared_path = package_path / "shared";
177   bf::path cache_path = package_path / "cache";
178   ASSERT_TRUE(bf::exists(root_path));
179   ASSERT_TRUE(bf::exists(package_path));
180   ASSERT_TRUE(bf::exists(data_path));
181   ASSERT_TRUE(bf::exists(shared_path));
182   ASSERT_TRUE(bf::exists(cache_path));
183
184   bf::path manifest_path =
185       bf::path(getUserManifestPath(
186           kTestUserId, false)) / (pkgid + ".xml");
187   ASSERT_TRUE(bf::exists(manifest_path));
188
189   for (auto& appid : appids) {
190     bf::path binary_path = package_path / "bin" / appid;
191     ASSERT_TRUE(bf::exists(binary_path));
192   }
193
194   bf::path widget_root_path = package_path / "res" / "wgt";
195   bf::path config_path = widget_root_path / "config.xml";
196   ASSERT_TRUE(bf::exists(widget_root_path));
197   ASSERT_TRUE(bf::exists(config_path));
198
199   bf::path private_tmp_path = package_path / "tmp";
200   ASSERT_TRUE(bf::exists(private_tmp_path));
201
202   // backups should not exist
203   bf::path package_backup = ci::GetBackupPathForPackagePath(package_path);
204   bf::path manifest_backup = ci::GetBackupPathForManifestFile(manifest_path);
205   ASSERT_FALSE(bf::exists(package_backup));
206   ASSERT_FALSE(bf::exists(manifest_backup));
207
208   for (bf::recursive_directory_iterator iter(root_path);
209       iter != bf::recursive_directory_iterator(); ++iter) {
210     if (bf::is_symlink(symlink_status(iter->path())))
211       continue;
212     struct stat stats;
213     stat(iter->path().c_str(), &stats);
214     ASSERT_EQ(kTestUserId, stats.st_uid);
215     ASSERT_EQ(kTestGroupId, stats.st_gid);
216   }
217 }
218
219 void PackageCheckCleanup(const std::string& pkgid,
220                          const std::vector<std::string>&) {
221   bf::path root_path = ci::GetRootAppPath(
222       false, kTestUserId);
223   bf::path package_path = root_path / pkgid;
224   ASSERT_FALSE(bf::exists(package_path));
225
226   bf::path manifest_path =
227       bf::path(getUserManifestPath(
228           kTestUserId, false)) / (pkgid + ".xml");
229   ASSERT_FALSE(bf::exists(manifest_path));
230
231   // backups should not exist
232   bf::path package_backup = ci::GetBackupPathForPackagePath(package_path);
233   bf::path manifest_backup = ci::GetBackupPathForManifestFile(manifest_path);
234   ASSERT_FALSE(bf::exists(package_backup));
235   ASSERT_FALSE(bf::exists(manifest_backup));
236 }
237
238 void ValidatePackage(const std::string& pkgid,
239                      const std::vector<std::string>& appids) {
240   ASSERT_TRUE(ci::QueryIsPackageInstalled(
241       pkgid, ci::GetRequestMode(kTestUserId),
242       kTestUserId));
243   ValidatePackageFS(pkgid, appids);
244 }
245
246 void CheckPackageNonExistance(const std::string& pkgid,
247                               const std::vector<std::string>& appids) {
248   ASSERT_FALSE(ci::QueryIsPackageInstalled(
249       pkgid, ci::GetRequestMode(kTestUserId),
250       kTestUserId));
251   PackageCheckCleanup(pkgid, appids);
252 }
253
254 std::unique_ptr<ci::AppQueryInterface> CreateQueryInterface() {
255   std::unique_ptr<ci::AppQueryInterface> query_interface(
256       new wgt::WgtAppQueryInterface());
257   return query_interface;
258 }
259
260 std::unique_ptr<ci::AppInstaller> CreateInstaller(ci::PkgMgrPtr pkgmgr,
261                                                   PackageType type) {
262   switch (type) {
263     case PackageType::WGT:
264       return std::unique_ptr<ci::AppInstaller>(new wgt::WgtInstaller(pkgmgr));
265     case PackageType::HYBRID:
266       return std::unique_ptr<ci::AppInstaller>(
267           new hybrid::HybridInstaller(pkgmgr));
268     default:
269       LOG(ERROR) << "Unknown installer type";
270       return nullptr;
271   }
272 }
273
274 ci::AppInstaller::Result RunInstallerWithPkgrmgr(ci::PkgMgrPtr pkgmgr,
275                                                  PackageType type,
276                                                  RequestResult mode) {
277   std::unique_ptr<ci::AppInstaller> installer = CreateInstaller(pkgmgr, type);
278   switch (mode) {
279   case RequestResult::FAIL:
280     installer->AddStep<ci::configuration::StepFail>();
281     break;
282   default:
283     break;
284   }
285   return installer->Run();
286 }
287 ci::AppInstaller::Result CallBackend(int argc,
288                                      const char* argv[],
289                                      PackageType type,
290                                      RequestResult mode = RequestResult::NORMAL
291                                      ) {
292   TestPkgmgrInstaller pkgmgr_installer;
293   std::unique_ptr<ci::AppQueryInterface> query_interface =
294       CreateQueryInterface();
295   auto pkgmgr =
296       ci::PkgMgrInterface::Create(argc, const_cast<char**>(argv),
297                                   &pkgmgr_installer, query_interface.get());
298   if (!pkgmgr) {
299     LOG(ERROR) << "Failed to initialize pkgmgr interface";
300     return ci::AppInstaller::Result::UNKNOWN;
301   }
302   return RunInstallerWithPkgrmgr(pkgmgr, type, mode);
303 }
304
305 ci::AppInstaller::Result Install(const bf::path& path,
306                                  PackageType type,
307                                  RequestResult mode = RequestResult::NORMAL) {
308   const char* argv[] = {"", "-i", path.c_str(), "-u", kTestUserIdStr.c_str()};
309   return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
310 }
311
312 ci::AppInstaller::Result Update(const bf::path& path_old,
313                                 const bf::path& path_new,
314                                 PackageType type,
315                                 RequestResult mode = RequestResult::NORMAL) {
316   if (Install(path_old, type) != ci::AppInstaller::Result::OK) {
317     LOG(ERROR) << "Failed to install application. Cannot update";
318     return ci::AppInstaller::Result::UNKNOWN;
319   }
320   return Install(path_new, type, mode);
321 }
322
323 ci::AppInstaller::Result MountInstall(const bf::path& path,
324     PackageType type, RequestResult mode = RequestResult::NORMAL) {
325   const char* argv[] = {"", "-w", path.c_str(), "-u", kTestUserIdStr.c_str()};
326   return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
327 }
328
329 ci::AppInstaller::Result MountUpdate(const bf::path& path_old,
330     const bf::path& path_new, PackageType type,
331     RequestResult mode = RequestResult::NORMAL) {
332   if (MountInstall(path_old, type) != ci::AppInstaller::Result::OK) {
333     LOG(ERROR) << "Failed to mount-install application. Cannot mount-update";
334     return ci::AppInstaller::Result::UNKNOWN;
335   }
336   return MountInstall(path_new, type, mode);
337 }
338
339 ci::AppInstaller::Result Uninstall(const std::string& pkgid,
340                                    PackageType type,
341                                    RequestResult mode = RequestResult::NORMAL) {
342   const char* argv[] = {"", "-d", pkgid.c_str(), "-u", kTestUserIdStr.c_str()};
343   return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
344 }
345
346 ci::AppInstaller::Result Reinstall(const bf::path& path,
347                                    const bf::path& delta_dir,
348                                    PackageType type,
349                                    RequestResult mode = RequestResult::NORMAL) {
350   if (Install(path, type) != ci::AppInstaller::Result::OK) {
351     LOG(ERROR) << "Failed to install application. Cannot perform RDS";
352     return ci::AppInstaller::Result::UNKNOWN;
353   }
354   const char* argv[] = {"", "-r", delta_dir.c_str(), "-u",
355                         kTestUserIdStr.c_str()};
356   return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
357 }
358
359 ci::AppInstaller::Result DeltaInstall(const bf::path& path,
360     const bf::path& delta_package, PackageType type) {
361   if (Install(path, type) != ci::AppInstaller::Result::OK) {
362     LOG(ERROR) << "Failed to install application. Cannot perform delta update";
363     return ci::AppInstaller::Result::UNKNOWN;
364   }
365   return Install(delta_package, type);
366 }
367
368 ci::AppInstaller::Result Clear(const std::string& pkgid,
369                                    PackageType type,
370                                    RequestResult mode = RequestResult::NORMAL) {
371   const char* argv[] = {"", "-c", pkgid.c_str(), "-u", kTestUserIdStr.c_str()};
372   return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
373 }
374
375 ci::AppInstaller::Result EnablePackage(const std::string& pkgid,
376                                   PackageType type,
377                                   RequestResult mode = RequestResult::NORMAL) {
378   const char* argv[] = {"", "-A", pkgid.c_str(), "-u", kTestUserIdStr.c_str()};
379   return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
380 }
381
382 ci::AppInstaller::Result DisablePackage(const std::string& pkgid,
383                                   PackageType type,
384                                   RequestResult mode = RequestResult::NORMAL) {
385   const char* argv[] = {"", "-D", pkgid.c_str(), "-u", kTestUserIdStr.c_str()};
386   return CallBackend(SIZEOFARRAY(argv), argv, type, mode);
387 }
388
389 ci::AppInstaller::Result Recover(const bf::path& recovery_file,
390                                  PackageType type,
391                                  RequestResult mode = RequestResult::NORMAL) {
392   const char* argv[] = {"", "-b", recovery_file.c_str(), "-u",
393                         kTestUserIdStr.c_str()};
394   TestPkgmgrInstaller pkgmgr_installer;
395   std::unique_ptr<ci::AppQueryInterface> query_interface =
396       CreateQueryInterface();
397   auto pkgmgr =
398       ci::PkgMgrInterface::Create(SIZEOFARRAY(argv), const_cast<char**>(argv),
399                                   &pkgmgr_installer, query_interface.get());
400   if (!pkgmgr) {
401     LOG(ERROR) << "Failed to initialize pkgmgr interface";
402     return ci::AppInstaller::Result::UNKNOWN;
403   }
404   return RunInstallerWithPkgrmgr(pkgmgr, type, mode);
405 }
406
407 }  // namespace
408
409 namespace common_installer {
410
411 class SmokeEnvironment : public testing::Environment {
412  public:
413   explicit SmokeEnvironment(const bf::path& home) : home_(home) {
414   }
415   void SetUp() override {
416     bf::path UserDBDir = bf::path(kUserDataBaseDir) / kTestUserIdStr;
417     bf::path UserDBDirBackup = UserDBDir.string() + std::string(".bck");
418
419     bs::error_code error;
420     bf::remove_all(home_ / kApplicationDirBackup, error);
421     bf::remove_all(home_ / KUserAppsDirBackup, error);
422     bf::remove_all(UserDBDirBackup, error);
423     if (bf::exists(home_ / KUserAppsDir)) {
424       bf::rename(home_ / KUserAppsDir, home_ / KUserAppsDirBackup, error);
425       if (error)
426         LOG(ERROR) << "Failed to setup test environment. Does some previous"
427                    << " test crashed? Directory: "
428                    << (home_ / KUserAppsDirBackup) << " should not exist.";
429       assert(!error);
430     }
431     if (bf::exists(home_ / kApplicationDir)) {
432       bf::rename(home_ / kApplicationDir, home_ / kApplicationDirBackup, error);
433       if (error)
434         LOG(ERROR) << "Failed to setup test environment. Does some previous"
435                    << " test crashed? Directory: "
436                    << (home_ / kApplicationDirBackup) << " should not exist.";
437       assert(!error);
438     }
439     if (bf::exists(UserDBDir)) {
440       bf::rename(UserDBDir, UserDBDirBackup, error);
441       if (error)
442         LOG(ERROR) << "Failed to setup test environment. Does some previous"
443                    << " test crashed? Directory: "
444                    << UserDBDirBackup << " should not exist.";
445       assert(!error);
446     }
447   }
448   void TearDown() override {
449     bf::path UserDBDir = bf::path(kUserDataBaseDir) / kTestUserIdStr;
450     bf::path UserDBDirBackup = UserDBDir.string() + std::string(".bck");
451
452     bs::error_code error;
453     bf::remove_all(home_ / kApplicationDir, error);
454     bf::remove_all(home_ / KUserAppsDir, error);
455     bf::remove_all(UserDBDir, error);
456     if (bf::exists(home_ / KUserAppsDirBackup))
457       bf::rename(home_ / KUserAppsDirBackup, home_ / KUserAppsDir, error);
458     if (bf::exists(home_ / kApplicationDirBackup))
459       bf::rename(home_ / kApplicationDirBackup, home_ / kApplicationDir, error);
460     if (bf::exists(UserDBDirBackup))
461       bf::rename(UserDBDirBackup, UserDBDir, error);
462   }
463
464  private:
465   bf::path home_;
466 };
467
468 class SmokeTest : public testing::Test {
469 };
470
471 TEST_F(SmokeTest, InstallationMode) {
472   bf::path path = kSmokePackagesDirectory / "InstallationMode.wgt";
473   std::string pkgid = "smokeapp03";
474   std::string appid = "smokeapp03.InstallationMode";
475   ASSERT_EQ(Install(path, PackageType::WGT), ci::AppInstaller::Result::OK);
476   ValidatePackage(pkgid, {appid});
477 }
478
479 TEST_F(SmokeTest, UpdateMode) {
480   bf::path path_old = kSmokePackagesDirectory / "UpdateMode.wgt";
481   bf::path path_new = kSmokePackagesDirectory / "UpdateMode_2.wgt";
482   std::string pkgid = "smokeapp04";
483   std::string appid = "smokeapp04.UpdateMode";
484   ASSERT_EQ(Update(path_old, path_new, PackageType::WGT),
485             ci::AppInstaller::Result::OK);
486   ValidatePackage(pkgid, {appid});
487
488   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "2\n"));
489 }
490
491 TEST_F(SmokeTest, DeinstallationMode) {
492   bf::path path = kSmokePackagesDirectory / "DeinstallationMode.wgt";
493   std::string pkgid = "smokeapp05";
494   std::string appid = "smokeapp05.DeinstallationMode";
495   ASSERT_EQ(Install(path, PackageType::WGT),
496             ci::AppInstaller::Result::OK);
497   ASSERT_EQ(Uninstall(pkgid, PackageType::WGT), ci::AppInstaller::Result::OK);
498   CheckPackageNonExistance(pkgid, {appid});
499 }
500
501 TEST_F(SmokeTest, RDSMode) {
502   bf::path path = kSmokePackagesDirectory / "RDSMode.wgt";
503   bf::path delta_directory = kSmokePackagesDirectory / "delta_dir/";
504   std::string pkgid = "smokeapp11";
505   std::string appid = "smokeapp11.RDSMode";
506   ASSERT_EQ(Reinstall(path, delta_directory, PackageType::WGT),
507             ci::AppInstaller::Result::OK);
508   ValidatePackage(pkgid, {appid});
509
510   // Check delta modifications
511   bf::path root_path = ci::GetRootAppPath(false,
512       kTestUserId);
513   ASSERT_FALSE(bf::exists(root_path / pkgid / "res" / "wgt" / "DELETED"));
514   ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "ADDED"));
515   ValidateFileContentInPackage(pkgid, "res/wgt/MODIFIED", "2\n");
516 }
517
518 TEST_F(SmokeTest, EnablePkg) {
519   bf::path path = kSmokePackagesDirectory / "EnablePkg.wgt";
520   std::string pkgid = "smokeapp22";
521   ASSERT_EQ(Install(path, PackageType::WGT),
522             ci::AppInstaller::Result::OK);
523   ASSERT_EQ(DisablePackage(pkgid, PackageType::WGT),
524             ci::AppInstaller::Result::OK);
525   ASSERT_EQ(EnablePackage(pkgid, PackageType::WGT),
526             ci::AppInstaller::Result::OK);
527
528   ASSERT_TRUE(ci::QueryIsPackageInstalled(pkgid,
529       ci::GetRequestMode(kTestUserId),
530       kTestUserId));
531 }
532
533 TEST_F(SmokeTest, DisablePkg) {
534   bf::path path = kSmokePackagesDirectory / "DisablePkg.wgt";
535   std::string pkgid = "smokeapp21";
536   std::string appid = "smokeapp21.DisablePkg";
537   ASSERT_EQ(Install(path, PackageType::WGT),
538             ci::AppInstaller::Result::OK);
539   ASSERT_EQ(DisablePackage(pkgid, PackageType::WGT),
540             ci::AppInstaller::Result::OK);
541   ASSERT_FALSE(ci::QueryIsPackageInstalled(pkgid,
542       ci::GetRequestMode(kTestUserId),
543       kTestUserId));
544   ValidatePackageFS(pkgid, {appid});
545 }
546
547 TEST_F(SmokeTest, ClearMode) {
548   bf::path path = kSmokePackagesDirectory / "ClearMode.wgt";
549   std::string pkgid = "smokeapp20";
550   std::string appid = "smokeapp20.ClearMode";
551   ASSERT_EQ(Install(path, PackageType::WGT),
552             ci::AppInstaller::Result::OK);
553   bf::path root_path = ci::GetRootAppPath(false,
554       kTestUserId);
555   bs::error_code error;
556   bf::create_directory(root_path / pkgid / "data" / "dir", error);
557   ASSERT_FALSE(error);
558   ASSERT_TRUE(TouchFile(root_path / pkgid / "data" / "dir" / "file"));
559   ASSERT_TRUE(TouchFile(root_path / pkgid / "data" / "file"));
560   ASSERT_EQ(Clear(pkgid, PackageType::WGT), ci::AppInstaller::Result::OK);
561   ValidatePackage(pkgid, {appid});
562   ASSERT_FALSE(bf::exists(root_path / pkgid / "data" / "dir" / "file"));
563   ASSERT_FALSE(bf::exists(root_path / pkgid / "res" / "file"));
564 }
565
566 TEST_F(SmokeTest, DeltaMode) {
567   bf::path path = kSmokePackagesDirectory / "DeltaMode.wgt";
568   bf::path delta_package = kSmokePackagesDirectory / "DeltaMode.delta";
569   std::string pkgid = "smokeapp17";
570   std::string appid = "smokeapp17.DeltaMode";
571   ASSERT_EQ(DeltaInstall(path, delta_package, PackageType::WGT),
572             ci::AppInstaller::Result::OK);
573   ValidatePackage(pkgid, {appid});
574
575   // Check delta modifications
576   bf::path root_path = ci::GetRootAppPath(false,
577       kTestUserId);
578   ASSERT_FALSE(bf::exists(root_path / pkgid / "res" / "wgt" / "DELETED"));
579   ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "ADDED"));
580   ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "css" / "style.css"));  // NOLINT
581   ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "images" / "tizen_32.png"));  // NOLINT
582   ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "js" / "main.js"));
583   ValidateFileContentInPackage(pkgid, "res/wgt/MODIFIED", "version 2\n");
584 }
585
586 TEST_F(SmokeTest, RecoveryMode_ForInstallation) {
587   bf::path path = kSmokePackagesDirectory / "RecoveryMode_ForInstallation.wgt";
588   Subprocess backend_crash("/usr/bin/wgt-backend-ut/smoke-test-helper");
589   backend_crash.Run("-i", path.string(), "-u", kTestUserIdStr.c_str());
590   ASSERT_NE(backend_crash.Wait(), 0);
591
592   std::string pkgid = "smokeapp09";
593   std::string appid = "smokeapp09.RecoveryModeForInstallation";
594   bf::path recovery_file = FindRecoveryFile();
595   ASSERT_FALSE(recovery_file.empty());
596   ASSERT_EQ(Recover(recovery_file, PackageType::WGT),
597       ci::AppInstaller::Result::OK);
598   CheckPackageNonExistance(pkgid, {appid});
599 }
600
601 TEST_F(SmokeTest, RecoveryMode_ForUpdate) {
602   bf::path path_old = kSmokePackagesDirectory / "RecoveryMode_ForUpdate.wgt";
603   bf::path path_new = kSmokePackagesDirectory / "RecoveryMode_ForUpdate_2.wgt";
604   RemoveAllRecoveryFiles();
605   ASSERT_EQ(Install(path_old, PackageType::WGT), ci::AppInstaller::Result::OK);
606   Subprocess backend_crash("/usr/bin/wgt-backend-ut/smoke-test-helper");
607   backend_crash.Run("-i", path_new.string(), "-u", kTestUserIdStr.c_str());
608   ASSERT_NE(backend_crash.Wait(), 0);
609
610   std::string pkgid = "smokeapp10";
611   std::string appid = "smokeapp10.RecoveryModeForUpdate";
612   bf::path recovery_file = FindRecoveryFile();
613   ASSERT_FALSE(recovery_file.empty());
614   ASSERT_EQ(Recover(recovery_file, PackageType::WGT),
615             ci::AppInstaller::Result::OK);
616   ValidatePackage(pkgid, {appid});
617
618   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "1\n"));
619 }
620
621 TEST_F(SmokeTest, RecoveryMode_ForDelta) {
622   bf::path path_old = kSmokePackagesDirectory / "RecoveryMode_ForDelta.wgt";
623   bf::path path_new = kSmokePackagesDirectory / "RecoveryMode_ForDelta.delta";
624   RemoveAllRecoveryFiles();
625   ASSERT_EQ(Install(path_old, PackageType::WGT), ci::AppInstaller::Result::OK);
626   Subprocess backend_crash("/usr/bin/wgt-backend-ut/smoke-test-helper");
627   backend_crash.Run("-i", path_new.string(), "-u", kTestUserIdStr.c_str());
628   ASSERT_NE(backend_crash.Wait(), 0);
629
630   std::string pkgid = "smokeapp30";
631   std::string appid = "smokeapp30.RecoveryModeForDelta";
632   bf::path recovery_file = FindRecoveryFile();
633   ASSERT_FALSE(recovery_file.empty());
634   ASSERT_EQ(Recover(recovery_file, PackageType::WGT),
635             ci::AppInstaller::Result::OK);
636   ValidatePackage(pkgid, {appid});
637
638   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "1\n"));
639 }
640
641 TEST_F(SmokeTest, RecoveryMode_ForMountInstall) {
642   bf::path path = kSmokePackagesDirectory / "RecoveryMode_ForMountInstall.wgt";
643   RemoveAllRecoveryFiles();
644   Subprocess backend_crash("/usr/bin/wgt-backend-ut/smoke-test-helper");
645   backend_crash.Run("-w", path.string(), "-u", kTestUserIdStr.c_str());
646   ASSERT_NE(backend_crash.Wait(), 0);
647
648   std::string pkgid = "smokeapp31";
649   std::string appid = "smokeapp31.RecoveryModeForMountInstall";
650   bf::path recovery_file = FindRecoveryFile();
651   ASSERT_FALSE(recovery_file.empty());
652   ASSERT_EQ(Recover(recovery_file, PackageType::WGT),
653             ci::AppInstaller::Result::OK);
654   CheckPackageNonExistance(pkgid, {appid});
655 }
656
657 TEST_F(SmokeTest, RecoveryMode_ForMountUpdate) {
658   bf::path path_old =
659       kSmokePackagesDirectory / "RecoveryMode_ForMountUpdate.wgt";
660   bf::path path_new =
661       kSmokePackagesDirectory / "RecoveryMode_ForMountUpdate_2.wgt";
662   std::string pkgid = "smokeapp32";
663   std::string appid = "smokeapp32.RecoveryModeForMountUpdate";
664   RemoveAllRecoveryFiles();
665   ASSERT_EQ(MountInstall(path_old, PackageType::WGT),
666             ci::AppInstaller::Result::OK);
667   Subprocess backend_crash("/usr/bin/wgt-backend-ut/smoke-test-helper");
668   backend_crash.Run("-w", path_new.string(), "-u", kTestUserIdStr.c_str());
669   ASSERT_NE(backend_crash.Wait(), 0);
670
671   // Filesystem may be mounted after crash
672   ScopedTzipInterface poweroff_unmount_interface(pkgid);
673   poweroff_unmount_interface.Release();
674
675   bf::path recovery_file = FindRecoveryFile();
676   ASSERT_FALSE(recovery_file.empty());
677   ASSERT_EQ(Recover(recovery_file, PackageType::WGT),
678             ci::AppInstaller::Result::OK);
679
680   ScopedTzipInterface interface(pkgid);
681   ValidatePackage(pkgid, {appid});
682   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "1\n"));
683 }
684
685 TEST_F(SmokeTest, InstallationMode_GoodSignature) {
686   bf::path path = kSmokePackagesDirectory / "InstallationMode_GoodSignature.wgt";  // NOLINT
687   ASSERT_EQ(Install(path, PackageType::WGT), ci::AppInstaller::Result::OK);
688 }
689
690 TEST_F(SmokeTest, InstallationMode_WrongSignature) {
691   bf::path path = kSmokePackagesDirectory / "InstallationMode_WrongSignature.wgt";  // NOLINT
692   ASSERT_EQ(Install(path, PackageType::WGT), ci::AppInstaller::Result::ERROR);
693 }
694
695 TEST_F(SmokeTest, InstallationMode_Rollback) {
696   bf::path path = kSmokePackagesDirectory / "InstallationMode_Rollback.wgt";
697   std::string pkgid = "smokeapp06";
698   std::string appid = "smokeapp06.InstallationModeRollback";
699   ASSERT_EQ(Install(path, PackageType::WGT, RequestResult::FAIL),
700             ci::AppInstaller::Result::ERROR);
701   CheckPackageNonExistance(pkgid, {appid});
702 }
703
704 TEST_F(SmokeTest, UpdateMode_Rollback) {
705   bf::path path_old = kSmokePackagesDirectory / "UpdateMode_Rollback.wgt";
706   bf::path path_new = kSmokePackagesDirectory / "UpdateMode_Rollback_2.wgt";
707   std::string pkgid = "smokeapp07";
708   std::string appid = "smokeapp07.UpdateModeRollback";
709   ASSERT_EQ(Update(path_old, path_new, PackageType::WGT, RequestResult::FAIL),
710                    ci::AppInstaller::Result::ERROR);
711   ValidatePackage(pkgid, {appid});
712
713   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "1\n"));
714 }
715
716 TEST_F(SmokeTest, InstallationMode_Hybrid) {
717   bf::path path = kSmokePackagesDirectory / "InstallationMode_Hybrid.wgt";
718   std::string pkgid = "smokehyb01";
719   std::string appid1 = "smokehyb01.Web";
720   std::string appid2 = "smokehyb01.Native";
721   ASSERT_EQ(Install(path, PackageType::HYBRID), ci::AppInstaller::Result::OK);
722   ValidatePackage(pkgid, {appid1, appid2});
723 }
724
725 TEST_F(SmokeTest, UpdateMode_Hybrid) {
726   bf::path path_old = kSmokePackagesDirectory / "UpdateMode_Hybrid.wgt";
727   bf::path path_new = kSmokePackagesDirectory / "UpdateMode_Hybrid_2.wgt";
728   std::string pkgid = "smokehyb02";
729   std::string appid1 = "smokehyb02.Web";
730   std::string appid2 = "smokehyb02.Native";
731   ASSERT_EQ(Update(path_old, path_new, PackageType::HYBRID),
732             ci::AppInstaller::Result::OK);
733   ValidatePackage(pkgid, {appid1, appid2});
734
735   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "2\n"));
736   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "VERSION", "2\n"));
737 }
738
739 TEST_F(SmokeTest, DeinstallationMode_Hybrid) {
740   bf::path path = kSmokePackagesDirectory / "DeinstallationMode_Hybrid.wgt";
741   std::string pkgid = "smokehyb03";
742   std::string appid1 = "smokehyb03.Web";
743   std::string appid2 = "smokehyb03.Native";
744   ASSERT_EQ(Install(path, PackageType::HYBRID),
745             ci::AppInstaller::Result::OK);
746   ASSERT_EQ(Uninstall(pkgid, PackageType::WGT), ci::AppInstaller::Result::OK);
747   CheckPackageNonExistance(pkgid, {appid1, appid2});
748 }
749
750 TEST_F(SmokeTest, DeltaMode_Hybrid) {
751   bf::path path = kSmokePackagesDirectory / "DeltaMode_Hybrid.wgt";
752   bf::path delta_package = kSmokePackagesDirectory / "DeltaMode_Hybrid.delta";
753   std::string pkgid = "smokehyb04";
754   std::string appid1 = "smokehyb04.Web";
755   std::string appid2 = "smokehyb04.Native";
756   ASSERT_EQ(DeltaInstall(path, delta_package, PackageType::HYBRID),
757             ci::AppInstaller::Result::OK);
758   ValidatePackage(pkgid, {appid1, appid2});
759
760   // Check delta modifications
761   bf::path root_path = ci::GetRootAppPath(false,
762       kTestUserId);
763   ASSERT_FALSE(bf::exists(root_path / pkgid / "res" / "wgt" / "DELETED"));
764   ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "ADDED"));
765   ASSERT_FALSE(bf::exists(root_path / pkgid / "lib" / "DELETED"));
766   ASSERT_TRUE(bf::exists(root_path / pkgid / "lib" / "ADDED"));
767   ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "css" / "style.css"));  // NOLINT
768   ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "images" / "tizen_32.png"));  // NOLINT
769   ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "js" / "main.js"));
770   ValidateFileContentInPackage(pkgid, "res/wgt/MODIFIED", "version 2\n");
771   ValidateFileContentInPackage(pkgid, "lib/MODIFIED", "version 2\n");
772 }
773
774 TEST_F(SmokeTest, MountInstallationMode) {
775   bf::path path = kSmokePackagesDirectory / "MountInstallationMode.wgt";
776   std::string pkgid = "smokeapp28";
777   std::string appid = "smokeapp28.InstallationMode";
778   ASSERT_EQ(MountInstall(path, PackageType::WGT), ci::AppInstaller::Result::OK);
779   ScopedTzipInterface interface(pkgid);
780   ValidatePackage(pkgid, {appid});
781 }
782
783 TEST_F(SmokeTest, MountUpdateMode) {
784   bf::path path_old = kSmokePackagesDirectory / "MountUpdateMode.wgt";
785   bf::path path_new = kSmokePackagesDirectory / "MountUpdateMode_2.wgt";
786   std::string pkgid = "smokeapp29";
787   std::string appid = "smokeapp29.UpdateMode";
788   ASSERT_EQ(MountUpdate(path_old, path_new, PackageType::WGT),
789             ci::AppInstaller::Result::OK);
790   ScopedTzipInterface interface(pkgid);
791   ValidatePackage(pkgid, {appid});
792
793   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "2\n"));
794 }
795
796 TEST_F(SmokeTest, UserDefinedPlugins) {
797   bf::path path = kSmokePackagesDirectory / "SimpleEchoPrivilege.wgt";
798   std::string pkgid = "0CSPVhKmRk";
799   std::string appid = "0CSPVhKmRk.SimpleEcho";
800   std::string call_privilege = "http://tizen.org/privilege/call";
801   std::string location_privilege = "http://tizen.org/privilege/location";
802   std::string power_privilege = "http://tizen.org/privilege/power";
803
804   ASSERT_EQ(Install(path, PackageType::WGT), ci::AppInstaller::Result::OK);
805   ValidatePackage(pkgid, {appid});
806   std::vector<std::string> res;
807   ASSERT_TRUE(ci::QueryPrivilegesForPkgId(pkgid, kTestUserId, &res));
808   ASSERT_TRUE(std::find(res.begin(), res.end(), call_privilege) != res.end());
809   ASSERT_TRUE(std::find(res.begin(), res.end(), location_privilege)
810           != res.end());
811   ASSERT_TRUE(std::find(res.begin(), res.end(), power_privilege) != res.end());
812 }
813
814 }  // namespace common_installer
815
816 int main(int argc,  char** argv) {
817   testing::InitGoogleTest(&argc, argv);
818   bf::path directory =
819         bf::path("/home") / tzplatform_getenv(TZ_SYS_DEFAULT_USER);
820   testing::AddGlobalTestEnvironment(
821       new common_installer::SmokeEnvironment(directory));
822   return RUN_ALL_TESTS();
823 }