winget-cli

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

UninstallFlow.cpp (9049B)


      1 // Copyright (c) Microsoft Corporation.
      2 // Licensed under the MIT License.
      3 #include "pch.h"
      4 #include "WorkflowCommon.h"
      5 #include <Commands/UninstallCommand.h>
      6 #include <Workflows/PortableFlow.h>
      7 #include <Workflows/ShellExecuteInstallerHandler.h>
      8 #include <Workflows/UninstallFlow.h>
      9 
     10 using namespace TestCommon;
     11 using namespace AppInstaller::CLI;
     12 using namespace AppInstaller::CLI::Workflow;
     13 
     14 void OverrideForPortableUninstall(TestContext& context)
     15 {
     16     context.Override({ GetUninstallInfo, [](TestContext&)
     17     {
     18     } });
     19 
     20     context.Override({ PortableUninstallImpl, [](TestContext& context)
     21     {
     22         std::filesystem::path temp = std::filesystem::temp_directory_path();
     23         temp /= "TestPortableUninstalled.txt";
     24         std::ofstream file(temp, std::ofstream::out);
     25         file.close();
     26 
     27         context.Add<Execution::Data::OperationReturnCode>(0);
     28     } });
     29 }
     30 
     31 void OverrideForExeUninstall(TestContext& context)
     32 {
     33     context.Override({ ShellExecuteUninstallImpl, [](TestContext& context)
     34     {
     35             // Write out the uninstall command
     36             std::filesystem::path temp = std::filesystem::temp_directory_path();
     37             temp /= "TestExeUninstalled.txt";
     38             std::ofstream file(temp, std::ofstream::out);
     39             file << context.Get<Execution::Data::UninstallString>();
     40             file.close();
     41 
     42             context.Add<Execution::Data::OperationReturnCode>(0);
     43         } });
     44 }
     45 
     46 void OverrideForMSIXUninstall(TestContext& context)
     47 {
     48     context.Override({ MsixUninstall, [](TestContext& context)
     49     {
     50             // Write out the package full name
     51             std::filesystem::path temp = std::filesystem::temp_directory_path();
     52             temp /= "TestMsixUninstalled.txt";
     53             std::ofstream file(temp, std::ofstream::out);
     54             for (const auto& packageFamilyName : context.Get<Execution::Data::PackageFamilyNames>())
     55             {
     56                 file << packageFamilyName << std::endl;
     57             }
     58 
     59             file.close();
     60         } });
     61 }
     62 
     63 TEST_CASE("UninstallFlow_UninstallPortable", "[UninstallFlow][workflow]")
     64 {
     65     TestCommon::TempFile uninstallResultPath("TestPortableUninstalled.txt");
     66 
     67     std::ostringstream uninstallOutput;
     68     TestContext context{ uninstallOutput, std::cin };
     69     auto previousThreadGlobals = context.SetForCurrentThread();
     70     OverrideForCompositeInstalledSource(context, CreateTestSource({ TSR::TestInstaller_Portable }));
     71     OverrideForPortableUninstall(context);
     72     context.Args.AddArg(Execution::Args::Type::Query, TSR::TestInstaller_Portable.Query);
     73 
     74     UninstallCommand uninstall({});
     75     uninstall.Execute(context);
     76     INFO(uninstallOutput.str());
     77     REQUIRE(std::filesystem::exists(uninstallResultPath.GetPath()));
     78 }
     79 
     80 TEST_CASE("UninstallFlow_UninstallExe", "[UninstallFlow][workflow]")
     81 {
     82     TestCommon::TempFile uninstallResultPath("TestExeUninstalled.txt");
     83 
     84     std::ostringstream uninstallOutput;
     85     TestContext context{ uninstallOutput, std::cin };
     86     auto previousThreadGlobals = context.SetForCurrentThread();
     87     OverrideForCompositeInstalledSource(context, CreateTestSource({ TSR::TestInstaller_Exe }));
     88     OverrideForExeUninstall(context);
     89     context.Args.AddArg(Execution::Args::Type::Query, TSR::TestInstaller_Exe.Query);
     90     context.Args.AddArg(Execution::Args::Type::Silent);
     91 
     92     UninstallCommand uninstall({});
     93     uninstall.Execute(context);
     94     INFO(uninstallOutput.str());
     95 
     96     // Verify Uninstaller is called and parameters are passed in.
     97     REQUIRE(std::filesystem::exists(uninstallResultPath.GetPath()));
     98     std::ifstream uninstallResultFile(uninstallResultPath.GetPath());
     99     REQUIRE(uninstallResultFile.is_open());
    100     std::string uninstallResultStr;
    101     std::getline(uninstallResultFile, uninstallResultStr);
    102     REQUIRE(uninstallResultStr.find("uninstall.exe") != std::string::npos);
    103     REQUIRE(uninstallResultStr.find("/silence") != std::string::npos);
    104 }
    105 
    106 TEST_CASE("UninstallFlow_UninstallMsix", "[UninstallFlow][workflow]")
    107 {
    108     TestCommon::TempFile uninstallResultPath("TestMsixUninstalled.txt");
    109 
    110     std::ostringstream uninstallOutput;
    111     TestContext context{ uninstallOutput, std::cin };
    112     auto previousThreadGlobals = context.SetForCurrentThread();
    113     OverrideForCompositeInstalledSource(context, CreateTestSource({ TSR::TestInstaller_Msix }));
    114     OverrideForMSIXUninstall(context);
    115     context.Args.AddArg(Execution::Args::Type::Query, TSR::TestInstaller_Msix.Query);
    116 
    117     UninstallCommand uninstall({});
    118     uninstall.Execute(context);
    119     INFO(uninstallOutput.str());
    120 
    121     // Verify Uninstaller is called with the package full name.
    122     REQUIRE(std::filesystem::exists(uninstallResultPath.GetPath()));
    123     std::ifstream uninstallResultFile(uninstallResultPath.GetPath());
    124     REQUIRE(uninstallResultFile.is_open());
    125     std::string uninstallResultStr;
    126     std::getline(uninstallResultFile, uninstallResultStr);
    127     REQUIRE(uninstallResultStr.find("20477fca-282d-49fb-b03e-371dca074f0f_8wekyb3d8bbwe") != std::string::npos);
    128 }
    129 
    130 TEST_CASE("UninstallFlow_UninstallMSStore", "[UninstallFlow][workflow]")
    131 {
    132     TestCommon::TempFile uninstallResultPath("TestMsixUninstalled.txt");
    133 
    134     std::ostringstream uninstallOutput;
    135     TestContext context{ uninstallOutput, std::cin };
    136     auto previousThreadGlobals = context.SetForCurrentThread();
    137     OverrideForCompositeInstalledSource(context, CreateTestSource({ TSR::TestInstaller_MSStore }));
    138     OverrideForMSIXUninstall(context);
    139     context.Args.AddArg(Execution::Args::Type::Query, TSR::TestInstaller_MSStore.Query);
    140 
    141     UninstallCommand uninstall({});
    142     uninstall.Execute(context);
    143     INFO(uninstallOutput.str());
    144 
    145     // Verify Uninstaller is called with the package full name
    146     REQUIRE(std::filesystem::exists(uninstallResultPath.GetPath()));
    147     std::ifstream uninstallResultFile(uninstallResultPath.GetPath());
    148     REQUIRE(uninstallResultFile.is_open());
    149     std::string uninstallResultStr;
    150     std::getline(uninstallResultFile, uninstallResultStr);
    151     REQUIRE(uninstallResultStr.find("microsoft.skypeapp_kzf8qxf38zg5c") != std::string::npos);
    152 }
    153 
    154 TEST_CASE("UninstallFlow_UninstallExeNotFound", "[UninstallFlow][workflow]")
    155 {
    156     TestCommon::TempFile uninstallResultPath("TestExeUninstalled.txt");
    157 
    158     std::ostringstream uninstallOutput;
    159     TestContext context{ uninstallOutput, std::cin };
    160     auto previousThreadGlobals = context.SetForCurrentThread();
    161     OverrideForCompositeInstalledSource(context, CreateTestSource({}));
    162     context.Args.AddArg(Execution::Args::Type::Query, "AppInstallerCliTest.MissingApp"sv);
    163     context.Args.AddArg(Execution::Args::Type::Silent);
    164 
    165     UninstallCommand uninstall({});
    166     uninstall.Execute(context);
    167     INFO(uninstallOutput.str());
    168 
    169     // Verify Uninstaller is not called.
    170     REQUIRE(!std::filesystem::exists(uninstallResultPath.GetPath()));
    171     REQUIRE(uninstallOutput.str().find(Resource::LocString(Resource::String::NoInstalledPackageFound).get()) != std::string::npos);
    172     REQUIRE(context.GetTerminationHR() == APPINSTALLER_CLI_ERROR_NO_APPLICATIONS_FOUND);
    173 }
    174 
    175 TEST_CASE("UninstallFlow_UninstallMultiple", "[UninstallFlow][workflow][MultiQuery]")
    176 {
    177     TestCommon::TempFile exeUninstallResultPath("TestExeUninstalled.txt");
    178     TestCommon::TempFile msixUninstallResultPath("TestMsixUninstalled.txt");
    179 
    180     std::ostringstream uninstallOutput;
    181     TestContext context{ uninstallOutput, std::cin };
    182     auto previousThreadGlobals = context.SetForCurrentThread();
    183     OverrideForCompositeInstalledSource(context, CreateTestSource({ TSR::TestInstaller_Exe, TSR::TestInstaller_Msix }));
    184     OverrideForExeUninstall(context);
    185     OverrideForMSIXUninstall(context);
    186     context.Args.AddArg(Execution::Args::Type::MultiQuery, TSR::TestInstaller_Exe.Query);
    187     context.Args.AddArg(Execution::Args::Type::MultiQuery, TSR::TestInstaller_Msix.Query);
    188 
    189     UninstallCommand uninstall({});
    190     uninstall.Execute(context);
    191     INFO(uninstallOutput.str());
    192 
    193     // Verify Uninstallers are called
    194     REQUIRE(std::filesystem::exists(exeUninstallResultPath.GetPath()));
    195     REQUIRE(std::filesystem::exists(msixUninstallResultPath.GetPath()));
    196 }
    197 
    198 TEST_CASE("UninstallFlow_UninstallMultiple_NotAllInstalled", "[UninstallFlow][workflow][MultiQuery]")
    199 {
    200     std::ostringstream uninstallOutput;
    201     TestContext context{ uninstallOutput, std::cin };
    202     auto previousThreadGlobals = context.SetForCurrentThread();
    203     OverrideForCompositeInstalledSource(context, CreateTestSource({ TSR::TestInstaller_Exe }));
    204     context.Args.AddArg(Execution::Args::Type::MultiQuery, TSR::TestInstaller_Exe.Query);
    205     context.Args.AddArg(Execution::Args::Type::MultiQuery, TSR::TestInstaller_Msix.Query);
    206 
    207     UninstallCommand uninstall({});
    208     uninstall.Execute(context);
    209     INFO(uninstallOutput.str());
    210 
    211     REQUIRE_TERMINATED_WITH(context, APPINSTALLER_CLI_ERROR_NOT_ALL_QUERIES_FOUND_SINGLE);
    212 }