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.
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>
19 #include <tzplatform_config.h>
25 #include "wgt/wgt_app_query_interface.h"
26 #include "wgt/wgt_installer.h"
28 #define SIZEOFARRAY(ARR) \
29 sizeof(ARR) / sizeof(ARR[0]) \
31 namespace bf = boost::filesystem;
32 namespace bs = boost::system;
33 namespace ci = common_installer;
37 const bf::path kSmokePackagesDirectory =
38 "/usr/share/wgt-backend-ut/test_samples/smoke/";
40 const char kApplicationDir[] = ".applications";
41 const char kApplicationDirBackup[] = ".applications.bck";
42 const char KUserAppsDir[] = "apps_rw";
43 const char KUserAppsDirBackup[] = "apps_rw.bck";
45 enum class RequestResult {
51 class TestPkgmgrInstaller : public ci::PkgmgrInstallerInterface {
53 bool CreatePkgMgrInstaller(pkgmgr_installer** installer,
54 ci::InstallationMode* mode) {
55 *installer = pkgmgr_installer_new();
58 *mode = ci::InstallationMode::ONLINE;
62 bool ShouldCreateSignal() const {
67 class StepCrash : public ci::Step {
71 ci::Step::Status process() override {
75 ci::Step::Status clean() override { return ci::Step::Status::OK; }
76 ci::Step::Status undo() override { return ci::Step::Status::OK; }
77 ci::Step::Status precheck() override { return ci::Step::Status::OK; }
80 void RemoveAllRecoveryFiles() {
81 bf::path root_path = ci::GetRootAppPath(false);
82 if (!bf::exists(root_path))
84 for (auto& dir_entry : boost::make_iterator_range(
85 bf::directory_iterator(root_path), bf::directory_iterator())) {
86 if (bf::is_regular_file(dir_entry)) {
87 if (dir_entry.path().string().find("/recovery") != std::string::npos) {
89 bf::remove(dir_entry.path(), error);
95 bf::path FindRecoveryFile() {
96 bf::path root_path = ci::GetRootAppPath(false);
97 for (auto& dir_entry : boost::make_iterator_range(
98 bf::directory_iterator(root_path), bf::directory_iterator())) {
99 if (bf::is_regular_file(dir_entry)) {
100 if (dir_entry.path().string().find("/recovery") != std::string::npos) {
101 return dir_entry.path();
108 bool ValidateFileContentInPackage(const std::string& pkgid,
109 const std::string& relative,
110 const std::string& expected) {
111 bf::path root_path = ci::GetRootAppPath(false);
112 bf::path file_path = root_path / pkgid / relative;
113 if (!bf::exists(file_path)) {
114 LOG(ERROR) << file_path << " doesn't exist";
117 FILE* handle = fopen(file_path.c_str(), "r");
119 LOG(ERROR) << file_path << " cannot be open";
123 std::array<char, 200> buffer;
124 while (fgets(buffer.data(), buffer.size(), handle)) {
125 content += buffer.data();
128 return content == expected;
131 void ValidatePackageFS(const std::string& pkgid, const std::string& appid) {
132 bf::path root_path = ci::GetRootAppPath(false);
133 bf::path package_path = root_path / pkgid;
134 bf::path binary_path = package_path / "bin" / appid;
135 bf::path data_path = package_path / "data";
136 bf::path shared_path = package_path / "shared";
137 bf::path cache_path = package_path / "cache";
138 ASSERT_TRUE(bf::exists(root_path));
139 ASSERT_TRUE(bf::exists(package_path));
140 ASSERT_TRUE(bf::exists(binary_path));
141 ASSERT_TRUE(bf::exists(data_path));
142 ASSERT_TRUE(bf::exists(shared_path));
143 ASSERT_TRUE(bf::exists(cache_path));
145 bf::path manifest_path =
146 bf::path(getUserManifestPath(getuid())) / (pkgid + ".xml");
147 bf::path icon_path = bf::path(getIconPath(getuid())) / (appid + ".png");
148 ASSERT_TRUE(bf::exists(manifest_path));
149 ASSERT_TRUE(bf::exists(icon_path));
151 bf::path widget_root_path = package_path / "res" / "wgt";
152 bf::path config_path = widget_root_path / "config.xml";
153 ASSERT_TRUE(bf::exists(widget_root_path));
154 ASSERT_TRUE(bf::exists(config_path));
156 bf::path private_tmp_path = package_path / "tmp";
157 ASSERT_TRUE(bf::exists(private_tmp_path));
159 // backups should not exist
160 bf::path package_backup = ci::GetBackupPathForPackagePath(package_path);
161 bf::path manifest_backup = ci::GetBackupPathForManifestFile(manifest_path);
162 bf::path icon_backup = ci::GetBackupPathForIconFile(icon_path);
163 ASSERT_FALSE(bf::exists(package_backup));
164 ASSERT_FALSE(bf::exists(manifest_backup));
165 ASSERT_FALSE(bf::exists(icon_backup));
168 void PackageCheckCleanup(const std::string& pkgid, const std::string& appid) {
169 bf::path root_path = ci::GetRootAppPath(false);
170 bf::path package_path = root_path / pkgid;
171 ASSERT_FALSE(bf::exists(package_path));
173 bf::path manifest_path =
174 bf::path(getUserManifestPath(getuid())) / (pkgid + ".xml");
175 bf::path icon_path = bf::path(getIconPath(getuid())) / (appid + ".png");
176 ASSERT_FALSE(bf::exists(manifest_path));
177 ASSERT_FALSE(bf::exists(icon_path));
179 // backups should not exist
180 bf::path package_backup = ci::GetBackupPathForPackagePath(package_path);
181 bf::path manifest_backup = ci::GetBackupPathForManifestFile(manifest_path);
182 bf::path icon_backup = ci::GetBackupPathForIconFile(icon_path);
183 ASSERT_FALSE(bf::exists(package_backup));
184 ASSERT_FALSE(bf::exists(manifest_backup));
185 ASSERT_FALSE(bf::exists(icon_backup));
188 void ValidatePackage(const std::string& pkgid, const std::string& appid) {
189 ASSERT_TRUE(ci::IsPackageInstalled(pkgid, ci::GetRequestMode()));
190 ValidatePackageFS(pkgid, appid);
193 void CheckPackageNonExistance(const std::string& pkgid,
194 const std::string& appid) {
195 ASSERT_FALSE(ci::IsPackageInstalled(pkgid, ci::GetRequestMode()));
196 PackageCheckCleanup(pkgid, appid);
199 std::unique_ptr<ci::AppQueryInterface> CreateQueryInterface() {
200 std::unique_ptr<ci::AppQueryInterface> query_interface(
201 new wgt::WgtAppQueryInterface());
202 return query_interface;
205 std::unique_ptr<ci::AppInstaller> CreateInstaller(ci::PkgMgrPtr pkgmgr) {
206 std::unique_ptr<ci::AppInstaller> installer(new wgt::WgtInstaller(pkgmgr));
210 ci::AppInstaller::Result RunInstallerWithPkgrmgr(ci::PkgMgrPtr pkgmgr,
211 RequestResult mode) {
212 std::unique_ptr<ci::AppInstaller> installer = CreateInstaller(pkgmgr);
214 case RequestResult::FAIL:
215 installer->AddStep<ci::configuration::StepFail>();
217 case RequestResult::CRASH:
218 installer->AddStep<StepCrash>();
222 return installer->Run();
225 ci::AppInstaller::Result Install(const bf::path& path,
226 RequestResult mode = RequestResult::NORMAL) {
227 const char* argv[] = {"", "-i", path.c_str()};
228 TestPkgmgrInstaller pkgmgr_installer;
229 std::unique_ptr<ci::AppQueryInterface> query_interface =
230 CreateQueryInterface();
232 ci::PkgMgrInterface::Create(SIZEOFARRAY(argv), const_cast<char**>(argv),
233 &pkgmgr_installer, query_interface.get());
235 LOG(ERROR) << "Failed to initialize pkgmgr interface";
236 return ci::AppInstaller::Result::UNKNOWN;
238 return RunInstallerWithPkgrmgr(pkgmgr, mode);
241 ci::AppInstaller::Result Update(const bf::path& path_old,
242 const bf::path& path_new,
243 RequestResult mode = RequestResult::NORMAL) {
244 if (Install(path_old) != ci::AppInstaller::Result::OK) {
245 LOG(ERROR) << "Failed to install application. Cannot update";
246 return ci::AppInstaller::Result::UNKNOWN;
248 return Install(path_new, mode);
251 ci::AppInstaller::Result Uninstall(const std::string& pkgid,
252 RequestResult mode = RequestResult::NORMAL) {
253 const char* argv[] = {"", "-d", pkgid.c_str()};
254 TestPkgmgrInstaller pkgmgr_installer;
255 std::unique_ptr<ci::AppQueryInterface> query_interface =
256 CreateQueryInterface();
258 ci::PkgMgrInterface::Create(SIZEOFARRAY(argv), const_cast<char**>(argv),
259 &pkgmgr_installer, query_interface.get());
261 LOG(ERROR) << "Failed to initialize pkgmgr interface";
262 return ci::AppInstaller::Result::UNKNOWN;
264 return RunInstallerWithPkgrmgr(pkgmgr, mode);
267 ci::AppInstaller::Result Reinstall(const bf::path& path,
268 const bf::path& delta_dir,
269 RequestResult mode = RequestResult::NORMAL) {
270 if (Install(path) != ci::AppInstaller::Result::OK) {
271 LOG(ERROR) << "Failed to install application. Cannot perform RDS";
272 return ci::AppInstaller::Result::UNKNOWN;
274 const char* argv[] = {"", "-r", delta_dir.c_str()};
275 TestPkgmgrInstaller pkgmgr_installer;
276 std::unique_ptr<ci::AppQueryInterface> query_interface =
277 CreateQueryInterface();
279 ci::PkgMgrInterface::Create(SIZEOFARRAY(argv), const_cast<char**>(argv),
280 &pkgmgr_installer, query_interface.get());
282 LOG(ERROR) << "Failed to initialize pkgmgr interface";
283 return ci::AppInstaller::Result::UNKNOWN;
285 return RunInstallerWithPkgrmgr(pkgmgr, mode);
288 ci::AppInstaller::Result DeltaInstall(const bf::path& path,
289 const bf::path& delta_package) {
290 if (Install(path) != ci::AppInstaller::Result::OK) {
291 LOG(ERROR) << "Failed to install application. Cannot perform RDS";
292 return ci::AppInstaller::Result::UNKNOWN;
294 return Install(delta_package);
297 ci::AppInstaller::Result Recover(const bf::path& recovery_file,
298 RequestResult mode = RequestResult::NORMAL) {
299 const char* argv[] = {"", "-b", recovery_file.c_str()};
300 TestPkgmgrInstaller pkgmgr_installer;
301 std::unique_ptr<ci::AppQueryInterface> query_interface =
302 CreateQueryInterface();
304 ci::PkgMgrInterface::Create(SIZEOFARRAY(argv), const_cast<char**>(argv),
305 &pkgmgr_installer, query_interface.get());
307 LOG(ERROR) << "Failed to initialize pkgmgr interface";
308 return ci::AppInstaller::Result::UNKNOWN;
310 return RunInstallerWithPkgrmgr(pkgmgr, mode);
315 namespace common_installer {
317 class SmokeEnvironment : public testing::Environment {
319 explicit SmokeEnvironment(const bf::path& home) : home_(home) {
321 void SetUp() override {
322 bs::error_code error;
323 bf::remove_all(home_ / kApplicationDirBackup, error);
324 bf::remove_all(home_ / KUserAppsDirBackup, error);
325 if (bf::exists(home_ / KUserAppsDir)) {
326 bf::rename(home_ / KUserAppsDir, home_ / KUserAppsDirBackup, error);
328 LOG(ERROR) << "Failed to setup test environment. Does some previous"
329 << " test crashed? Directory: "
330 << (home_ / KUserAppsDirBackup) << " should not exist.";
333 if (bf::exists(home_ / kApplicationDir)) {
334 bf::rename(home_ / kApplicationDir, home_ / kApplicationDirBackup, error);
336 LOG(ERROR) << "Failed to setup test environment. Does some previous"
337 << " test crashed? Directory: "
338 << (home_ / kApplicationDirBackup) << " should not exist.";
342 void TearDown() override {
343 bs::error_code error;
344 bf::remove_all(home_ / kApplicationDir, error);
345 bf::remove_all(home_ / KUserAppsDir, error);
346 if (bf::exists(home_ / KUserAppsDirBackup))
347 bf::rename(home_ / KUserAppsDirBackup, home_ / KUserAppsDir, error);
348 if (bf::exists(home_ / kApplicationDirBackup))
349 bf::rename(home_ / kApplicationDirBackup, home_ / kApplicationDir, error);
356 class SmokeTest : public testing::Test {
359 TEST_F(SmokeTest, InstallationMode) {
360 bf::path path = kSmokePackagesDirectory / "InstallationMode.wgt";
361 std::string pkgid = "smokeapp03";
362 std::string appid = "smokeapp03.InstallationMode";
363 ASSERT_EQ(Install(path), ci::AppInstaller::Result::OK);
364 ValidatePackage(pkgid, appid);
367 TEST_F(SmokeTest, UpdateMode) {
368 bf::path path_old = kSmokePackagesDirectory / "UpdateMode.wgt";
369 bf::path path_new = kSmokePackagesDirectory / "UpdateMode_2.wgt";
370 std::string pkgid = "smokeapp04";
371 std::string appid = "smokeapp04.UpdateMode";
372 ASSERT_EQ(Update(path_old, path_new), ci::AppInstaller::Result::OK);
373 ValidatePackage(pkgid, appid);
375 ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "2\n"));
378 TEST_F(SmokeTest, DeinstallationMode) {
379 bf::path path = kSmokePackagesDirectory / "DeinstallationMode.wgt";
380 std::string pkgid = "smokeapp05";
381 std::string appid = "smokeapp05.DeinstallationMode";
382 ASSERT_EQ(Install(path),
383 ci::AppInstaller::Result::OK);
384 ASSERT_EQ(Uninstall(pkgid), ci::AppInstaller::Result::OK);
385 CheckPackageNonExistance(pkgid, appid);
388 TEST_F(SmokeTest, RDSMode) {
389 bf::path path = kSmokePackagesDirectory / "RDSMode.wgt";
390 bf::path delta_directory = kSmokePackagesDirectory / "delta_dir/";
391 std::string pkgid = "smokeapp11";
392 std::string appid = "smokeapp11.RDSMode";
393 ASSERT_EQ(Reinstall(path, delta_directory),
394 ci::AppInstaller::Result::OK);
395 ValidatePackage(pkgid, appid);
397 // Check delta modifications
398 bf::path root_path = ci::GetRootAppPath(false);
399 ASSERT_FALSE(bf::exists(root_path / pkgid / "res" / "wgt" / "DELETED"));
400 ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "ADDED"));
401 ValidateFileContentInPackage(pkgid, "res/wgt/MODIFIED", "2\n");
404 TEST_F(SmokeTest, DeltaMode) {
405 bf::path path = kSmokePackagesDirectory / "DeltaMode.wgt";
406 bf::path delta_package = kSmokePackagesDirectory / "DeltaMode.delta";
407 std::string pkgid = "smokeapp17";
408 std::string appid = "smokeapp17.DeltaMode";
409 ASSERT_EQ(DeltaInstall(path, delta_package),
410 ci::AppInstaller::Result::OK);
411 ValidatePackage(pkgid, appid);
413 // Check delta modifications
414 bf::path root_path = ci::GetRootAppPath(false);
415 ASSERT_FALSE(bf::exists(root_path / pkgid / "res" / "wgt" / "DELETED"));
416 ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "ADDED"));
417 ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "css" / "style.css")); // NOLINT
418 ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "images" / "tizen_32.png")); // NOLINT
419 ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "js" / "main.js"));
420 ValidateFileContentInPackage(pkgid, "res/wgt/MODIFIED", "version 2\n");
423 TEST_F(SmokeTest, RecoveryMode_ForInstallation) {
424 bf::path path = kSmokePackagesDirectory / "RecoveryMode_ForInstallation.wgt";
425 ASSERT_DEATH(Install(path, RequestResult::CRASH), ".*");
427 std::string pkgid = "smokeapp09";
428 std::string appid = "smokeapp09.RecoveryModeForInstallation";
429 bf::path recovery_file = FindRecoveryFile();
430 ASSERT_FALSE(recovery_file.empty());
431 ASSERT_EQ(Recover(recovery_file),
432 ci::AppInstaller::Result::OK);
433 CheckPackageNonExistance(pkgid, appid);
436 TEST_F(SmokeTest, RecoveryMode_ForUpdate) {
437 bf::path path_old = kSmokePackagesDirectory / "RecoveryMode_ForUpdate.wgt";
438 bf::path path_new = kSmokePackagesDirectory / "RecoveryMode_ForUpdate_2.wgt";
439 RemoveAllRecoveryFiles();
440 ASSERT_DEATH(Update(path_old, path_new, RequestResult::CRASH), ".*");
442 std::string pkgid = "smokeapp10";
443 std::string appid = "smokeapp10.RecoveryModeForUpdate";
444 bf::path recovery_file = FindRecoveryFile();
445 ASSERT_FALSE(recovery_file.empty());
446 ASSERT_EQ(Recover(recovery_file),
447 ci::AppInstaller::Result::OK);
448 ValidatePackage(pkgid, appid);
450 ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "1\n"));
453 TEST_F(SmokeTest, InstallationMode_GoodSignature) {
454 bf::path path = kSmokePackagesDirectory / "InstallationMode_GoodSignature.wgt"; // NOLINT
455 ASSERT_EQ(Install(path), ci::AppInstaller::Result::OK);
458 TEST_F(SmokeTest, InstallationMode_WrongSignature) {
459 bf::path path = kSmokePackagesDirectory / "InstallationMode_WrongSignature.wgt"; // NOLINT
460 ASSERT_EQ(Install(path), ci::AppInstaller::Result::ERROR);
463 TEST_F(SmokeTest, InstallationMode_Rollback) {
464 bf::path path = kSmokePackagesDirectory / "InstallationMode_Rollback.wgt";
465 std::string pkgid = "smokeapp06";
466 std::string appid = "smokeapp06.InstallationModeRollback";
467 ASSERT_EQ(Install(path, RequestResult::FAIL),
468 ci::AppInstaller::Result::ERROR);
469 CheckPackageNonExistance(pkgid, appid);
472 TEST_F(SmokeTest, UpdateMode_Rollback) {
473 bf::path path_old = kSmokePackagesDirectory / "UpdateMode_Rollback.wgt";
474 bf::path path_new = kSmokePackagesDirectory / "UpdateMode_Rollback_2.wgt";
475 std::string pkgid = "smokeapp07";
476 std::string appid = "smokeapp07.UpdateModeRollback";
477 ASSERT_EQ(Update(path_old, path_new, RequestResult::FAIL),
478 ci::AppInstaller::Result::ERROR);
479 ValidatePackage(pkgid, appid);
481 ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "1\n"));
484 } // namespace common_installer
486 int main(int argc, char** argv) {
487 testing::InitGoogleTest(&argc, argv);
488 const char* directory = getenv("HOME");
490 LOG(ERROR) << "Cannot get $HOME value";
493 testing::AddGlobalTestEnvironment(
494 new common_installer::SmokeEnvironment(directory));
495 return RUN_ALL_TESTS();