TestCommon.h (6290B)
1 // Copyright (c) Microsoft Corporation. 2 // Licensed under the MIT License. 3 #pragma once 4 #include <AppInstallerLanguageUtilities.h> 5 #include <AppInstallerLogging.h> 6 #include <AppInstallerProgress.h> 7 #include <AppxPackaging.h> 8 #include <winget/UserSettings.h> 9 #include <winget/ExperimentalFeature.h> 10 #include <wil/result.h> 11 12 #include <filesystem> 13 #include <functional> 14 #include <memory> 15 #include <string> 16 17 #define REQUIRE_THROWS_HR(_expr_, _hr_) REQUIRE_THROWS_MATCHES(_expr_, wil::ResultException, ::TestCommon::ResultExceptionHRMatcher(_hr_)) 18 19 namespace TestCommon 20 { 21 enum class TempFileDestructionBehavior 22 { 23 Delete, 24 Keep, 25 ShellExecuteOnFailure, 26 }; 27 28 struct KeepTempFile {}; 29 30 // Use this to create a temporary file for testing. 31 struct TempFile 32 { 33 TempFile(const std::string& baseName, const std::string& baseExt, std::optional<KeepTempFile> keepTempFile = {}); 34 TempFile(const std::filesystem::path& parent, const std::string& baseName, const std::string& baseExt, std::optional<KeepTempFile> keepTempFile = {}); 35 TempFile(const std::filesystem::path& filePath, std::optional<KeepTempFile> keepTempFile = {}); 36 37 TempFile(const TempFile&) = delete; 38 TempFile& operator=(const TempFile&) = delete; 39 40 TempFile(TempFile&&) = default; 41 TempFile& operator=(TempFile&&) = default; 42 43 ~TempFile(); 44 45 const std::filesystem::path& GetPath() const { return _filepath; } 46 operator const std::filesystem::path& () const { return _filepath; } 47 operator const std::string() const { return _filepath.u8string(); } 48 49 void Rename(const std::filesystem::path& newFilePath); 50 51 void Release(); 52 53 static void SetDestructorBehavior(TempFileDestructionBehavior behavior); 54 55 static void SetTestFailed(bool failed); 56 57 protected: 58 TempFile() = default; 59 std::filesystem::path _filepath; 60 AppInstaller::DestructionToken m_destructionToken{ true }; 61 }; 62 63 // Use to create a temporary directory for testing. 64 struct TempDirectory : public TempFile 65 { 66 TempDirectory(const std::string& baseName, bool create = true); 67 }; 68 69 // Use this to find a test data file when testing. 70 struct TestDataFile 71 { 72 TestDataFile(const std::filesystem::path& path) : m_path(path) {} 73 74 std::filesystem::path GetPath() const; 75 operator std::filesystem::path () const { return GetPath(); } 76 77 static void SetTestDataBasePath(const std::filesystem::path& path); 78 79 private: 80 std::filesystem::path m_path; 81 }; 82 83 // Matcher that lets us verify wil::ResultExceptions have a specific HR. 84 struct ResultExceptionHRMatcher : public Catch::Matchers::MatcherBase<wil::ResultException> 85 { 86 ResultExceptionHRMatcher(HRESULT hr) : m_expectedHR(hr) {} 87 88 bool match(const wil::ResultException& re) const override 89 { 90 return re.GetErrorCode() == m_expectedHR; 91 } 92 93 std::string describe() const override 94 { 95 std::ostringstream result; 96 result << "has HR == 0x" << AppInstaller::Logging::SetHRFormat << m_expectedHR; 97 return result.str(); 98 } 99 100 private: 101 HRESULT m_expectedHR = S_OK; 102 }; 103 104 // An IProgressCallback that is easily hooked. 105 struct TestProgress : public AppInstaller::IProgressCallback 106 { 107 // Inherited via IProgressCallback 108 void BeginProgress() override; 109 110 void OnProgress(uint64_t current, uint64_t maximum, AppInstaller::ProgressType type) override; 111 112 void SetProgressMessage(std::string_view message) override; 113 114 void EndProgress(bool) override; 115 116 bool IsCancelledBy(AppInstaller::CancelReason) override; 117 118 CancelFunctionRemoval SetCancellationFunction(std::function<void()>&& f) override; 119 120 std::function<void(uint64_t, uint64_t, AppInstaller::ProgressType)> m_OnProgress; 121 }; 122 123 // Creates a volatile key for testing. 124 wil::unique_hkey RegCreateVolatileTestRoot(); 125 126 // Creates a volatile subkey for testing. 127 wil::unique_hkey RegCreateVolatileSubKey(HKEY parent, const std::wstring& name); 128 129 // Set registry values. 130 void SetRegistryValue(HKEY key, const std::wstring& name, const std::wstring& value, DWORD type = REG_SZ); 131 void SetRegistryValue(HKEY key, const std::wstring& name, const std::vector<BYTE>& value, DWORD type = REG_BINARY); 132 void SetRegistryValue(HKEY key, const std::wstring& name, DWORD value); 133 134 // Enable or disable developer mode. 135 void EnableDevMode(bool enable); 136 137 // Override UserSettings using this class. 138 // Automatically overrides the user settings for the lifetime of this object. 139 // DOES NOT SUPPORT NESTED USE 140 struct TestUserSettings : public AppInstaller::Settings::UserSettings 141 { 142 TestUserSettings(bool keepFileSettings = false); 143 ~TestUserSettings(); 144 145 template <AppInstaller::Settings::Setting S> 146 void Set(typename AppInstaller::Settings::details::SettingMapping<S>::value_t&& value) 147 { 148 m_settings[S].emplace<AppInstaller::Settings::details::SettingIndex(S)>(std::move(value)); 149 } 150 151 static std::unique_ptr<TestUserSettings> EnableExperimentalFeature(AppInstaller::Settings::ExperimentalFeature::Feature feature, bool keepFileSettings = false); 152 }; 153 154 // Below cert installation/uninstallation methods require admin privilege, 155 // tests calling these functions should skip when not running with admin. 156 bool InstallCertFromSignedPackage(const std::filesystem::path& package); 157 bool UninstallCertFromSignedPackage(const std::filesystem::path& package); 158 159 // Get manifest reader from a msix file path 160 bool GetMsixPackageManifestReader(std::string_view testFileName, IAppxManifestReader** manifestReader); 161 162 // Removes console format 163 std::string RemoveConsoleFormat(const std::string& str); 164 165 // Convert to Json::Value 166 Json::Value ConvertToJson(const std::string& content); 167 168 // Sets up the test path overrides. 169 void SetTestPathOverrides(); 170 }