winget-cli

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

WorkFlow.cpp (8185B)


      1 // Copyright (c) Microsoft Corporation.
      2 // Licensed under the MIT License.
      3 #include "pch.h"
      4 #include "WorkflowCommon.h"
      5 #include "TestSettings.h"
      6 #include <AppInstallerDownloader.h>
      7 #include <winget/Settings.h>
      8 #include <Workflows/DownloadFlow.h>
      9 #include <Commands/InstallCommand.h>
     10 #include <Commands/SettingsCommand.h>
     11 #include <Commands/ValidateCommand.h>
     12 
     13 using namespace TestCommon;
     14 using namespace AppInstaller::CLI;
     15 using namespace AppInstaller::CLI::Execution;
     16 using namespace AppInstaller::CLI::Workflow;
     17 using namespace AppInstaller::Manifest;
     18 using namespace AppInstaller::Repository;
     19 using namespace AppInstaller::Settings;
     20 using namespace AppInstaller::Utility;
     21 
     22 void VerifyMotw(const std::filesystem::path& testFile, DWORD zone)
     23 {
     24     std::filesystem::path motwFile(testFile);
     25     motwFile += ":Zone.Identifier:$data";
     26     std::ifstream motwStream(motwFile);
     27     std::stringstream motwContent;
     28     motwContent << motwStream.rdbuf();
     29     std::string motwContentStr = motwContent.str();
     30     motwStream.close();
     31     REQUIRE(motwContentStr.find("ZoneId=" + std::to_string(zone)) != std::string::npos);
     32 }
     33 
     34 TEST_CASE("VerifyInstallerTrustLevelAndUpdateInstallerFileMotw", "[DownloadInstaller][workflow]")
     35 {
     36     TestCommon::TempFile testInstallerPath("TestInstaller.txt");
     37 
     38     std::ofstream ofile(testInstallerPath, std::ofstream::out);
     39     ofile << "test";
     40     ofile.close();
     41 
     42     ApplyMotwIfApplicable(testInstallerPath, URLZONE_INTERNET);
     43     VerifyMotw(testInstallerPath, 3);
     44 
     45     std::ostringstream updateMotwOutput;
     46     TestContext context{ updateMotwOutput, std::cin };
     47     auto previousThreadGlobals = context.SetForCurrentThread();
     48     context.Add<Data::DownloadHashInfo>({ {}, {} });
     49     context.Add<Data::InstallerPath>(testInstallerPath);
     50     auto packageVersion = std::make_shared<TestPackageVersion>(Manifest{});
     51     auto testSource = std::make_shared<TestSource>();
     52     testSource->Details.TrustLevel = SourceTrustLevel::Trusted;
     53     packageVersion->Source = testSource;
     54     context.Add<Data::PackageVersion>(packageVersion);
     55     ManifestInstaller installer;
     56     installer.Url = "http://NotTrusted.com";
     57     context.Add<Data::Installer>(std::move(installer));
     58 
     59     context << VerifyInstallerHash << UpdateInstallerFileMotwIfApplicable;
     60     REQUIRE(WI_IsFlagSet(context.GetFlags(), ContextFlag::InstallerTrusted));
     61     VerifyMotw(testInstallerPath, 2);
     62 
     63     testSource->Details.TrustLevel = SourceTrustLevel::None;
     64     context.ClearFlags(ContextFlag::InstallerTrusted);
     65     context << VerifyInstallerHash << UpdateInstallerFileMotwIfApplicable;
     66     REQUIRE_FALSE(WI_IsFlagSet(context.GetFlags(), ContextFlag::InstallerTrusted));
     67     VerifyMotw(testInstallerPath, 3);
     68 
     69     INFO(updateMotwOutput.str());
     70 }
     71 
     72 TEST_CASE("ValidateCommand_Dependencies", "[workflow][dependencies]")
     73 {
     74     std::ostringstream validateOutput;
     75     TestContext context{ validateOutput, std::cin };
     76     auto previousThreadGlobals = context.SetForCurrentThread();
     77     context.Args.AddArg(Args::Type::ValidateManifest, TestDataFile("Manifest-Good-AllDependencyTypes.yaml").GetPath().u8string());
     78 
     79     ValidateCommand validate({});
     80     validate.Execute(context);
     81     INFO(validateOutput.str());
     82 
     83     // Verify all types of dependencies are printed
     84     REQUIRE(validateOutput.str().find(Resource::LocString(Resource::String::ValidateCommandReportDependencies).get()) != std::string::npos);
     85     REQUIRE(validateOutput.str().find("WindowsFeaturesDep") != std::string::npos);
     86     REQUIRE(validateOutput.str().find("WindowsLibrariesDep") != std::string::npos);
     87     // PackageDep1 has minimum version (1.0), PackageDep2 doesn't (shouldn't show [>=...])
     88     REQUIRE(validateOutput.str().find("Package.Dep1-x64 [>= 1.0]") != std::string::npos);
     89     REQUIRE(validateOutput.str().find("Package.Dep2-x64") != std::string::npos);
     90     REQUIRE(validateOutput.str().find("Package.Dep2-x64 [") == std::string::npos);
     91     REQUIRE(validateOutput.str().find("ExternalDep") != std::string::npos);
     92 }
     93 
     94 TEST_CASE("AdminSetting_LocalManifestFiles", "[LocalManifests][workflow]")
     95 {
     96     RemoveSetting(Stream::AdminSettings);
     97 
     98     {
     99         // If there's no admin setting, using local manifest should fail.
    100         Execution::Args args;
    101         args.AddArg(Execution::Args::Type::Manifest, TestDataFile("InstallFlowTest_Exe.yaml").GetPath().u8string());
    102         InstallCommand installCommand({});
    103         REQUIRE_THROWS(installCommand.ValidateArguments(args));
    104     }
    105 
    106     {
    107         // Using settings command to enable local manifests
    108         std::ostringstream settingsOutput;
    109         TestContext context{ settingsOutput, std::cin };
    110         auto previousThreadGlobals = context.SetForCurrentThread();
    111         context.Args.AddArg(Execution::Args::Type::AdminSettingEnable, "LocalManifestFiles"sv);
    112         context.Override({ EnsureRunningAsAdmin, [](TestContext&) {} });
    113         SettingsCommand settings({});
    114         settings.Execute(context);
    115         INFO(settingsOutput.str());
    116     }
    117 
    118     {
    119         // Now using local manifests should succeed
    120         Execution::Args args2;
    121         args2.AddArg(Execution::Args::Type::Manifest, TestDataFile("InstallFlowTest_Exe.yaml").GetPath().u8string());
    122         InstallCommand installCommand2({});
    123         REQUIRE_NOTHROW(installCommand2.ValidateArguments(args2));
    124     }
    125 
    126     {
    127         // Using settings command to disable local manifests
    128         std::ostringstream settingsOutput2;
    129         TestContext context2{ settingsOutput2, std::cin };
    130         auto previousThreadGlobals = context2.SetForCurrentThread();
    131         context2.Args.AddArg(Execution::Args::Type::AdminSettingDisable, "LocalManifestFiles"sv);
    132         context2.Override({ EnsureRunningAsAdmin, [](TestContext&) {} });
    133         SettingsCommand settings2({});
    134         settings2.Execute(context2);
    135         INFO(settingsOutput2.str());
    136     }
    137 
    138     {
    139         // Now using local manifests should fail
    140         Execution::Args args3;
    141         args3.AddArg(Execution::Args::Type::Manifest, TestDataFile("InstallFlowTest_Exe.yaml").GetPath().u8string());
    142         InstallCommand installCommand3({});
    143         REQUIRE_THROWS(installCommand3.ValidateArguments(args3));
    144     }
    145 }
    146 
    147 TEST_CASE("Export_Settings", "[Settings][workflow]")
    148 {
    149     RemoveSetting(Stream::AdminSettings);
    150 
    151     {
    152         // No admin settings, local manifest should be false.
    153         std::ostringstream exportOutput;
    154         TestContext context{ exportOutput, std::cin };
    155         auto previousThreadGlobals = context.SetForCurrentThread();
    156         SettingsExportCommand settingsExportCommand({});
    157         settingsExportCommand.Execute(context);
    158 
    159         auto json = ConvertToJson(exportOutput.str());
    160         REQUIRE(!json.isNull());
    161         REQUIRE_FALSE(json["adminSettings"]["LocalManifestFiles"].asBool());
    162 
    163         auto userSettingsFileValue = std::string(json["userSettingsFile"].asCString());
    164         REQUIRE(userSettingsFileValue.find("settings.json") != std::string::npos);
    165     }
    166 
    167     {
    168         // Enable local manifest and verify export works.
    169         std::ostringstream settingsOutput;
    170         TestContext context{ settingsOutput, std::cin };
    171         auto previousThreadGlobals = context.SetForCurrentThread();
    172         context.Args.AddArg(Execution::Args::Type::AdminSettingEnable, "LocalManifestFiles"sv);
    173         context.Override({ EnsureRunningAsAdmin, [](TestContext&) {} });
    174         SettingsCommand settings({});
    175         settings.Execute(context);
    176 
    177         std::ostringstream exportOutput;
    178         TestContext context2{ exportOutput, std::cin };
    179         auto previousThreadGlobals2 = context2.SetForCurrentThread();
    180         SettingsExportCommand settingsExportCommand({});
    181         settingsExportCommand.Execute(context2);
    182         auto json = ConvertToJson(exportOutput.str());
    183         REQUIRE(!json.isNull());
    184         REQUIRE(json["adminSettings"]["LocalManifestFiles"].asBool());
    185 
    186         auto userSettingsFileValue = std::string(json["userSettingsFile"].asCString());
    187         REQUIRE(userSettingsFileValue.find("settings.json") != std::string::npos);
    188     }
    189 }