Add FileInfoCollector class
[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 <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 class FileInfoCollector {
156  public:
157   using FileInfo = std::tuple<bf::path, bf::file_type, bf::perms,
158       std::string, std::string, std::string>;
159
160   FileInfoCollector(std::string pkgid, TestParameters params) :
161       pkgid_(pkgid), params_(params) {}
162   bool FileInfoToFile(const bf::path& path) const;
163   bool Init();
164   bool IsEqual(const FileInfoCollector& collector,
165       const std::vector<bf::path>* exception_list = nullptr) const;
166   bool LoadFromFile(const bf::path& path);
167
168  private:
169   void AddPath(const bf::path& path);
170   bool CollectFileInfoRecursive();
171   bool GetFileListTraversal(const bf::path& cur);
172   std::string FileInfoToString(const FileInfo& file_info) const;
173
174   std::string pkgid_;
175   TestParameters params_;
176   std::vector<bf::path> root_paths_;
177   std::vector<FileInfo> FileInfos_;
178 };
179
180 struct PackageAttributes {
181   explicit PackageAttributes(common_installer::PkgQueryInterface pi)
182       : is_global(pi.IsGlobalPackage()), is_readonly(pi.IsReadonlyPackage()),
183         is_update(pi.IsUpdatedPackage()), is_preload(pi.IsPreloadPackage()),
184         is_system(pi.IsSystemPackage()), is_removable(pi.IsRemovablePackage()) {
185   }
186
187   bool operator==(const PackageAttributes& other) const {
188     return (is_global == other.is_global) &&
189            (is_readonly == other.is_readonly) &&
190            (is_update == other.is_update) &&
191            (is_preload == other.is_preload) &&
192            (is_system == other.is_system) &&
193            (is_removable == other.is_removable);
194   }
195
196   bool is_global;
197   bool is_readonly;
198   bool is_update;
199   bool is_preload;
200   bool is_system;
201   bool is_removable;
202 };
203
204 common_installer::RequestMode ParseRequestMode(int argc,  char** argv);
205
206 bool TouchFile(const boost::filesystem::path& path);
207
208 void AddDataFiles(const std::string& pkgid, uid_t uid,
209     std::vector<bf::path>* result = nullptr);
210
211 bool AddTestUser(User* test_user);
212
213 bool DeleteTestUser();
214
215 void RemoveAllRecoveryFiles(const std::string& prefix, uid_t uid);
216
217 boost::filesystem::path FindRecoveryFile(const std::string& prefix, uid_t uid);
218
219 boost::filesystem::path GetPackageRoot(const std::string& pkgid, uid_t uid);
220
221 std::unique_ptr<common_installer::recovery::RecoveryFile> GetRecoverFileInfo(
222     const bf::path& recovery_file_path);
223
224 bool ValidateFileContentInPackage(const std::string& pkgid,
225                                   const std::string& relative,
226                                   const std::string& expected,
227                                   const TestParameters& params);
228
229 bool ValidatePackage(const std::string& pkgid, const Apps& apps,
230     const TestParameters& params);
231
232 bool ValidateDataFiles(const std::string& pkgid, uid_t uid);
233
234 bool ValidateExternalPackage(const std::string& pkgid, const Apps& apps,
235     const TestParameters& params);
236 bool ValidateExtendedPackage(const std::string& pkgid, const Apps& apps,
237     const TestParameters& params);
238
239 bool CheckPackageNonExistance(const std::string& pkgid,
240                               const TestParameters& params);
241
242 bool CheckPackageReadonlyNonExistance(const std::string& pkgid,
243                                       const TestParameters& params);
244
245 bool CheckSharedDataExistance(const std::string& pkgid,
246                               const TestParameters& params);
247
248 bool CheckSharedDataNonExistance(const std::string& pkgid,
249                                 const TestParameters& params);
250
251 bool TouchFile(const boost::filesystem::path& path);
252
253 class SmokeInstallerFactory {
254  public:
255   using AppInstallerPtr = std::unique_ptr<common_installer::AppInstaller>;
256   virtual ~SmokeInstallerFactory() = default;
257   virtual AppInstallerPtr CreateInstaller(
258       int idx, common_installer::PkgMgrPtr pkgmgr) const = 0;
259   virtual AppInstallerPtr CreateFailExpectedInstaller(
260       int idx, common_installer::PkgMgrPtr pkgmgr, int fail_at = -1) const = 0;
261 };
262
263 class BackendInterface {
264  public:
265   enum class SubProcessResult {
266     SUCCESS,
267     FAIL,
268     KILLED,
269     UnKnown
270   };
271
272   using CommandResult = common_installer::AppInstaller::Result;
273   using SmokeInstallerFactoryPtr = std::unique_ptr<SmokeInstallerFactory>;
274   explicit BackendInterface(std::string uid,
275       RequestResult mode = RequestResult::NORMAL)
276       : uid_str_(uid), mode_(mode) {}
277   explicit BackendInterface(SmokeInstallerFactoryPtr factory,
278       std::string uid,
279       RequestResult mode = RequestResult::NORMAL)
280       : factory_(std::move(factory)), uid_str_(uid), mode_(mode) {}
281   virtual ~BackendInterface() = default;
282
283   void TestRollbackAfterEachStep(int argc, const char* argv[],
284                                  std::function<bool()> validator) const;
285   void CrashAfterEachStep(std::vector<std::string>* args,
286                           std::function<bool(int iter)> validator,
287                           PackageType type) const;
288   CommandResult Install(const std::vector<bf::path>& paths) const;
289   CommandResult InstallSuccess(const std::vector<bf::path>& paths) const;
290   CommandResult Install(const boost::filesystem::path& path) const;
291   CommandResult InstallPreload(const boost::filesystem::path& path) const;
292   CommandResult InstallWithStorage(const boost::filesystem::path& path,
293       StorageType type = StorageType::INTERNAL) const;
294   CommandResult InstallSuccess(const bf::path& path) const;
295   CommandResult InstallPreloadSuccess(
296       const boost::filesystem::path& path) const;
297
298   CommandResult Uninstall(const std::vector<std::string>& pkgids) const;
299   CommandResult Uninstall(const std::string& pkgid) const;
300   CommandResult UninstallPreload(const std::string& pkgid) const;
301
302   CommandResult EnablePackage(const std::string& pkgid) const;
303   CommandResult DisablePackage(const std::string& pkgid) const;
304
305   CommandResult MountInstall(const boost::filesystem::path& path) const;
306   CommandResult MountInstallSuccess(const bf::path& path) const;
307   CommandResult ManifestDirectInstall(const std::string& pkgid) const;
308
309   CommandResult MigrateLegacyExternalImage(const std::string& pkgid,
310       const boost::filesystem::path& path,
311       const boost::filesystem::path& legacy_path) const;
312
313   CommandResult RDSUpdate(const boost::filesystem::path& path,
314       const std::string& pkgid) const;
315
316   CommandResult Recover(const boost::filesystem::path& recovery_file) const;
317
318   SubProcessResult InstallWithSubprocess(const bf::path& path) const;
319   SubProcessResult MountInstallWithSubprocess(const bf::path& path) const;
320   SubProcessResult RecoverWithSubprocess(const bf::path& path) const;
321   SubProcessResult UninstallWithSubprocess(const std::string& pkgid) const;
322   SubProcessResult InstallPreloadWithSubprocess(
323       const boost::filesystem::path& path) const;
324   SubProcessResult InstallWithSubprocessAndKill(
325       const bf::path& path, useconds_t delay) const;
326   SubProcessResult MountInstallWithSubprocessAndKill(
327       const bf::path& path, useconds_t delay) const;
328   SubProcessResult UninstallWithSubprocessAndKill(
329       const std::string& pkgid, useconds_t delay) const;
330   SubProcessResult InstallPkgsWithSubprocess(
331       const std::vector<bf::path>& paths) const;
332   SubProcessResult MountInstallPkgsWithSubprocess(
333       const std::vector<bf::path>& paths) const;
334   SubProcessResult RecoverPkgsWithSubprocess(
335       const std::vector<bf::path>& paths) const;
336   SubProcessResult UninstallPkgsWithSubprocess(
337       const std::vector<std::string>& pkgids) const;
338   SubProcessResult InstallPkgsWithSubprocessAndKill(
339       const std::vector<bf::path>& paths, useconds_t delay) const;
340   SubProcessResult MountInstallPkgsWithSubprocessAndKill(
341       const std::vector<bf::path>& paths, useconds_t delay) const;
342
343  protected:
344   CommandResult CallBackend(int argc, const char* argv[]) const;
345   CommandResult CallBackendWithRunner(int argc, const char* argv[]) const;
346   using AppQueryInterfacePtr =
347       std::shared_ptr<common_installer::AppQueryInterface>;
348   using AppInstallerPtr = std::unique_ptr<common_installer::AppInstaller>;
349   SmokeInstallerFactoryPtr factory_;
350   std::string uid_str_;
351   RequestResult mode_;
352
353  protected:
354   CommandResult RunInstallerWithPkgrmgr(
355       common_installer::PkgMgrPtr pkgmgr) const;
356   virtual AppQueryInterfacePtr CreateQueryInterface() const = 0;
357   virtual AppInstallerPtr CreateInstaller(
358       common_installer::PkgMgrPtr pkgmgr) const = 0;
359   virtual AppInstallerPtr CreateFailExpectedInstaller(
360       common_installer::PkgMgrPtr pkgmgr, int fail_at = -1) const = 0;
361   CommandResult RunInstallersWithPkgmgr(
362       common_installer::PkgMgrPtr pkgmgr) const;
363   SubProcessResult RunSubprocess(std::vector<std::string> args) const;
364   SubProcessResult RunSubprocessAndKill(std::vector<std::string> args,
365       useconds_t delay) const;
366   virtual common_installer::Subprocess CreateSubprocess() const {
367     return common_installer::Subprocess("");
368   }
369 };
370
371 bool CheckAvailableExternalPath();
372
373 bool CheckAvailableExtendedPath();
374
375 bool BackupPathCopyAndRemove(const boost::filesystem::path& path);
376
377 bool BackupPath(const boost::filesystem::path& path);
378
379 void CreateDatabase();
380
381 bool RestorePathCopyAndRemove(const boost::filesystem::path& path);
382
383 bool RestorePath(const boost::filesystem::path& path);
384
385 std::vector<boost::filesystem::path> SetupBackupDirectories(uid_t test_uid);
386
387 void UninstallAllAppsInDirectory(boost::filesystem::path dir, bool is_preload,
388     BackendInterface* backend);
389
390 void UninstallAllSmokeApps(common_installer::RequestMode request_mode,
391     uid_t test_uid, BackendInterface* backend);
392
393 int GetAppInstalledTime(const char* appid, uid_t uid);
394
395 enum class CrashStepType {
396   PROCESS,
397   CLEAN
398 };
399
400 class StepCrash : public common_installer::Step {
401  public:
402   using Step::Step;
403
404   explicit StepCrash(common_installer::InstallerContext* context,
405       CrashStepType type)
406       : common_installer::Step::Step(context), type_(type) {}
407
408   common_installer::Step::Status process() override {
409     if (type_ == CrashStepType::PROCESS)
410       raise(SIGKILL);
411     return Status::OK;
412   }
413   common_installer::Step::Status clean() override {
414     if (type_ == CrashStepType::CLEAN)
415       raise(SIGKILL);
416     return Status::OK;
417   }
418   common_installer::Step::Status undo() override {
419     return common_installer::Step::Status::OK;
420   }
421   common_installer::Step::Status precheck() override {
422     return common_installer::Step::Status::OK;
423   }
424
425   STEP_NAME(Crash)
426
427  private:
428   CrashStepType type_;
429 };
430
431 bool CompareFileInfo(const std::string& pkgid, const TestParameters& params,
432     const bf::path& file);
433
434 }  // namespace smoke_test
435
436 #endif  // TEST_SMOKE_TESTS_COMMON_SMOKE_UTILS_H_