Smoke tests for hybrid package
[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/backup_paths.h>
10 #include <common/pkgmgr_interface.h>
11 #include <common/pkgmgr_registration.h>
12 #include <common/request.h>
13 #include <common/step/step_fail.h>
14 #include <gtest/gtest.h>
15 #include <gtest/gtest-death-test.h>
16 #include <pkgmgr-info.h>
17 #include <signal.h>
18 #include <unistd.h>
19 #include <tzplatform_config.h>
20
21 #include <array>
22 #include <cstdio>
23 #include <cstdlib>
24 #include <vector>
25
26 #include "hybrid/hybrid_installer.h"
27 #include "wgt/wgt_app_query_interface.h"
28 #include "wgt/wgt_installer.h"
29
30 #define SIZEOFARRAY(ARR)                                                       \
31   sizeof(ARR) / sizeof(ARR[0])                                                 \
32
33 namespace bf = boost::filesystem;
34 namespace bs = boost::system;
35 namespace ci = common_installer;
36
37 namespace {
38
39 const bf::path kSmokePackagesDirectory =
40     "/usr/share/wgt-backend-ut/test_samples/smoke/";
41
42 const char kApplicationDir[] = ".applications";
43 const char kApplicationDirBackup[] = ".applications.bck";
44 const char KUserAppsDir[] = "apps_rw";
45 const char KUserAppsDirBackup[] = "apps_rw.bck";
46
47 enum class RequestResult {
48   NORMAL,
49   FAIL,
50   CRASH
51 };
52
53 class TestPkgmgrInstaller : public ci::PkgmgrInstallerInterface {
54  public:
55   bool CreatePkgMgrInstaller(pkgmgr_installer** installer,
56                              ci::InstallationMode* mode) {
57     *installer = pkgmgr_installer_new();
58     if (!*installer)
59       return false;
60     *mode = ci::InstallationMode::ONLINE;
61     return true;
62   }
63
64   bool ShouldCreateSignal() const {
65     return false;
66   }
67 };
68
69 enum class PackageType {
70   WGT,
71   HYBRID
72 };
73
74 class StepCrash : public ci::Step {
75  public:
76   using Step::Step;
77
78   ci::Step::Status process() override {
79     raise(SIGSEGV);
80     return Status::OK;
81   }
82   ci::Step::Status clean() override { return ci::Step::Status::OK; }
83   ci::Step::Status undo() override { return ci::Step::Status::OK; }
84   ci::Step::Status precheck() override { return ci::Step::Status::OK; }
85 };
86
87 void RemoveAllRecoveryFiles() {
88   bf::path root_path = ci::GetRootAppPath(false);
89   if (!bf::exists(root_path))
90     return;
91   for (auto& dir_entry : boost::make_iterator_range(
92          bf::directory_iterator(root_path), bf::directory_iterator())) {
93     if (bf::is_regular_file(dir_entry)) {
94       if (dir_entry.path().string().find("/recovery") != std::string::npos) {
95         bs::error_code error;
96         bf::remove(dir_entry.path(), error);
97       }
98     }
99   }
100 }
101
102 bf::path FindRecoveryFile() {
103   bf::path root_path = ci::GetRootAppPath(false);
104   for (auto& dir_entry : boost::make_iterator_range(
105          bf::directory_iterator(root_path), bf::directory_iterator())) {
106     if (bf::is_regular_file(dir_entry)) {
107       if (dir_entry.path().string().find("/recovery") != std::string::npos) {
108         return dir_entry.path();
109       }
110     }
111   }
112   return {};
113 }
114
115 bool ValidateFileContentInPackage(const std::string& pkgid,
116                                   const std::string& relative,
117                                   const std::string& expected) {
118   bf::path root_path = ci::GetRootAppPath(false);
119   bf::path file_path = root_path / pkgid / relative;
120   if (!bf::exists(file_path)) {
121     LOG(ERROR) << file_path << " doesn't exist";
122     return false;
123   }
124   FILE* handle = fopen(file_path.c_str(), "r");
125   if (!handle) {
126     LOG(ERROR) << file_path << " cannot  be open";
127     return false;
128   }
129   std::string content;
130   std::array<char, 200> buffer;
131   while (fgets(buffer.data(), buffer.size(), handle)) {
132     content += buffer.data();
133   }
134   fclose(handle);
135   return content == expected;
136 }
137
138 void ValidatePackageFS(const std::string& pkgid,
139                        const std::vector<std::string>& appids) {
140   bf::path root_path = ci::GetRootAppPath(false);
141   bf::path package_path = root_path / pkgid;
142   bf::path data_path = package_path / "data";
143   bf::path shared_path = package_path / "shared";
144   bf::path cache_path = package_path / "cache";
145   ASSERT_TRUE(bf::exists(root_path));
146   ASSERT_TRUE(bf::exists(package_path));
147   ASSERT_TRUE(bf::exists(data_path));
148   ASSERT_TRUE(bf::exists(shared_path));
149   ASSERT_TRUE(bf::exists(cache_path));
150
151   bf::path manifest_path =
152       bf::path(getUserManifestPath(getuid())) / (pkgid + ".xml");
153   ASSERT_TRUE(bf::exists(manifest_path));
154
155   for (auto& appid : appids) {
156     bf::path binary_path = package_path / "bin" / appid;
157     ASSERT_TRUE(bf::exists(binary_path));
158     bf::path icon_path = bf::path(getIconPath(getuid())) / (appid + ".png");
159     ASSERT_TRUE(bf::exists(icon_path));
160     bf::path icon_backup = ci::GetBackupPathForIconFile(icon_path);
161     ASSERT_FALSE(bf::exists(icon_backup));
162   }
163
164   bf::path widget_root_path = package_path / "res" / "wgt";
165   bf::path config_path = widget_root_path / "config.xml";
166   ASSERT_TRUE(bf::exists(widget_root_path));
167   ASSERT_TRUE(bf::exists(config_path));
168
169   bf::path private_tmp_path = package_path / "tmp";
170   ASSERT_TRUE(bf::exists(private_tmp_path));
171
172   // backups should not exist
173   bf::path package_backup = ci::GetBackupPathForPackagePath(package_path);
174   bf::path manifest_backup = ci::GetBackupPathForManifestFile(manifest_path);
175   ASSERT_FALSE(bf::exists(package_backup));
176   ASSERT_FALSE(bf::exists(manifest_backup));
177 }
178
179 void PackageCheckCleanup(const std::string& pkgid,
180                          const std::vector<std::string>& appids) {
181   bf::path root_path = ci::GetRootAppPath(false);
182   bf::path package_path = root_path / pkgid;
183   ASSERT_FALSE(bf::exists(package_path));
184
185   bf::path manifest_path =
186       bf::path(getUserManifestPath(getuid())) / (pkgid + ".xml");
187   ASSERT_FALSE(bf::exists(manifest_path));
188
189   for (auto& appid : appids) {
190     bf::path icon_path = bf::path(getIconPath(getuid())) / (appid + ".png");
191     ASSERT_FALSE(bf::exists(icon_path));
192     bf::path icon_backup = ci::GetBackupPathForIconFile(icon_path);
193     ASSERT_FALSE(bf::exists(icon_backup));
194   }
195
196   // backups should not exist
197   bf::path package_backup = ci::GetBackupPathForPackagePath(package_path);
198   bf::path manifest_backup = ci::GetBackupPathForManifestFile(manifest_path);
199   ASSERT_FALSE(bf::exists(package_backup));
200   ASSERT_FALSE(bf::exists(manifest_backup));
201 }
202
203 void ValidatePackage(const std::string& pkgid,
204                      const std::vector<std::string>& appids) {
205   ASSERT_TRUE(ci::IsPackageInstalled(pkgid, ci::GetRequestMode()));
206   ValidatePackageFS(pkgid, appids);
207 }
208
209 void CheckPackageNonExistance(const std::string& pkgid,
210                               const std::vector<std::string>& appids) {
211   ASSERT_FALSE(ci::IsPackageInstalled(pkgid, ci::GetRequestMode()));
212   PackageCheckCleanup(pkgid, appids);
213 }
214
215 std::unique_ptr<ci::AppQueryInterface> CreateQueryInterface() {
216   std::unique_ptr<ci::AppQueryInterface> query_interface(
217       new wgt::WgtAppQueryInterface());
218   return query_interface;
219 }
220
221 std::unique_ptr<ci::AppInstaller> CreateInstaller(ci::PkgMgrPtr pkgmgr,
222                                                   PackageType type) {
223   switch (type) {
224     case PackageType::WGT:
225       return std::unique_ptr<ci::AppInstaller>(new wgt::WgtInstaller(pkgmgr));
226     case PackageType::HYBRID:
227       return std::unique_ptr<ci::AppInstaller>(
228           new hybrid::HybridInstaller(pkgmgr));
229     default:
230       LOG(ERROR) << "Unknown installer type";
231       return nullptr;
232   }
233 }
234
235 ci::AppInstaller::Result RunInstallerWithPkgrmgr(ci::PkgMgrPtr pkgmgr,
236                                                  PackageType type,
237                                                  RequestResult mode) {
238   std::unique_ptr<ci::AppInstaller> installer = CreateInstaller(pkgmgr, type);
239   switch (mode) {
240   case RequestResult::FAIL:
241     installer->AddStep<ci::configuration::StepFail>();
242     break;
243   case RequestResult::CRASH:
244     installer->AddStep<StepCrash>();
245   default:
246     break;
247   }
248   return installer->Run();
249 }
250
251 ci::AppInstaller::Result Install(const bf::path& path,
252                                  PackageType type,
253                                  RequestResult mode = RequestResult::NORMAL) {
254   const char* argv[] = {"", "-i", path.c_str()};
255   TestPkgmgrInstaller pkgmgr_installer;
256   std::unique_ptr<ci::AppQueryInterface> query_interface =
257       CreateQueryInterface();
258   auto pkgmgr =
259       ci::PkgMgrInterface::Create(SIZEOFARRAY(argv), const_cast<char**>(argv),
260                                   &pkgmgr_installer, query_interface.get());
261   if (!pkgmgr) {
262     LOG(ERROR) << "Failed to initialize pkgmgr interface";
263     return ci::AppInstaller::Result::UNKNOWN;
264   }
265   return RunInstallerWithPkgrmgr(pkgmgr, type, mode);
266 }
267
268 ci::AppInstaller::Result Update(const bf::path& path_old,
269                                 const bf::path& path_new,
270                                 PackageType type,
271                                 RequestResult mode = RequestResult::NORMAL) {
272   if (Install(path_old, type) != ci::AppInstaller::Result::OK) {
273     LOG(ERROR) << "Failed to install application. Cannot update";
274     return ci::AppInstaller::Result::UNKNOWN;
275   }
276   return Install(path_new, type, mode);
277 }
278
279 ci::AppInstaller::Result Uninstall(const std::string& pkgid,
280                                    PackageType type,
281                                    RequestResult mode = RequestResult::NORMAL) {
282   const char* argv[] = {"", "-d", pkgid.c_str()};
283   TestPkgmgrInstaller pkgmgr_installer;
284   std::unique_ptr<ci::AppQueryInterface> query_interface =
285       CreateQueryInterface();
286   auto pkgmgr =
287       ci::PkgMgrInterface::Create(SIZEOFARRAY(argv), const_cast<char**>(argv),
288                                   &pkgmgr_installer, query_interface.get());
289   if (!pkgmgr) {
290     LOG(ERROR) << "Failed to initialize pkgmgr interface";
291     return ci::AppInstaller::Result::UNKNOWN;
292   }
293   return RunInstallerWithPkgrmgr(pkgmgr, type, mode);
294 }
295
296 ci::AppInstaller::Result Reinstall(const bf::path& path,
297                                    const bf::path& delta_dir,
298                                    PackageType type,
299                                    RequestResult mode = RequestResult::NORMAL) {
300   if (Install(path, type) != ci::AppInstaller::Result::OK) {
301     LOG(ERROR) << "Failed to install application. Cannot perform RDS";
302     return ci::AppInstaller::Result::UNKNOWN;
303   }
304   const char* argv[] = {"", "-r", delta_dir.c_str()};
305   TestPkgmgrInstaller pkgmgr_installer;
306   std::unique_ptr<ci::AppQueryInterface> query_interface =
307       CreateQueryInterface();
308   auto pkgmgr =
309       ci::PkgMgrInterface::Create(SIZEOFARRAY(argv), const_cast<char**>(argv),
310                                   &pkgmgr_installer, query_interface.get());
311   if (!pkgmgr) {
312     LOG(ERROR) << "Failed to initialize pkgmgr interface";
313     return ci::AppInstaller::Result::UNKNOWN;
314   }
315   return RunInstallerWithPkgrmgr(pkgmgr, type, mode);
316 }
317
318 ci::AppInstaller::Result DeltaInstall(const bf::path& path,
319     const bf::path& delta_package, PackageType type) {
320   if (Install(path, type) != ci::AppInstaller::Result::OK) {
321     LOG(ERROR) << "Failed to install application. Cannot perform RDS";
322     return ci::AppInstaller::Result::UNKNOWN;
323   }
324   return Install(delta_package, type);
325 }
326
327 ci::AppInstaller::Result Recover(const bf::path& recovery_file,
328                                  PackageType type,
329                                  RequestResult mode = RequestResult::NORMAL) {
330   const char* argv[] = {"", "-b", recovery_file.c_str()};
331   TestPkgmgrInstaller pkgmgr_installer;
332   std::unique_ptr<ci::AppQueryInterface> query_interface =
333       CreateQueryInterface();
334   auto pkgmgr =
335       ci::PkgMgrInterface::Create(SIZEOFARRAY(argv), const_cast<char**>(argv),
336                                   &pkgmgr_installer, query_interface.get());
337   if (!pkgmgr) {
338     LOG(ERROR) << "Failed to initialize pkgmgr interface";
339     return ci::AppInstaller::Result::UNKNOWN;
340   }
341   return RunInstallerWithPkgrmgr(pkgmgr, type, mode);
342 }
343
344 }  // namespace
345
346 namespace common_installer {
347
348 class SmokeEnvironment : public testing::Environment {
349  public:
350   explicit SmokeEnvironment(const bf::path& home) : home_(home) {
351   }
352   void SetUp() override {
353     bs::error_code error;
354     bf::remove_all(home_ / kApplicationDirBackup, error);
355     bf::remove_all(home_ / KUserAppsDirBackup, error);
356     if (bf::exists(home_ / KUserAppsDir)) {
357       bf::rename(home_ / KUserAppsDir, home_ / KUserAppsDirBackup, error);
358       if (error)
359         LOG(ERROR) << "Failed to setup test environment. Does some previous"
360                    << " test crashed? Directory: "
361                    << (home_ / KUserAppsDirBackup) << " should not exist.";
362       assert(!error);
363     }
364     if (bf::exists(home_ / kApplicationDir)) {
365       bf::rename(home_ / kApplicationDir, home_ / kApplicationDirBackup, error);
366       if (error)
367         LOG(ERROR) << "Failed to setup test environment. Does some previous"
368                    << " test crashed? Directory: "
369                    << (home_ / kApplicationDirBackup) << " should not exist.";
370       assert(!error);
371     }
372   }
373   void TearDown() override {
374     bs::error_code error;
375     bf::remove_all(home_ / kApplicationDir, error);
376     bf::remove_all(home_ / KUserAppsDir, error);
377     if (bf::exists(home_ / KUserAppsDirBackup))
378       bf::rename(home_ / KUserAppsDirBackup, home_ / KUserAppsDir, error);
379     if (bf::exists(home_ / kApplicationDirBackup))
380       bf::rename(home_ / kApplicationDirBackup, home_ / kApplicationDir, error);
381   }
382
383  private:
384   bf::path home_;
385 };
386
387 class SmokeTest : public testing::Test {
388 };
389
390 TEST_F(SmokeTest, InstallationMode) {
391   bf::path path = kSmokePackagesDirectory / "InstallationMode.wgt";
392   std::string pkgid = "smokeapp03";
393   std::string appid = "smokeapp03.InstallationMode";
394   ASSERT_EQ(Install(path, PackageType::WGT), ci::AppInstaller::Result::OK);
395   ValidatePackage(pkgid, {appid});
396 }
397
398 TEST_F(SmokeTest, UpdateMode) {
399   bf::path path_old = kSmokePackagesDirectory / "UpdateMode.wgt";
400   bf::path path_new = kSmokePackagesDirectory / "UpdateMode_2.wgt";
401   std::string pkgid = "smokeapp04";
402   std::string appid = "smokeapp04.UpdateMode";
403   ASSERT_EQ(Update(path_old, path_new, PackageType::WGT),
404             ci::AppInstaller::Result::OK);
405   ValidatePackage(pkgid, {appid});
406
407   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "2\n"));
408 }
409
410 TEST_F(SmokeTest, DeinstallationMode) {
411   bf::path path = kSmokePackagesDirectory / "DeinstallationMode.wgt";
412   std::string pkgid = "smokeapp05";
413   std::string appid = "smokeapp05.DeinstallationMode";
414   ASSERT_EQ(Install(path, PackageType::WGT),
415             ci::AppInstaller::Result::OK);
416   ASSERT_EQ(Uninstall(pkgid, PackageType::WGT), ci::AppInstaller::Result::OK);
417   CheckPackageNonExistance(pkgid, {appid});
418 }
419
420 TEST_F(SmokeTest, RDSMode) {
421   bf::path path = kSmokePackagesDirectory / "RDSMode.wgt";
422   bf::path delta_directory = kSmokePackagesDirectory / "delta_dir/";
423   std::string pkgid = "smokeapp11";
424   std::string appid = "smokeapp11.RDSMode";
425   ASSERT_EQ(Reinstall(path, delta_directory, PackageType::WGT),
426             ci::AppInstaller::Result::OK);
427   ValidatePackage(pkgid, {appid});
428
429   // Check delta modifications
430   bf::path root_path = ci::GetRootAppPath(false);
431   ASSERT_FALSE(bf::exists(root_path / pkgid / "res" / "wgt" / "DELETED"));
432   ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "ADDED"));
433   ValidateFileContentInPackage(pkgid, "res/wgt/MODIFIED", "2\n");
434 }
435
436 TEST_F(SmokeTest, DeltaMode) {
437   bf::path path = kSmokePackagesDirectory / "DeltaMode.wgt";
438   bf::path delta_package = kSmokePackagesDirectory / "DeltaMode.delta";
439   std::string pkgid = "smokeapp17";
440   std::string appid = "smokeapp17.DeltaMode";
441   ASSERT_EQ(DeltaInstall(path, delta_package, PackageType::WGT),
442             ci::AppInstaller::Result::OK);
443   ValidatePackage(pkgid, {appid});
444
445   // Check delta modifications
446   bf::path root_path = ci::GetRootAppPath(false);
447   ASSERT_FALSE(bf::exists(root_path / pkgid / "res" / "wgt" / "DELETED"));
448   ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "ADDED"));
449   ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "css" / "style.css"));  // NOLINT
450   ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "images" / "tizen_32.png"));  // NOLINT
451   ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "js" / "main.js"));
452   ValidateFileContentInPackage(pkgid, "res/wgt/MODIFIED", "version 2\n");
453 }
454
455 TEST_F(SmokeTest, RecoveryMode_ForInstallation) {
456   bf::path path = kSmokePackagesDirectory / "RecoveryMode_ForInstallation.wgt";
457   ASSERT_DEATH(Install(path, PackageType::WGT, RequestResult::CRASH), ".*");
458
459   std::string pkgid = "smokeapp09";
460   std::string appid = "smokeapp09.RecoveryModeForInstallation";
461   bf::path recovery_file = FindRecoveryFile();
462   ASSERT_FALSE(recovery_file.empty());
463   ASSERT_EQ(Recover(recovery_file, PackageType::WGT),
464       ci::AppInstaller::Result::OK);
465   CheckPackageNonExistance(pkgid, {appid});
466 }
467
468 TEST_F(SmokeTest, RecoveryMode_ForUpdate) {
469   bf::path path_old = kSmokePackagesDirectory / "RecoveryMode_ForUpdate.wgt";
470   bf::path path_new = kSmokePackagesDirectory / "RecoveryMode_ForUpdate_2.wgt";
471   RemoveAllRecoveryFiles();
472   ASSERT_DEATH(Update(path_old, path_new, PackageType::WGT,
473                       RequestResult::CRASH), ".*");
474
475   std::string pkgid = "smokeapp10";
476   std::string appid = "smokeapp10.RecoveryModeForUpdate";
477   bf::path recovery_file = FindRecoveryFile();
478   ASSERT_FALSE(recovery_file.empty());
479   ASSERT_EQ(Recover(recovery_file, PackageType::WGT),
480             ci::AppInstaller::Result::OK);
481   ValidatePackage(pkgid, {appid});
482
483   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "1\n"));
484 }
485
486 TEST_F(SmokeTest, InstallationMode_GoodSignature) {
487   bf::path path = kSmokePackagesDirectory / "InstallationMode_GoodSignature.wgt";  // NOLINT
488   ASSERT_EQ(Install(path, PackageType::WGT), ci::AppInstaller::Result::OK);
489 }
490
491 TEST_F(SmokeTest, InstallationMode_WrongSignature) {
492   bf::path path = kSmokePackagesDirectory / "InstallationMode_WrongSignature.wgt";  // NOLINT
493   ASSERT_EQ(Install(path, PackageType::WGT), ci::AppInstaller::Result::ERROR);
494 }
495
496 TEST_F(SmokeTest, InstallationMode_Rollback) {
497   bf::path path = kSmokePackagesDirectory / "InstallationMode_Rollback.wgt";
498   std::string pkgid = "smokeapp06";
499   std::string appid = "smokeapp06.InstallationModeRollback";
500   ASSERT_EQ(Install(path, PackageType::WGT, RequestResult::FAIL),
501             ci::AppInstaller::Result::ERROR);
502   CheckPackageNonExistance(pkgid, {appid});
503 }
504
505 TEST_F(SmokeTest, UpdateMode_Rollback) {
506   bf::path path_old = kSmokePackagesDirectory / "UpdateMode_Rollback.wgt";
507   bf::path path_new = kSmokePackagesDirectory / "UpdateMode_Rollback_2.wgt";
508   std::string pkgid = "smokeapp07";
509   std::string appid = "smokeapp07.UpdateModeRollback";
510   ASSERT_EQ(Update(path_old, path_new, PackageType::WGT, RequestResult::FAIL),
511                    ci::AppInstaller::Result::ERROR);
512   ValidatePackage(pkgid, {appid});
513
514   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "1\n"));
515 }
516
517 TEST_F(SmokeTest, InstallationMode_Hybrid) {
518   bf::path path = kSmokePackagesDirectory / "InstallationMode_Hybrid.wgt";
519   std::string pkgid = "smokehyb01";
520   std::string appid1 = "smokehyb01.Web";
521   std::string appid2 = "smokehyb01.Native";
522   ASSERT_EQ(Install(path, PackageType::HYBRID), ci::AppInstaller::Result::OK);
523   ValidatePackage(pkgid, {appid1, appid2});
524 }
525
526 TEST_F(SmokeTest, UpdateMode_Hybrid) {
527   bf::path path_old = kSmokePackagesDirectory / "UpdateMode_Hybrid.wgt";
528   bf::path path_new = kSmokePackagesDirectory / "UpdateMode_Hybrid_2.wgt";
529   std::string pkgid = "smokehyb02";
530   std::string appid1 = "smokehyb02.Web";
531   std::string appid2 = "smokehyb02.Native";
532   ASSERT_EQ(Update(path_old, path_new, PackageType::HYBRID),
533             ci::AppInstaller::Result::OK);
534   ValidatePackage(pkgid, {appid1, appid2});
535
536   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "2\n"));
537   ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "VERSION", "2\n"));
538 }
539
540 TEST_F(SmokeTest, DeinstallationMode_Hybrid) {
541   bf::path path = kSmokePackagesDirectory / "DeinstallationMode_Hybrid.wgt";
542   std::string pkgid = "smokehyb03";
543   std::string appid1 = "smokehyb03.Web";
544   std::string appid2 = "smokehyb03.Native";
545   ASSERT_EQ(Install(path, PackageType::HYBRID),
546             ci::AppInstaller::Result::OK);
547   ASSERT_EQ(Uninstall(pkgid, PackageType::WGT), ci::AppInstaller::Result::OK);
548   CheckPackageNonExistance(pkgid, {appid1, appid2});
549 }
550
551 TEST_F(SmokeTest, DeltaMode_Hybrid) {
552   bf::path path = kSmokePackagesDirectory / "DeltaMode_Hybrid.wgt";
553   bf::path delta_package = kSmokePackagesDirectory / "DeltaMode_Hybrid.delta";
554   std::string pkgid = "smokehyb04";
555   std::string appid1 = "smokehyb04.Web";
556   std::string appid2 = "smokehyb04.Native";
557   ASSERT_EQ(DeltaInstall(path, delta_package, PackageType::HYBRID),
558             ci::AppInstaller::Result::OK);
559   ValidatePackage(pkgid, {appid1, appid2});
560
561   // Check delta modifications
562   bf::path root_path = ci::GetRootAppPath(false);
563   ASSERT_FALSE(bf::exists(root_path / pkgid / "res" / "wgt" / "DELETED"));
564   ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "ADDED"));
565   ASSERT_FALSE(bf::exists(root_path / pkgid / "lib" / "DELETED"));
566   ASSERT_TRUE(bf::exists(root_path / pkgid / "lib" / "ADDED"));
567   ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "css" / "style.css"));  // NOLINT
568   ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "images" / "tizen_32.png"));  // NOLINT
569   ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "js" / "main.js"));
570   ValidateFileContentInPackage(pkgid, "res/wgt/MODIFIED", "version 2\n");
571   ValidateFileContentInPackage(pkgid, "lib/MODIFIED", "version 2\n");
572 }
573
574 }  // namespace common_installer
575
576 int main(int argc,  char** argv) {
577   testing::InitGoogleTest(&argc, argv);
578   const char* directory = getenv("HOME");
579   if (!directory) {
580     LOG(ERROR) << "Cannot get $HOME value";
581     return 1;
582   }
583   testing::AddGlobalTestEnvironment(
584       new common_installer::SmokeEnvironment(directory));
585   return RUN_ALL_TESTS();
586 }