winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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 }