winget-cli

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

WorkflowCommon.cpp (35477B)


      1 // Copyright (c) Microsoft Corporation.
      2 // Licensed under the MIT License.
      3 #include "pch.h"
      4 #include "DependenciesTestSource.h"
      5 #include "WorkflowCommon.h"
      6 #include <winget/ManifestYamlParser.h>
      7 #include <Workflows/ArchiveFlow.h>
      8 #include <Workflows/DownloadFlow.h>
      9 #include <Workflows/InstallFlow.h>
     10 #include <Workflows/MSStoreInstallerHandler.h>
     11 #include <Workflows/DependenciesFlow.h>
     12 
     13 using namespace AppInstaller::CLI;
     14 using namespace AppInstaller::CLI::Execution;
     15 using namespace AppInstaller::CLI::Workflow;
     16 using namespace AppInstaller::Manifest;
     17 using namespace AppInstaller::Repository;
     18 using namespace AppInstaller::Utility;
     19 
     20 namespace TestCommon
     21 {
     22     namespace TSR
     23     {
     24         const TestSourceResult TestQuery_ReturnOne(
     25             "TestQueryReturnOne"sv,
     26             [](std::vector<ResultMatch>& matches, std::weak_ptr<const ISource> source) {
     27                 auto manifest = YamlParser::CreateFromPath(TestDataFile("InstallFlowTest_Exe.yaml"));
     28                 matches.emplace_back(
     29                     ResultMatch(
     30                         TestCompositePackage::Make(std::vector<Manifest>{ manifest }, source),
     31                         PackageMatchFilter(PackageMatchField::Id, MatchType::Exact, "TestQueryReturnOne")));
     32             });
     33 
     34         const TestSourceResult TestQuery_ReturnTwo(
     35             "TestQueryReturnTwo"sv,
     36             [](std::vector<ResultMatch>& matches, std::weak_ptr<const ISource> source) {
     37                 auto manifest = YamlParser::CreateFromPath(TestDataFile("InstallFlowTest_Exe.yaml"));
     38                 matches.emplace_back(
     39                     ResultMatch(
     40                         TestCompositePackage::Make(std::vector<Manifest>{ manifest }, source),
     41                         PackageMatchFilter(PackageMatchField::Id, MatchType::Exact, "TestQueryReturnTwo")));
     42 
     43                 auto manifest2 = YamlParser::CreateFromPath(TestDataFile("Manifest-Good.yaml"));
     44                 matches.emplace_back(
     45                     ResultMatch(
     46                         TestCompositePackage::Make(std::vector<Manifest>{ manifest2 }, source),
     47                         PackageMatchFilter(PackageMatchField::Id, MatchType::Exact, "TestQueryReturnTwo")));
     48             });
     49 
     50         const TestSourceResult TestInstaller_Exe(
     51             "AppInstallerCliTest.TestExeInstaller"sv,
     52             [](std::vector<ResultMatch>& matches, std::weak_ptr<const ISource> source) {
     53                 auto manifest = YamlParser::CreateFromPath(TestDataFile("InstallFlowTest_Exe.yaml"));
     54                 auto manifest2 = YamlParser::CreateFromPath(TestDataFile("UpdateFlowTest_Exe.yaml"));
     55                 auto manifest3 = YamlParser::CreateFromPath(TestDataFile("UpdateFlowTest_Exe_2.yaml"));
     56 
     57                 auto testPackage =
     58                     TestCompositePackage::Make(
     59                         manifest,
     60                         TestCompositePackage::MetadataMap
     61                         {
     62                             { PackageVersionMetadata::InstalledType, "Exe" },
     63                             { PackageVersionMetadata::StandardUninstallCommand, "C:\\uninstall.exe" },
     64                             { PackageVersionMetadata::SilentUninstallCommand, "C:\\uninstall.exe /silence" },
     65                         },
     66                         std::vector<Manifest>{ manifest3, manifest2, manifest },
     67                         source
     68                         );
     69                 for (auto& availablePackage : testPackage->Available)
     70                 {
     71                     availablePackage->IsSameOverride = [](const IPackage*, const IPackage*) { return true; };
     72                 }
     73                 matches.emplace_back(
     74                     ResultMatch(
     75                         testPackage,
     76                         PackageMatchFilter(PackageMatchField::Id, MatchType::Exact, "AppInstallerCliTest.TestExeInstaller")));
     77             });
     78 
     79         const TestSourceResult TestInstaller_Exe_UpgradeUsesAgreements(
     80             "AppInstallerCliTest.TestExeInstaller"sv,
     81             [](std::vector<ResultMatch>& matches, std::weak_ptr<const ISource> source) {
     82                 auto manifest = YamlParser::CreateFromPath(TestDataFile("InstallFlowTest_Exe.yaml"));
     83                 auto manifest2 = YamlParser::CreateFromPath(TestDataFile("UpdateFlowTest_Exe.yaml"));
     84                 auto manifest3 = YamlParser::CreateFromPath(TestDataFile("UpdateFlowTest_Exe_2_LicenseAgreement.yaml"));
     85 
     86                 auto testPackage =
     87                     TestCompositePackage::Make(
     88                         manifest,
     89                         TestCompositePackage::MetadataMap
     90                         {
     91                             { PackageVersionMetadata::InstalledType, "Exe" },
     92                             { PackageVersionMetadata::StandardUninstallCommand, "C:\\uninstall.exe" },
     93                             { PackageVersionMetadata::SilentUninstallCommand, "C:\\uninstall.exe /silence" },
     94                         },
     95                         std::vector<Manifest>{ manifest3, manifest2, manifest },
     96                         source
     97                         );
     98                 for (auto& availablePackage : testPackage->Available)
     99                 {
    100                     availablePackage->IsSameOverride = [](const IPackage*, const IPackage*) { return true; };
    101                 }
    102                 matches.emplace_back(
    103                     ResultMatch(
    104                         testPackage,
    105                         PackageMatchFilter(PackageMatchField::Id, MatchType::Exact, "AppInstallerCliTest.TestExeInstaller")));
    106             });
    107 
    108         const TestSourceResult TestInstaller_Portable(
    109             "AppInstallerCliTest.TestPortableInstaller"sv,
    110             [](std::vector<ResultMatch>& matches, std::weak_ptr<const ISource> source) {
    111                 auto manifest = YamlParser::CreateFromPath(TestDataFile("InstallFlowTest_Portable.yaml"));
    112                 auto manifest2 = YamlParser::CreateFromPath(TestDataFile("UpdateFlowTest_Portable.yaml"));
    113                 matches.emplace_back(
    114                     ResultMatch(
    115                         TestCompositePackage::Make(
    116                             manifest,
    117                             TestCompositePackage::MetadataMap{ { PackageVersionMetadata::InstalledType, "Portable" } },
    118                             std::vector<Manifest>{ manifest2, manifest },
    119                             source
    120                         ),
    121                         PackageMatchFilter(PackageMatchField::Id, MatchType::Exact, "AppInstallerCliTest.TestPortableInstaller")));
    122             });
    123 
    124         const TestSourceResult TestInstaller_Msix(
    125             "AppInstallerCliTest.TestMsixInstaller"sv,
    126             [](std::vector<ResultMatch>& matches, std::weak_ptr<const ISource> source) {
    127                 auto manifest = YamlParser::CreateFromPath(TestDataFile("InstallFlowTest_Msix_StreamingFlow.yaml"));
    128                 auto manifest2 = YamlParser::CreateFromPath(TestDataFile("UpdateFlowTest_Msix.yaml"));
    129 
    130                 matches.emplace_back(
    131                     ResultMatch(
    132                         TestCompositePackage::Make(
    133                             manifest,
    134                             TestCompositePackage::MetadataMap{ { PackageVersionMetadata::InstalledType, "Msix" } },
    135                             std::vector<Manifest>{ manifest2, manifest },
    136                             source
    137                         ),
    138                         PackageMatchFilter(PackageMatchField::Id, MatchType::Exact, "AppInstallerCliTest.TestMsixInstaller")));
    139             });
    140 
    141         const TestSourceResult TestInstaller_Msix_UpgradeUsesAgreements(
    142             "AppInstallerCliTest.TestMsixInstaller"sv,
    143             [](std::vector<ResultMatch>& matches, std::weak_ptr<const ISource> source) {
    144                 auto manifest = YamlParser::CreateFromPath(TestDataFile("InstallFlowTest_Msix_StreamingFlow.yaml"));
    145                 auto manifest2 = YamlParser::CreateFromPath(TestDataFile("UpdateFlowTest_Msix_LicenseAgreement.yaml"));
    146 
    147                 matches.emplace_back(
    148                     ResultMatch(
    149                         TestCompositePackage::Make(
    150                             manifest,
    151                             TestCompositePackage::MetadataMap{ { PackageVersionMetadata::InstalledType, "Msix" } },
    152                             std::vector<Manifest>{ manifest2, manifest },
    153                             source
    154                         ),
    155                         PackageMatchFilter(PackageMatchField::Id, MatchType::Exact, "AppInstallerCliTest.TestMsixInstaller")));
    156             });
    157 
    158         const TestSourceResult TestInstaller_Msix_UpgradeRequiresExplicit(
    159             "AppInstallerCliTest.TestMsixInstaller"sv,
    160             [](std::vector<ResultMatch>& matches, std::weak_ptr<const ISource> source) {
    161                 auto manifest = YamlParser::CreateFromPath(TestDataFile("InstallFlowTest_Msix_StreamingFlow.yaml"));
    162                 auto manifest2 = YamlParser::CreateFromPath(TestDataFile("UpdateFlowTest_Msix.yaml"));
    163 
    164                 matches.emplace_back(
    165                     ResultMatch(
    166                         TestCompositePackage::Make(
    167                             manifest,
    168                             TestCompositePackage::MetadataMap
    169                             {
    170                                 { PackageVersionMetadata::InstalledType, "Msix" },
    171                                 { PackageVersionMetadata::PinnedState, "PinnedByManifest" },
    172                             },
    173                             std::vector<Manifest>{ manifest2, manifest },
    174                             source
    175                             ),
    176                         PackageMatchFilter(PackageMatchField::Id, MatchType::Exact, "AppInstallerCliTest.TestMsixInstaller")));
    177             });
    178 
    179         const TestSourceResult TestInstaller_Zip(
    180             "AppInstallerCliTest.TestZipInstaller"sv,
    181             [](std::vector<ResultMatch>& matches, std::weak_ptr<const ISource> source) {
    182                 auto manifest = YamlParser::CreateFromPath(TestDataFile("InstallFlowTest_Zip_Exe.yaml"));
    183                 auto manifest2 = YamlParser::CreateFromPath(TestDataFile("UpdateFlowTest_Zip_Exe.yaml"));
    184                 matches.emplace_back(
    185                     ResultMatch(
    186                         TestCompositePackage::Make(
    187                             manifest,
    188                             TestCompositePackage::MetadataMap{ { PackageVersionMetadata::InstalledType, "Exe" } },
    189                             std::vector<Manifest>{ manifest2, manifest },
    190                             source
    191                         ),
    192                         PackageMatchFilter(PackageMatchField::Id, MatchType::Exact, "AppInstallerCliTest.TestZipInstaller")));
    193             });
    194 
    195         const TestSourceResult TestInstaller_MSStore(
    196             "AppInstallerCliTest.TestMSStoreInstaller"sv,
    197             [](std::vector<ResultMatch>& matches, std::weak_ptr<const ISource> source) {
    198                 auto installed = YamlParser::CreateFromPath(TestDataFile("InstallFlowTest_MSStore.yaml"));
    199                 auto available = installed;
    200                 // Override the installed version to not be Latest
    201                 installed.Version = "1.0.0.0";
    202                 matches.emplace_back(
    203                     ResultMatch(
    204                         TestCompositePackage::Make(
    205                             installed,
    206                             TestCompositePackage::MetadataMap{ { PackageVersionMetadata::InstalledType, "MSStore" } },
    207                             std::vector<Manifest>{ available },
    208                             source
    209                         ),
    210                         PackageMatchFilter(PackageMatchField::Id, MatchType::Exact, "AppInstallerCliTest.TestMSStoreInstaller")));
    211             });
    212 
    213         const TestSourceResult TestInstaller_Exe_ExpectedReturnCodes(
    214             "AppInstallerCliTest.ExpectedReturnCodes"sv,
    215             [](std::vector<ResultMatch>& matches, std::weak_ptr<const ISource> source) {
    216                 auto manifest = YamlParser::CreateFromPath(TestDataFile("InstallFlowTest_ExpectedReturnCodes.yaml"));
    217                 auto manifest2 = YamlParser::CreateFromPath(TestDataFile("UpdateFlowTest_ExpectedReturnCodes.yaml"));
    218                 matches.emplace_back(
    219                     ResultMatch(
    220                         TestCompositePackage::Make(
    221                             manifest,
    222                             TestCompositePackage::MetadataMap{ { PackageVersionMetadata::InstalledType, "Exe" } },
    223                             std::vector<Manifest>{ manifest2, manifest },
    224                             source
    225                         ),
    226                         PackageMatchFilter(PackageMatchField::Id, MatchType::Exact, "AppInstallerCliTest.ExpectedReturnCodes")));
    227             });
    228 
    229         const TestSourceResult TestInstaller_Exe_UnknownVersion(
    230             "TestExeInstallerWithUnknownVersion"sv,
    231             [](std::vector<ResultMatch>& matches, std::weak_ptr<const ISource> source) {
    232                 auto installed = YamlParser::CreateFromPath(TestDataFile("InstallFlowTest_UnknownVersion.yaml"));
    233                 auto available = installed;
    234                 // Override the installed version to be unknown.
    235                 installed.Version = "unknown";
    236                 matches.emplace_back(
    237                     ResultMatch(
    238                         TestCompositePackage::Make(
    239                             installed,
    240                             TestCompositePackage::MetadataMap{ { PackageVersionMetadata::InstalledType, "Exe" } },
    241                             std::vector<Manifest>{ available },
    242                             source
    243                         ),
    244                         PackageMatchFilter(PackageMatchField::Id, MatchType::Exact, "AppInstallerCliTest.TestExeUnknownVersion")));
    245             });
    246 
    247         const TestSourceResult TestInstaller_Exe_LatestInstalled(
    248             "TestExeInstallerWithLatestInstalled"sv,
    249             [](std::vector<ResultMatch>& matches, std::weak_ptr<const ISource> source) {
    250                 auto manifest = YamlParser::CreateFromPath(TestDataFile("InstallFlowTest_Exe.yaml"));
    251                 auto manifest2 = YamlParser::CreateFromPath(TestDataFile("UpdateFlowTest_Exe.yaml"));
    252                 matches.emplace_back(
    253                     ResultMatch(
    254                         TestCompositePackage::Make(
    255                             manifest2,
    256                             TestCompositePackage::MetadataMap{ { PackageVersionMetadata::InstalledType, "Exe" } },
    257                             std::vector<Manifest>{ manifest2, manifest },
    258                             source
    259                         ),
    260                         PackageMatchFilter(PackageMatchField::Id, MatchType::Exact, "AppInstallerCliTest.TestExeInstaller")));
    261             });
    262 
    263         const TestSourceResult TestInstaller_Exe_IncompatibleInstallerType(
    264             "TestExeInstallerWithIncompatibleInstallerType"sv,
    265             [](std::vector<ResultMatch>& matches, std::weak_ptr<const ISource> source) {
    266                 auto manifest = YamlParser::CreateFromPath(TestDataFile("InstallFlowTest_Exe.yaml"));
    267                 auto manifest2 = YamlParser::CreateFromPath(TestDataFile("UpdateFlowTest_Exe.yaml"));
    268                 matches.emplace_back(
    269                     ResultMatch(
    270                         TestCompositePackage::Make(
    271                             manifest,
    272                             TestCompositePackage::MetadataMap{ { PackageVersionMetadata::InstalledType, "Msix" } },
    273                             std::vector<Manifest>{ manifest2, manifest },
    274                             source
    275                         ),
    276                         PackageMatchFilter(PackageMatchField::Id, MatchType::Exact, "AppInstallerCliTest.TestExeInstaller")));
    277             });
    278 
    279         const TestSourceResult TestInstaller_Exe_DifferentInstallerType(
    280             "TestExeInstallerWithDifferentInstalledType"sv,
    281             [](std::vector<ResultMatch>& matches, std::weak_ptr<const ISource> source) {
    282                 auto manifest = YamlParser::CreateFromPath(TestDataFile("InstallFlowTest_Exe.yaml"));
    283                 auto manifest2 = YamlParser::CreateFromPath(TestDataFile("UpdateFlowTest_Exe_ARPInstallerType.yaml"));
    284                 matches.emplace_back(
    285                     ResultMatch(
    286                         TestCompositePackage::Make(
    287                             manifest,
    288                             TestCompositePackage::MetadataMap{ { PackageVersionMetadata::InstalledType, "Msix" } },
    289                             std::vector<Manifest>{ manifest2, manifest },
    290                             source
    291                         ),
    292                         PackageMatchFilter(PackageMatchField::Id, MatchType::Exact, "AppInstallerCliTest.TestExeInstaller")));
    293             });
    294 
    295         const TestSourceResult TestInstaller_Exe_UnsupportedArguments(
    296             "TestExeInstallerWithUnsupportedArguments"sv,
    297             [](std::vector<ResultMatch>& matches, std::weak_ptr<const ISource> source) {
    298                 auto manifest = YamlParser::CreateFromPath(TestDataFile("InstallFlowTest_Exe.yaml"));
    299                 auto manifest2 = YamlParser::CreateFromPath(TestDataFile("UpdateFlowTest_Exe_UnsupportedArgs.yaml"));
    300                 matches.emplace_back(
    301                     ResultMatch(
    302                         TestCompositePackage::Make(
    303                             manifest,
    304                             TestCompositePackage::MetadataMap{ { PackageVersionMetadata::InstalledType, "Exe" } },
    305                             std::vector<Manifest>{ manifest2, manifest },
    306                             source
    307                         ),
    308                         PackageMatchFilter(PackageMatchField::Id, MatchType::Exact, "AppInstallerCliTest.TestExeInstaller")));
    309             });
    310 
    311         const TestSourceResult TestInstaller_Exe_NothingInstalled(
    312             "TestExeInstallerWithNothingInstalled"sv,
    313             [](std::vector<ResultMatch>& matches, std::weak_ptr<const ISource> source) {
    314                 auto manifest = YamlParser::CreateFromPath(TestDataFile("InstallFlowTest_Exe.yaml"));
    315                 matches.emplace_back(
    316                     ResultMatch(
    317                         TestCompositePackage::Make(
    318                             std::vector<Manifest>{ manifest },
    319                             source
    320                         ),
    321                         PackageMatchFilter(PackageMatchField::Id, MatchType::Exact, "AppInstallerCliTest.TestExeInstaller")));
    322             });
    323 
    324         const TestSourceResult TestInstaller_Exe_Dependencies(
    325             "AppInstallerCliTest.TestExeInstaller.Dependencies"sv,
    326             [](std::vector<ResultMatch>& matches, std::weak_ptr<const ISource> source) {
    327                 auto manifest = YamlParser::CreateFromPath(TestDataFile("Installer_Exe_Dependencies.yaml"));
    328                 auto manifest2 = YamlParser::CreateFromPath(TestDataFile("UpdateFlowTest_ExeDependencies.yaml"));
    329                 matches.emplace_back(
    330                     ResultMatch(
    331                         TestCompositePackage::Make(
    332                             manifest,
    333                             TestCompositePackage::MetadataMap
    334                             {
    335                                 { PackageVersionMetadata::InstalledType, "Exe" },
    336                                 { PackageVersionMetadata::StandardUninstallCommand, "C:\\uninstall.exe" },
    337                                 { PackageVersionMetadata::SilentUninstallCommand, "C:\\uninstall.exe /silence" },
    338                             },
    339                             std::vector<Manifest>{ manifest2, manifest },
    340                             source
    341                             ),
    342                         PackageMatchFilter(PackageMatchField::Id, MatchType::Exact, "AppInstallerCliTest.TestExeInstaller.Dependencies")));
    343             });
    344 
    345         const TestSourceResult TestInstaller_Msix_WFDependency(
    346             "AppInstallerCliTest.TestMsixInstaller.WFDep"sv,
    347             [](std::vector<ResultMatch>& matches, std::weak_ptr<const ISource> source) {
    348                 auto manifest = YamlParser::CreateFromPath(TestDataFile("Installer_Msix_WFDependency.yaml"));
    349                 matches.emplace_back(
    350                     ResultMatch(
    351                         TestCompositePackage::Make(
    352                             std::vector<Manifest>{ manifest },
    353                             source
    354                         ),
    355                         PackageMatchFilter(PackageMatchField::Id, MatchType::Exact, "AppInstallerCliTest.TestMsixInstaller.WFDep")));
    356             });
    357 
    358         const TestSourceResult TestInstaller_Exe_LicenseAgreement(
    359             "TestInstallerWithLicenseAgreement"sv,
    360             [](std::vector<ResultMatch>& matches, std::weak_ptr<const ISource> source) {
    361                 auto manifest = YamlParser::CreateFromPath(TestDataFile("InstallFlowTest_LicenseAgreement.yaml"));
    362                 auto manifest2 = YamlParser::CreateFromPath(TestDataFile("UpdateFlowTest_Exe_2_LicenseAgreement.yaml"));
    363                 matches.emplace_back(
    364                     ResultMatch(
    365                         TestCompositePackage::Make(
    366                             manifest,
    367                             TestCompositePackage::MetadataMap{ { PackageVersionMetadata::InstalledType, "Exe" } },
    368                             std::vector<Manifest>{ manifest2, manifest },
    369                             source
    370                         ),
    371                         PackageMatchFilter(PackageMatchField::Id, MatchType::Exact, "TestInstallerWithLicenseAgreement")));
    372             });
    373 
    374         const TestSourceResult TestInstaller_Exe_UpgradeAllWithDuplicateUpgradeItems(
    375             "TestUpgradeAllWithDuplicateUpgradeItems"sv,
    376             [](std::vector<ResultMatch>& matches, std::weak_ptr<const ISource> source) {
    377                 auto manifest = YamlParser::CreateFromPath(TestDataFile("InstallFlowTest_Exe.yaml"));
    378                 auto manifest2 = YamlParser::CreateFromPath(TestDataFile("UpdateFlowTest_Exe.yaml"));
    379                 auto manifest3 = YamlParser::CreateFromPath(TestDataFile("UpdateFlowTest_Exe_2.yaml"));
    380                 matches.emplace_back(
    381                     ResultMatch(
    382                         TestCompositePackage::Make(
    383                             manifest,
    384                             TestCompositePackage::MetadataMap
    385                             {
    386                                 { PackageVersionMetadata::InstalledType, "Exe" },
    387                                 { PackageVersionMetadata::StandardUninstallCommand, "C:\\uninstall.exe" },
    388                                 { PackageVersionMetadata::SilentUninstallCommand, "C:\\uninstall.exe /silence" },
    389                             },
    390                             std::vector<Manifest>{ manifest3, manifest2, manifest },
    391                             source
    392                             ),
    393                         PackageMatchFilter(PackageMatchField::Id, MatchType::Exact, "AppInstallerCliTest.TestExeInstaller")));
    394                 matches.emplace_back(
    395                     ResultMatch(
    396                         TestCompositePackage::Make(
    397                             manifest2,
    398                             TestCompositePackage::MetadataMap
    399                             {
    400                                 { PackageVersionMetadata::InstalledType, "Exe" },
    401                                 { PackageVersionMetadata::StandardUninstallCommand, "C:\\uninstall.exe" },
    402                                 { PackageVersionMetadata::SilentUninstallCommand, "C:\\uninstall.exe /silence" },
    403                             },
    404                             std::vector<Manifest>{ manifest3, manifest2, manifest },
    405                             source
    406                             ),
    407                         PackageMatchFilter(PackageMatchField::Id, MatchType::Exact, "AppInstallerCliTest.TestExeInstaller")));
    408             });
    409     }
    410 
    411     SearchResult WorkflowTestSource::Search(const SearchRequest& request) const
    412     {
    413         std::string input;
    414         if (request.Query)
    415         {
    416             input = request.Query->Value;
    417         }
    418         else if (!request.Inclusions.empty())
    419         {
    420             input = request.Inclusions[0].Value;
    421         }
    422         else if (!request.Filters.empty())
    423         {
    424             input = request.Filters[0].Value;
    425         }
    426 
    427         SearchResult result;
    428         for (const auto& testSourceResult : m_testSourceResults)
    429         {
    430             if (input.empty() || CaseInsensitiveEquals(input, testSourceResult.Query))
    431             {
    432                 testSourceResult.AddResults(result.Matches, shared_from_this());
    433             }
    434         }
    435 
    436         return result;
    437     }
    438 
    439     void WorkflowTestSource::AddResult(const TestSourceResult& testSourceResult)
    440     {
    441         m_testSourceResults.push_back(testSourceResult);
    442     }
    443 
    444     std::shared_ptr<WorkflowTestSource> CreateTestSource(std::vector<TestSourceResult>&& testSourceResults)
    445     {
    446         return std::make_shared<WorkflowTestSource>(std::move(testSourceResults));
    447     }
    448 
    449     TestContext::TestContext(std::ostream& out, std::istream& in) : TestContext(out, in, false, std::make_shared<std::vector<WorkflowTaskOverride>>())
    450     {
    451         WorkflowTaskOverride wto
    452         { RemoveInstaller, [](TestContext&)
    453             {
    454                 // Do nothing; we never want to remove the test files.
    455         } };
    456 
    457         // Mark this one as used so that it doesn't anger the destructor.
    458         wto.UseCount++;
    459 
    460         Override(wto);
    461     }
    462 
    463     TestContext::TestContext(std::ostream& out, std::istream& in, bool isClone, std::shared_ptr<std::vector<WorkflowTaskOverride>> overrides) :
    464         m_out(out), m_in(in), m_overrides(overrides), m_isClone(isClone), Context(out, in)
    465     {
    466         m_shouldExecuteWorkflowTask = [this](const Workflow::WorkflowTask& task)
    467         {
    468             auto itr = std::find_if(m_overrides->begin(), m_overrides->end(), [&](const WorkflowTaskOverride& wto) { return wto.Target == task; });
    469 
    470             if (itr == m_overrides->end())
    471             {
    472                 return true;
    473             }
    474             else
    475             {
    476                 itr->UseCount++;
    477                 itr->Override(*this);
    478                 return false;
    479             }
    480         };
    481     }
    482 
    483     TestContext::~TestContext()
    484     {
    485         if (!m_isClone)
    486         {
    487             for (const auto& wto : *m_overrides)
    488             {
    489                 if (wto.UseCount == 0)
    490                 {
    491                     FAIL_CHECK("Unused override " + wto.Target.GetName());
    492                 }
    493                 else if (wto.ExpectedUseCount != -1 && wto.ExpectedUseCount != wto.UseCount)
    494                 {
    495                     FAIL_CHECK("Used override count does not match expected " + wto.Target.GetName());
    496                 }
    497             }
    498         }
    499     }
    500 
    501     void TestContext::Override(const WorkflowTaskOverride& wto)
    502     {
    503         m_overrides->emplace_back(wto);
    504     }
    505 
    506     std::unique_ptr<Context> TestContext::CreateSubContext()
    507     {
    508         auto clone = std::make_unique<TestContext>(m_out, m_in, true, m_overrides);
    509         clone->SetFlags(this->GetFlags());
    510         CopyArgsToSubContext(clone.get());
    511         return clone;
    512     }
    513 
    514     void OverrideForOpenSource(TestContext& context, std::shared_ptr<WorkflowTestSource> testSource, bool overrideOpenCompositeSource)
    515     {
    516         context.Override({ "OpenSource", [=](TestContext& context)
    517         {
    518             context.Add<Execution::Data::Source>(Source{ testSource });
    519         } });
    520 
    521         if (overrideOpenCompositeSource)
    522         {
    523             context.Override({ "OpenCompositeSource", [](TestContext&)
    524             {
    525             } });
    526         }
    527     }
    528 
    529     void OverrideForCompositeInstalledSource(TestContext& context, std::shared_ptr<WorkflowTestSource> testSource)
    530     {
    531         context.Override({ "OpenSource", [](TestContext&)
    532         {
    533         } });
    534 
    535         context.Override({ "OpenCompositeSource", [=](TestContext& context)
    536         {
    537             context.Add<Execution::Data::Source>(Source{ testSource });
    538         } });
    539     }
    540 
    541     void OverrideForUpdateInstallerMotw(TestContext& context)
    542     {
    543         context.Override({ UpdateInstallerFileMotwIfApplicable, [](TestContext&)
    544         {
    545         } });
    546     }
    547 
    548     void OverrideForCheckExistingInstaller(TestContext& context)
    549     {
    550         context.Override({ CheckForExistingInstaller, [](TestContext&)
    551         {
    552         } });
    553     }
    554 
    555     void OverrideForShellExecute(TestContext& context, int expectedUseCount)
    556     {
    557         OverrideForCheckExistingInstaller(context);
    558 
    559         context.Override({ DownloadInstallerFile, [](TestContext& context)
    560         {
    561             context.Add<Data::DownloadHashInfo>({ {}, {} });
    562             context.Add<Data::InstallerPath>(TestDataFile("AppInstallerTestExeInstaller.exe"));
    563         }, expectedUseCount });
    564 
    565         context.Override({ RenameDownloadedInstaller, [](TestContext&)
    566         {
    567         }, expectedUseCount });
    568 
    569         OverrideForUpdateInstallerMotw(context);
    570     }
    571 
    572     void OverrideForShellExecute(TestContext& context, std::vector<Dependency>& installationLog)
    573     {
    574         context.Override({ DownloadInstallerFile, [&installationLog](TestContext& context)
    575         {
    576             context.Add<Data::DownloadHashInfo>({ {}, {} });
    577             context.Add<Data::InstallerPath>(TestDataFile("AppInstallerTestExeInstaller.exe"));
    578 
    579             auto dependency = Dependency(DependencyType::Package, context.Get<Execution::Data::Manifest>().Id, context.Get<Execution::Data::Manifest>().Version);
    580             installationLog.push_back(dependency);
    581         } });
    582 
    583         context.Override({ RenameDownloadedInstaller, [](TestContext&)
    584         {
    585         } });
    586 
    587         OverrideForUpdateInstallerMotw(context);
    588     }
    589 
    590     void OverrideForPortableInstall(TestContext& context)
    591     {
    592         context.Override({ Workflow::details::PortableInstall, [](TestContext&)
    593         {
    594             std::filesystem::path temp = std::filesystem::temp_directory_path();
    595             temp /= "TestPortableInstalled.txt";
    596             std::ofstream file(temp, std::ofstream::out);
    597             file.close();
    598         } });
    599     }
    600 
    601     void OverrideForPortableInstallFlow(TestContext& context)
    602     {
    603         context.Override({ DownloadInstallerFile, [](TestContext& context)
    604         {
    605             context.Add<Data::DownloadHashInfo>({ {}, {} });
    606             context.Add<Data::InstallerPath>(TestDataFile("AppInstallerTestExeInstaller.exe"));
    607         } });
    608 
    609         context.Override({ RenameDownloadedInstaller, [](TestContext&)
    610         {
    611         } });
    612 
    613         OverrideForUpdateInstallerMotw(context);
    614         OverrideForPortableInstall(context);
    615     }
    616 
    617     void OverridePortableInstaller(TestContext& context)
    618     {
    619         context.Override({ DownloadInstallerFile, [](TestContext& context)
    620         {
    621             std::filesystem::path tempDirectory = std::filesystem::temp_directory_path();
    622             const auto& installerPath = TestDataFile("AppInstallerTestExeInstaller.exe").GetPath();
    623             const auto& tempInstallerPath = tempDirectory / "AppInstallerTestExeInstaller.exe";
    624             std::filesystem::copy(installerPath, tempInstallerPath, std::filesystem::copy_options::overwrite_existing);
    625             context.Add<Data::InstallerPath>(tempInstallerPath);
    626 
    627             std::ifstream inStream{ tempInstallerPath, std::ifstream::binary };
    628             SHA256::HashBuffer fileHash = SHA256::ComputeHash(inStream);
    629             context.Add<Data::DownloadHashInfo>({ fileHash, DownloadResult{ fileHash } });
    630         } });
    631 
    632         context.Override({ RenameDownloadedInstaller, [](TestContext&)
    633         {
    634         } });
    635 
    636         OverrideForUpdateInstallerMotw(context);
    637     }
    638 
    639     void OverrideForExtractInstallerFromArchive(TestContext& context)
    640     {
    641         context.Override({ ExtractFilesFromArchive, [](TestContext&)
    642         {
    643         } });
    644     }
    645 
    646     void OverrideForVerifyAndSetNestedInstaller(TestContext& context)
    647     {
    648         context.Override({ VerifyAndSetNestedInstaller, [](TestContext&)
    649         {
    650         } });
    651     }
    652 
    653     void OverrideForMSIX(TestContext& context)
    654     {
    655         context.Override({ Workflow::details::MsixInstall, [](TestContext& context)
    656         {
    657             std::filesystem::path temp = std::filesystem::temp_directory_path();
    658             temp /= "TestMsixInstalled.txt";
    659             std::ofstream file(temp, std::ofstream::out);
    660 
    661             if (context.Contains(Execution::Data::InstallerPath))
    662             {
    663                 file << context.Get<Execution::Data::InstallerPath>().u8string();
    664             }
    665             else
    666             {
    667                 file << context.Get<Execution::Data::Installer>()->Url;
    668             }
    669 
    670             file.close();
    671         } });
    672     }
    673 
    674     void OverrideForMSStore(TestContext& context, bool isUpdate)
    675     {
    676         if (isUpdate)
    677         {
    678             context.Override({ MSStoreUpdate, [](TestContext& context)
    679             {
    680                 std::filesystem::path temp = std::filesystem::temp_directory_path();
    681                 temp /= "TestMSStoreUpdated.txt";
    682                 std::ofstream file(temp, std::ofstream::out);
    683                 file << context.Get<Execution::Data::Installer>()->ProductId;
    684                 file.close();
    685             } });
    686         }
    687         else
    688         {
    689             context.Override({ MSStoreInstall, [](TestContext& context)
    690             {
    691                 std::filesystem::path temp = std::filesystem::temp_directory_path();
    692                 temp /= "TestMSStoreInstalled.txt";
    693                 std::ofstream file(temp, std::ofstream::out);
    694                 file << context.Get<Execution::Data::Installer>()->ProductId;
    695                 file.close();
    696             } });
    697         }
    698 
    699         context.Override({ Workflow::EnsureStorePolicySatisfied, [](TestContext&)
    700         {
    701         } });
    702     }
    703 
    704     void OverrideOpenDependencySource(TestContext& context)
    705     {
    706         context.Override({ Workflow::OpenDependencySource, [](TestContext& context)
    707         {
    708             context.Add<Execution::Data::DependencySource>(Source{ std::make_shared<DependenciesTestSource>() });
    709         } });
    710     }
    711 
    712     void OverrideEnableWindowsFeaturesDependencies(TestContext& context)
    713     {
    714         context.Override({ Workflow::EnableWindowsFeaturesDependencies, [](TestContext&)
    715         {
    716         } });
    717     }
    718 
    719     void OverrideRegisterStartupAfterReboot(TestContext& context)
    720     {
    721         context.Override({ "RegisterStartupAfterReboot", [](TestContext&)
    722         {
    723         } });
    724     }
    725 
    726     void OverrideDownloadInstallerFileForMSStoreDownload(TestContext& context)
    727     {
    728         context.Override({ DownloadInstallerFile, [](TestContext& context)
    729         {
    730             const auto& installer = context.Get<Data::Installer>().value();
    731             const auto& installerPath = context.Get<Data::InstallerPath>();
    732             std::ofstream file(installerPath, std::ofstream::out | std::ofstream::trunc);
    733             file << installer.Url;
    734             file.close();
    735             context.Add<Data::DownloadHashInfo>({ {}, {} });
    736         } });
    737     }
    738 }