PinFlow.cpp (8079B)
1 // Copyright (c) Microsoft Corporation. 2 // Licensed under the MIT License. 3 #include "pch.h" 4 #include "WorkflowCommon.h" 5 #include "TestHooks.h" 6 #include <Commands/PinCommand.h> 7 #include <Workflows/PinFlow.h> 8 #include <Microsoft/PinningIndex.h> 9 #include <AppInstallerRuntime.h> 10 #include <AppInstallerVersions.h> 11 #include <winget/PinningData.h> 12 13 using namespace TestCommon; 14 using namespace AppInstaller::CLI; 15 using namespace AppInstaller::CLI::Workflow; 16 using namespace AppInstaller::Repository::Microsoft; 17 using namespace AppInstaller::Utility; 18 using namespace AppInstaller::Pinning; 19 using namespace AppInstaller::SQLite; 20 21 TEST_CASE("PinFlow_Add", "[PinFlow][workflow]") 22 { 23 TempFile indexFile("pinningIndex", ".db"); 24 TestHook::SetPinningIndex_Override pinningIndexOverride(indexFile.GetPath()); 25 26 std::ostringstream pinAddOutput; 27 TestContext addContext{ pinAddOutput, std::cin }; 28 OverrideForCompositeInstalledSource(addContext, CreateTestSource({ TSR::TestInstaller_Exe })); 29 addContext.Args.AddArg(Execution::Args::Type::Query, TSR::TestInstaller_Exe.Query); 30 addContext.Args.AddArg(Execution::Args::Type::BlockingPin); 31 32 PinAddCommand pinAdd({}); 33 pinAdd.Execute(addContext); 34 INFO(pinAddOutput.str()); 35 36 SECTION("Pin is saved") 37 { 38 auto index = PinningIndex::Open(indexFile.GetPath().u8string(), SQLiteStorageBase::OpenDisposition::Read); 39 auto pins = index.GetAllPins(); 40 REQUIRE(pins.size() == 1); 41 REQUIRE(pins[0].GetType() == PinType::Blocking); 42 REQUIRE(pins[0].GetGatedVersion().ToString() == ""); 43 REQUIRE(pins[0].GetKey().PackageId == "AppInstallerCliTest.TestExeInstaller"); 44 REQUIRE(pins[0].GetKey().SourceId == "*TestSource"); 45 46 std::ostringstream pinListOutput; 47 TestContext listContext{ pinListOutput, std::cin }; 48 OverrideForCompositeInstalledSource(listContext, CreateTestSource({ TSR::TestInstaller_Exe })); 49 listContext.Args.AddArg(Execution::Args::Type::Query, TSR::TestInstaller_Exe.Query); 50 51 PinListCommand pinList({}); 52 pinList.Execute(listContext); 53 54 INFO(pinListOutput.str()); 55 REQUIRE(pinListOutput.str().find("AppInstallerCliTest.TestExeInstaller")); 56 REQUIRE(pinListOutput.str().find("Blocking")); 57 } 58 SECTION("Remove pin") 59 { 60 std::ostringstream pinRemoveOutput; 61 TestContext removeContext{ pinRemoveOutput, std::cin }; 62 OverrideForCompositeInstalledSource(removeContext, CreateTestSource({ TSR::TestInstaller_Exe })); 63 removeContext.Args.AddArg(Execution::Args::Type::Query, TSR::TestInstaller_Exe.Query); 64 65 PinRemoveCommand pinRemove({}); 66 pinRemove.Execute(removeContext); 67 INFO(pinRemoveOutput.str()); 68 69 auto index = PinningIndex::Open(indexFile.GetPath().u8string(), SQLiteStorageBase::OpenDisposition::Read); 70 auto pins = index.GetAllPins(); 71 REQUIRE(pins.empty()); 72 } 73 SECTION("Reset pins") 74 { 75 std::ostringstream pinResetOutput; 76 TestContext resetContext{ pinResetOutput, std::cin }; 77 78 SECTION("Without --force") 79 { 80 OverrideForCompositeInstalledSource(resetContext, CreateTestSource({ TSR::TestInstaller_Exe })); 81 PinResetCommand pinReset({}); 82 pinReset.Execute(resetContext); 83 INFO(pinResetOutput.str()); 84 85 auto index = PinningIndex::Open(indexFile.GetPath().u8string(), SQLiteStorageBase::OpenDisposition::Read); 86 auto pins = index.GetAllPins(); 87 REQUIRE(pins.size() == 1); 88 } 89 SECTION("With --force") 90 { 91 resetContext.Args.AddArg(Execution::Args::Type::Force); 92 93 PinResetCommand pinReset({}); 94 pinReset.Execute(resetContext); 95 INFO(pinResetOutput.str()); 96 97 auto index = PinningIndex::Open(indexFile.GetPath().u8string(), SQLiteStorageBase::OpenDisposition::Read); 98 auto pins = index.GetAllPins(); 99 REQUIRE(pins.empty()); 100 } 101 } 102 SECTION("Update pin") 103 { 104 std::ostringstream pinUpdateOutput; 105 TestContext updateContext{ pinUpdateOutput, std::cin }; 106 OverrideForCompositeInstalledSource(updateContext, CreateTestSource({ TSR::TestInstaller_Exe })); 107 updateContext.Args.AddArg(Execution::Args::Type::Query, TSR::TestInstaller_Exe.Query); 108 109 SECTION("Without --force") 110 { 111 PinAddCommand pinUpdate({}); 112 pinUpdate.Execute(updateContext); 113 INFO(pinUpdateOutput.str()); 114 REQUIRE_TERMINATED_WITH(updateContext, APPINSTALLER_CLI_ERROR_PIN_ALREADY_EXISTS); 115 116 auto index = PinningIndex::Open(indexFile.GetPath().u8string(), SQLiteStorageBase::OpenDisposition::Read); 117 auto pins = index.GetAllPins(); 118 REQUIRE(pins.size() == 1); 119 REQUIRE(pins[0].GetType() == PinType::Blocking); 120 } 121 SECTION("With --force") 122 { 123 updateContext.Args.AddArg(Execution::Args::Type::Force); 124 125 PinAddCommand pinUpdate({}); 126 pinUpdate.Execute(updateContext); 127 INFO(pinUpdateOutput.str()); 128 129 auto index = PinningIndex::Open(indexFile.GetPath().u8string(), SQLiteStorageBase::OpenDisposition::Read); 130 auto pins = index.GetAllPins(); 131 REQUIRE(pins.size() == 1); 132 REQUIRE(pins[0].GetType() == PinType::Pinning); 133 } 134 } 135 } 136 137 TEST_CASE("PinFlow_Add_NotFound", "[PinFlow][workflow]") 138 { 139 TempFile indexFile("pinningIndex", ".db"); 140 TestHook::SetPinningIndex_Override pinningIndexOverride(indexFile.GetPath()); 141 142 std::ostringstream pinAddOutput; 143 TestContext addContext{ pinAddOutput, std::cin }; 144 OverrideForCompositeInstalledSource(addContext, CreateTestSource({})); 145 addContext.Args.AddArg(Execution::Args::Type::Query, "This package doesn't exist"sv); 146 147 PinAddCommand pinAdd({}); 148 pinAdd.Execute(addContext); 149 INFO(pinAddOutput.str()); 150 151 REQUIRE_TERMINATED_WITH(addContext, APPINSTALLER_CLI_ERROR_NO_APPLICATIONS_FOUND); 152 } 153 154 TEST_CASE("PinFlow_ListEmpty", "[PinFlow][workflow]") 155 { 156 TempFile indexFile("pinningIndex", ".db"); 157 TestHook::SetPinningIndex_Override pinningIndexOverride(indexFile.GetPath()); 158 159 std::ostringstream pinListOutput; 160 TestContext listContext{ pinListOutput, std::cin }; 161 OverrideForCompositeInstalledSource(listContext, CreateTestSource({})); 162 163 PinListCommand pinList({}); 164 pinList.Execute(listContext); 165 INFO(pinListOutput.str()); 166 167 REQUIRE(pinListOutput.str().find(Resource::LocString(Resource::String::PinNoPinsExist)) != std::string::npos); 168 } 169 170 TEST_CASE("PinFlow_RemoveNonExisting", "[PinFlow][workflow]") 171 { 172 TempFile indexFile("pinningIndex", ".db"); 173 TestHook::SetPinningIndex_Override pinningIndexOverride(indexFile.GetPath()); 174 175 std::ostringstream pinRemoveOutput; 176 TestContext removeContext{ pinRemoveOutput, std::cin }; 177 OverrideForCompositeInstalledSource(removeContext, CreateTestSource({ TSR::TestInstaller_Exe })); 178 removeContext.Args.AddArg(Execution::Args::Type::Query, TSR::TestInstaller_Exe.Query); 179 180 PinRemoveCommand pinRemove({}); 181 pinRemove.Execute(removeContext); 182 INFO(pinRemoveOutput.str()); 183 184 REQUIRE_TERMINATED_WITH(removeContext, APPINSTALLER_CLI_ERROR_PIN_DOES_NOT_EXIST); 185 } 186 187 TEST_CASE("PinFlow_ResetEmpty", "[PinFlow][workflow]") 188 { 189 TempFile indexFile("pinningIndex", ".db"); 190 TestHook::SetPinningIndex_Override pinningIndexOverride(indexFile.GetPath()); 191 192 std::ostringstream pinResetOutput; 193 TestContext resetContext{ pinResetOutput, std::cin }; 194 resetContext.Args.AddArg(Execution::Args::Type::Force); 195 196 PinResetCommand pinReset({}); 197 pinReset.Execute(resetContext); 198 INFO(pinResetOutput.str()); 199 200 REQUIRE(pinResetOutput.str().find(Resource::LocString(Resource::String::PinNoPinsExist)) != std::string::npos); 201 }