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 }