winget-cli

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

ConfigurableTestSourceFactory.cpp (5791B)


      1 // Copyright (c) Microsoft Corporation.
      2 // Licensed under the MIT License.
      3 #include "pch.h"
      4 #include "Microsoft/ConfigurableTestSourceFactory.h"
      5 
      6 #include <json/json.h>
      7 
      8 using namespace std::string_literals;
      9 using namespace std::string_view_literals;
     10 
     11 namespace AppInstaller::Repository::Microsoft
     12 {
     13     namespace
     14     {
     15         // The configuration defined for a source.
     16         // This can be added to as new scenarios are needed for testing.
     17         struct TestSourceConfiguration
     18         {
     19             TestSourceConfiguration(const std::string& config)
     20             {
     21                 Json::Value root;
     22                 Json::CharReaderBuilder builder;
     23                 const std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
     24 
     25                 std::string error;
     26 
     27                 if (reader->parse(config.c_str(), config.c_str() + config.size(), &root, &error))
     28                 {
     29                     // TODO: If this becomes more dynamic, refactor the UserSettings code to make it easier to leverage here
     30                     ParseHR(root, ".OpenHR", OpenHR);
     31                     ParseHR(root, ".SearchHR", SearchHR);
     32                 }
     33                 else
     34                 {
     35                     AICLI_LOG(Repo, Error, << "Error parsing test source config: " << error);
     36                     THROW_HR_MSG(E_INVALIDARG, "%hs", error.c_str());
     37                 }
     38             }
     39 
     40             // The HR to throw on Factory::Create (if FAILED)
     41             HRESULT OpenHR = S_OK;
     42 
     43             // The HR to throw on Source::Search (if FAILED)
     44             HRESULT SearchHR = S_OK;
     45 
     46         private:
     47             static void ParseHR(const Json::Value& root, const std::string& path, HRESULT& hr)
     48             {
     49                 const Json::Path jsonPath(path);
     50                 Json::Value node = jsonPath.resolve(root);
     51                 if (!node.isNull())
     52                 {
     53                     if (node.isIntegral())
     54                     {
     55                         hr = node.asInt();
     56                     }
     57                     else if (node.isString())
     58                     {
     59                         hr = static_cast<HRESULT>(std::strtoll(node.asString().c_str(), nullptr, 0));
     60                     }
     61                 }
     62             }
     63         };
     64 
     65         // The configurable source itself.
     66         struct ConfigurableTestSource : public ISource
     67         {
     68             static constexpr ISourceType SourceType = ISourceType::ConfigurableTestSource;
     69 
     70             ConfigurableTestSource(const SourceDetails& details, const TestSourceConfiguration& config) :
     71                 m_details(details), m_config(config) {}
     72 
     73             const SourceDetails& GetDetails() const override { return m_details; }
     74 
     75             const std::string& GetIdentifier() const override { return m_details.Identifier; }
     76 
     77             SearchResult Search(const SearchRequest&) const override
     78             {
     79                 THROW_IF_FAILED(m_config.SearchHR);
     80                 return {};
     81             }
     82 
     83             void* CastTo(ISourceType type) override
     84             {
     85                 if (type == SourceType)
     86                 {
     87                     return this;
     88                 }
     89 
     90                 return nullptr;
     91             }
     92 
     93         private:
     94             SourceDetails m_details;
     95             TestSourceConfiguration m_config;
     96         };
     97 
     98         struct ConfigurableTestSourceReference : public ISourceReference
     99         {
    100             ConfigurableTestSourceReference(const SourceDetails& details) : m_details(details)
    101             {
    102                 m_details.Identifier = "*ConfigurableTestSource";
    103             }
    104 
    105             std::string GetIdentifier() override { return m_details.Identifier; }
    106 
    107             SourceDetails& GetDetails() override { return m_details; };
    108 
    109             bool SetCustomHeader(std::optional<std::string>) override { return true; }
    110 
    111             std::shared_ptr<ISource> Open(IProgressCallback&) override
    112             {
    113                 // enables `source add` with FAILED(OpenHR)
    114                 TestSourceConfiguration config{ m_details.Arg };
    115                 THROW_IF_FAILED(config.OpenHR);
    116                 return std::make_shared<ConfigurableTestSource>(m_details, config);
    117             }
    118 
    119         private:
    120             SourceDetails m_details;
    121         };
    122 
    123         // The actual factory implementation.
    124         struct ConfigurableTestSourceFactoryImpl : public ISourceFactory
    125         {
    126             std::string_view TypeName() const override final
    127             {
    128                 return ConfigurableTestSourceFactory::Type();
    129             }
    130 
    131             std::shared_ptr<ISourceReference> Create(const SourceDetails& details) override final
    132             {
    133                 return std::make_shared<ConfigurableTestSourceReference>(details);
    134             }
    135 
    136             bool Add(SourceDetails& details, IProgressCallback&) override final
    137             {
    138                 // Attempt to parse the configuration so that we can fail at the appropriate point
    139                 TestSourceConfiguration config{ details.Arg };
    140                 return true;
    141             }
    142 
    143             bool Update(const SourceDetails&, IProgressCallback&) override final
    144             {
    145                 return true;
    146             }
    147 
    148             bool BackgroundUpdate(const SourceDetails&, IProgressCallback&) override final
    149             {
    150                 return true;
    151             }
    152 
    153             bool Remove(const SourceDetails&, IProgressCallback&) override final
    154             {
    155                 return true;
    156             }
    157         };
    158     }
    159 
    160     std::unique_ptr<ISourceFactory> ConfigurableTestSourceFactory::Create()
    161     {
    162         return std::make_unique<ConfigurableTestSourceFactoryImpl>();
    163     }
    164 }