57afe29951fbc363f8b642af4d8d936b92efe277
[platform/core/appfw/app-installers.git] / src / unit_tests / common / smoke_utils.h
1 // Copyright (c) 2017 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 #ifndef UNIT_TESTS_COMMON_SMOKE_UTILS_H_
6 #define UNIT_TESTS_COMMON_SMOKE_UTILS_H_
7
8 #include <pkgmgr-info.h>
9 #include <signal.h>
10 #include <unistd.h>
11 #include <tzplatform_config.h>
12
13 #include <boost/filesystem/operations.hpp>
14 #include <boost/range/iterator_range.hpp>
15 #include <boost/format.hpp>
16 #include <boost/program_options.hpp>
17 #include <boost/system/error_code.hpp>
18
19 #include <gtest/gtest.h>
20 #include <gtest/gtest-death-test.h>
21
22 #include <manifest_parser/utils/version_number.h>
23
24 #include <common/utils/subprocess.h>
25 #include <common/utils/user_util.h>
26 #include <common/utils/file_util.h>
27 #include <common/utils/request.h>
28 #include <common/tzip_interface.h>
29 #include <common/installer/app_installer.h>
30 #include <common/utils/paths.h>
31 #include <common/utils/pkgmgr_query.h>
32 #include <common/recovery_file.h>
33
34 #include <array>
35 #include <cstdio>
36 #include <cstdlib>
37 #include <memory>
38 #include <regex>
39 #include <string>
40 #include <vector>
41 #include <utility>
42
43 #define SIZEOFARRAY(ARR)                                                       \
44   sizeof(ARR) / sizeof(ARR[0])                                                 \
45
46 #define EXTENDED_ASSERT_TRUE(expression) do {                                  \
47     bool tmp = expression;                                                     \
48     EXPECT_TRUE(tmp) << #expression << " is not true";                         \
49     if (!tmp)                                                                  \
50         return false;                                                          \
51 } while (0);
52
53 #define EXTENDED_ASSERT_FALSE(expression) do {                                 \
54     bool tmp = expression;                                                     \
55     EXPECT_FALSE(tmp) << #expression << " is not false";                       \
56     if (tmp)                                                                   \
57         return false;                                                          \
58 } while (0);
59
60 #define EXTENDED_ASSERT_EQ(expression, value) do {                             \
61     auto ret = expression;                                                     \
62     EXPECT_EQ(ret, value) << #expression << " is not equal to " << #value;     \
63     if (ret != value)                                                          \
64         return false;                                                          \
65 } while (0);
66
67 namespace smoke_test {
68
69 extern const bf::path kSmokePackagesDirectory;
70 extern const bf::path kSdkDirectory;
71 extern const uid_t kGlobalUserUid;
72 extern const uid_t kGlobalUserGid;
73 extern const char kLegacyExtImageDir[];
74 extern const std::string& kDefaultUserIdStr;
75
76 using App = std::pair<std::string, std::string>;
77 using Apps = std::vector<App>;
78
79 enum class RequestResult {
80   NORMAL,
81   FAIL
82 };
83
84 enum class StorageType {
85   INTERNAL,
86   EXTERNAL,
87   EXTENDED
88 };
89
90 class ScopedTzipInterface {
91  public:
92   explicit ScopedTzipInterface(const std::string& pkgid, uid_t test_user)
93       : pkg_path_(boost::filesystem::path(
94           common_installer::GetRootAppPath(false, test_user)) / pkgid),
95         interface_(common_installer::GetMountLocation(pkg_path_)),
96         mounted_(true) {
97     interface_.MountZip(common_installer::GetZipPackageLocation(pkg_path_,
98                                                                 pkgid));
99   }
100
101   void Release() {
102     if (mounted_) {
103       interface_.UnmountZip();
104       mounted_ = false;
105     }
106   }
107
108   ~ScopedTzipInterface() {
109     Release();
110   }
111
112  private:
113   boost::filesystem::path pkg_path_;
114   common_installer::TzipInterface interface_;
115   bool mounted_;
116 };
117
118 class TestPkgmgrInstaller : public common_installer::PkgmgrInstallerInterface {
119  public:
120   bool CreatePkgMgrInstaller(pkgmgr_installer** installer,
121                              common_installer::InstallationMode* mode) {
122     *installer = pkgmgr_installer_offline_new();
123     if (!*installer)
124       return false;
125     *mode = common_installer::InstallationMode::ONLINE;
126     return true;
127   }
128
129   bool ShouldCreateSignal() const {
130     return false;
131   }
132 };
133
134 enum class PackageType {
135   TPK,
136   WGT,
137   HYBRID
138 };
139
140 struct User {
141   uid_t uid = kGlobalUserUid;
142   gid_t gid = kGlobalUserGid;
143 };
144
145 struct TestParameters {
146   TestParameters(PackageType type, bool readonly) :
147       pkg_type(type), is_readonly(readonly) {}
148   TestParameters(const TestParameters& other) : pkg_type(other.pkg_type),
149       is_readonly(other.is_readonly), test_user{other.test_user} {}
150   PackageType pkg_type;
151   bool is_readonly;
152   User test_user;
153 };
154
155 struct PackageAttributes {
156   explicit PackageAttributes(common_installer::PkgQueryInterface pi)
157       : is_global(pi.IsGlobalPackage()), is_readonly(pi.IsReadonlyPackage()),
158         is_update(pi.IsUpdatedPackage()), is_preload(pi.IsPreloadPackage()),
159         is_system(pi.IsSystemPackage()), is_removable(pi.IsRemovablePackage()) {
160   }
161
162   bool operator==(const PackageAttributes& other) const {
163     return (is_global == other.is_global) &&
164            (is_readonly == other.is_readonly) &&
165            (is_update == other.is_update) &&
166            (is_preload == other.is_preload) &&
167            (is_system == other.is_system) &&
168            (is_removable == other.is_removable);
169   }
170
171   bool is_global;
172   bool is_readonly;
173   bool is_update;
174   bool is_preload;
175   bool is_system;
176   bool is_removable;
177 };
178
179 common_installer::RequestMode ParseRequestMode(int argc,  char** argv);
180
181 bool TouchFile(const boost::filesystem::path& path);
182
183 void AddDataFiles(const std::string& pkgid, uid_t uid);
184
185 bool AddTestUser(User* test_user);
186
187 bool DeleteTestUser();
188
189 void RemoveAllRecoveryFiles(const std::string& prefix, uid_t uid);
190
191 boost::filesystem::path FindRecoveryFile(const std::string& prefix, uid_t uid);
192
193 boost::filesystem::path GetPackageRoot(const std::string& pkgid, uid_t uid);
194
195 std::unique_ptr<common_installer::recovery::RecoveryFile> GetRecoverFileInfo(
196     const bf::path& recovery_file_path);
197
198 bool ValidateFileContentInPackage(const std::string& pkgid,
199                                   const std::string& relative,
200                                   const std::string& expected,
201                                   const TestParameters& params);
202
203 bool ValidatePackage(const std::string& pkgid, const Apps& apps,
204     const TestParameters& params);
205
206 bool ValidateDataFiles(const std::string& pkgid, uid_t uid);
207
208 bool ValidateExternalPackage(const std::string& pkgid, const Apps& apps,
209     const TestParameters& params);
210 bool ValidateExtendedPackage(const std::string& pkgid, const Apps& apps,
211     const TestParameters& params);
212
213 bool CheckPackageNonExistance(const std::string& pkgid,
214                               const TestParameters& params);
215
216 bool CheckPackageReadonlyNonExistance(const std::string& pkgid,
217                                       const TestParameters& params);
218
219 bool CheckSharedDataExistance(const std::string& pkgid,
220                               const TestParameters& params);
221
222 bool CheckSharedDataNonExistance(const std::string& pkgid,
223                                 const TestParameters& params);
224
225 bool TouchFile(const boost::filesystem::path& path);
226
227 class SmokeInstallerFactory {
228  public:
229   using AppInstallerPtr = std::unique_ptr<common_installer::AppInstaller>;
230   virtual AppInstallerPtr CreateInstaller(
231       int idx, common_installer::PkgMgrPtr pkgmgr) const = 0;
232   virtual AppInstallerPtr CreateFailExpectedInstaller(
233       int idx, common_installer::PkgMgrPtr pkgmgr, int fail_at = -1) const = 0;
234 };
235
236 class BackendInterface {
237  public:
238   using CommandResult = common_installer::AppInstaller::Result;
239   using SmokeInstallerFactoryPtr = std::unique_ptr<SmokeInstallerFactory>;
240   explicit BackendInterface(std::string uid,
241       RequestResult mode = RequestResult::NORMAL)
242       : uid_str_(uid), mode_(mode) {}
243   explicit BackendInterface(SmokeInstallerFactoryPtr factory,
244       std::string uid,
245       RequestResult mode = RequestResult::NORMAL)
246       : factory_(std::move(factory)), uid_str_(uid), mode_(mode) {}
247   virtual ~BackendInterface() {}
248
249   void TestRollbackAfterEachStep(int argc, const char* argv[],
250                                  std::function<bool()> validator) const;
251   void CrashAfterEachStep(std::vector<std::string>* args,
252                           std::function<bool(int iter)> validator,
253                           PackageType type) const;
254   CommandResult Install(const std::vector<bf::path>& paths) const;
255   CommandResult InstallSuccess(const std::vector<bf::path>& paths) const;
256   CommandResult Install(const boost::filesystem::path& path) const;
257   CommandResult InstallPreload(const boost::filesystem::path& path) const;
258   CommandResult InstallWithStorage(const boost::filesystem::path& path,
259       StorageType type = StorageType::INTERNAL) const;
260   CommandResult InstallSuccess(const bf::path& path) const;
261   CommandResult InstallPreloadSuccess(
262       const boost::filesystem::path& path) const;
263
264   CommandResult Uninstall(const std::vector<std::string>& pkgids) const;
265   CommandResult Uninstall(const std::string& pkgid) const;
266   CommandResult UninstallPreload(const std::string& pkgid) const;
267
268   CommandResult EnablePackage(const std::string& pkgid) const;
269   CommandResult DisablePackage(const std::string& pkgid) const;
270
271   CommandResult MountInstall(const boost::filesystem::path& path) const;
272   CommandResult MountInstallSuccess(const bf::path& path) const;
273   CommandResult ManifestDirectInstall(const std::string& pkgid) const;
274
275   CommandResult MigrateLegacyExternalImage(const std::string& pkgid,
276       const boost::filesystem::path& path,
277       const boost::filesystem::path& legacy_path) const;
278
279   CommandResult RDSUpdate(const boost::filesystem::path& path,
280       const std::string& pkgid) const;
281
282   CommandResult Recover(const boost::filesystem::path& recovery_file) const;
283
284  protected:
285   CommandResult CallBackend(int argc, const char* argv[]) const;
286   CommandResult CallBackendWithRunner(int argc, const char* argv[]) const;
287   using AppQueryInterfacePtr =
288       std::unique_ptr<common_installer::AppQueryInterface>;
289   using AppInstallerPtr = std::unique_ptr<common_installer::AppInstaller>;
290   SmokeInstallerFactoryPtr factory_;
291   std::string uid_str_;
292   RequestResult mode_;
293
294  private:
295   CommandResult RunInstallerWithPkgrmgr(
296       common_installer::PkgMgrPtr pkgmgr) const;
297   virtual AppQueryInterfacePtr CreateQueryInterface() const = 0;
298   virtual AppInstallerPtr CreateInstaller(
299       common_installer::PkgMgrPtr pkgmgr) const = 0;
300   virtual AppInstallerPtr CreateFailExpectedInstaller(
301       common_installer::PkgMgrPtr pkgmgr, int fail_at = -1) const = 0;
302   CommandResult RunInstallersWithPkgmgr(
303       common_installer::PkgMgrPtr pkgmgr) const;
304 };
305
306 class SmokeTestHelperRunner {
307  public:
308   enum class Result {
309     SUCCESS,
310     FAIL,
311     KILLED,
312     UnKnown
313   };
314
315   Result InstallWithSubprocess(const bf::path& path, uid_t uid) const;
316   Result MountInstallWithSubprocess(const bf::path& path, uid_t uid) const;
317   Result RecoveryWithSubprocess(const bf::path& path, uid_t uid) const;
318   Result UninstallWithSubprocess(const std::string& pkgid, uid_t uid) const;
319   Result InstallWithSubprocessAndKill(
320       const bf::path& path, uid_t uid, useconds_t delay) const;
321   Result MountInstallWithSubprocessAndKill(
322       const bf::path& path, uid_t uid, useconds_t delay) const;
323   Result UninstallWithSubprocessAndKill(
324       const std::string& pkgid, uid_t uid, useconds_t delay) const;
325   Result InstallPkgsWithSubprocess(
326       const std::vector<bf::path>& paths, uid_t uid) const;
327   Result MountInstallPkgsWithSubprocess(
328       const std::vector<bf::path>& paths, uid_t uid) const;
329   Result RecoveryPkgsWithSubprocess(
330       const std::vector<bf::path>& paths, uid_t uid) const;
331   Result UninstallPkgsWithSubprocess(
332       const std::vector<std::string>& pkgids, uid_t uid) const;
333   Result InstallPkgsWithSubprocessAndKill(
334       const std::vector<bf::path>& paths, uid_t uid, useconds_t delay) const;
335   Result MountInstallPkgsWithSubprocessAndKill(
336       const std::vector<bf::path>& paths, uid_t uid, useconds_t delay) const;
337
338  private:
339   Result RunSubprocess(std::vector<std::string> args) const;
340   Result RunSubprocessAndKill(std::vector<std::string> args,
341       useconds_t delay) const;
342   virtual common_installer::Subprocess CreateSubprocess() const = 0;
343 };
344
345 bool CheckAvailableExternalPath();
346
347 bool CheckAvailableExtendedPath();
348
349 bool BackupPathCopyAndRemove(const boost::filesystem::path& path);
350
351 bool BackupPath(const boost::filesystem::path& path);
352
353 bool RestorePathCopyAndRemove(const boost::filesystem::path& path);
354
355 bool RestorePath(const boost::filesystem::path& path);
356
357 std::vector<boost::filesystem::path> SetupBackupDirectories(uid_t test_uid);
358
359 void UninstallAllAppsInDirectory(boost::filesystem::path dir, bool is_preload,
360     BackendInterface* backend);
361
362 void UninstallAllSmokeApps(common_installer::RequestMode request_mode,
363     uid_t test_uid, BackendInterface* backend);
364
365 int GetAppInstalledTime(const char* appid, uid_t uid);
366
367 enum class CrashStepType {
368   PROCESS,
369   CLEAN
370 };
371
372 class StepCrash : public common_installer::Step {
373  public:
374   using Step::Step;
375
376   explicit StepCrash(common_installer::InstallerContext* context,
377       CrashStepType type)
378       : common_installer::Step::Step(context), type_(type) {}
379
380   common_installer::Step::Status process() override {
381     if (type_ == CrashStepType::PROCESS)
382       raise(SIGSEGV);
383     return Status::OK;
384   }
385   common_installer::Step::Status clean() override {
386     if (type_ == CrashStepType::CLEAN)
387       raise(SIGSEGV);
388     return Status::OK;
389   }
390   common_installer::Step::Status undo() override {
391     return common_installer::Step::Status::OK;
392   }
393   common_installer::Step::Status precheck() override {
394     return common_installer::Step::Status::OK;
395   }
396
397   STEP_NAME(Crash)
398
399  private:
400   CrashStepType type_;
401 };
402
403 }  // namespace smoke_test
404
405 #endif  // UNIT_TESTS_COMMON_SMOKE_UTILS_H_