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