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