@@ -133,6 +133,19 @@ std::vector<SFS::AppContent> GetSfsAppContentsOverrideFunction(std::string_view
133133 dependencyX64);
134134 dependencyPackages.emplace_back (std::move (*dependencyX64));
135135
136+ // Lower target OS dependency
137+ std::unique_ptr<SFS::AppFile> dependencyX64_lower;
138+ std::ignore = SFS::AppFile::Make (
139+ wuCategoryIdStr + " .appx" ,
140+ " https://NotUsed/" + wuCategoryIdStr + " /dependency/x64" ,
141+ 100 ,
142+ { { SFS::HashType::Sha256, base64EncodedSha256 } },
143+ { SFS::Architecture::Amd64 },
144+ { " Universal=9.0.0.0" },
145+ wuCategoryIdStr + " .Dependency_0.9.3.4_x64__8wekyb3d8bbwe" ,
146+ dependencyX64_lower);
147+ dependencyPackages.emplace_back (std::move (*dependencyX64_lower));
148+
136149 std::unique_ptr<SFS::AppFile> dependencyArm;
137150 std::ignore = SFS::AppFile::Make (
138151 wuCategoryIdStr + " .appx" ,
@@ -166,6 +179,19 @@ std::vector<SFS::AppContent> GetSfsAppContentsOverrideFunction(std::string_view
166179 packageX64);
167180 packages.emplace_back (std::move (*packageX64));
168181
182+ // Good candidate x64, lower minimum OS version, lower package version
183+ std::unique_ptr<SFS::AppFile> packageX64_lower;
184+ std::ignore = SFS::AppFile::Make (
185+ wuCategoryIdStr + " .appx" ,
186+ " https://NotUsed/" + wuCategoryIdStr + " /x64" ,
187+ 100 ,
188+ { { SFS::HashType::Sha256, base64EncodedSha256 } },
189+ { SFS::Architecture::Amd64 },
190+ { " Desktop=9.0.0.0" },
191+ wuCategoryIdStr + " _0.9.0.0_x64__8wekyb3d8bbwe" ,
192+ packageX64_lower);
193+ packages.emplace_back (std::move (*packageX64_lower));
194+
169195 // Good candidate arm
170196 std::unique_ptr<SFS::AppFile> packageArm;
171197 std::ignore = SFS::AppFile::Make (
@@ -595,3 +621,43 @@ TEST_CASE("MSStoreDownloadFlow_Fail_Licensing_Forbidden", "[MSStoreDownloadFlow]
595621 REQUIRE_TERMINATED_WITH (context, APPINSTALLER_CLI_ERROR_LICENSING_API_FAILED_FORBIDDEN);
596622 INFO (downloadOutput.str ());
597623}
624+
625+ TEST_CASE (" MSStoreDownloadFlow_Success_TargetOSVersion" , " [MSStoreDownloadFlow][workflow]" )
626+ {
627+ TestCommon::TempDirectory tempDirectory (" TestDownloadDirectory" , false );
628+
629+ std::ostringstream downloadOutput;
630+ TestContext context{ downloadOutput, std::cin };
631+ auto previousThreadGlobals = context.SetForCurrentThread ();
632+ OverrideDownloadInstallerFileForMSStoreDownload (context);
633+ TestHook::SetDisplayCatalogHttpPipelineStage_Override displayCatalogOverride (GetTestRestRequestHandler (web::http::status_codes::OK, TestDisplayCatalogResponse));
634+ TestHook::SetSfsClientAppContents_Override sfsClientOverride ({ &GetSfsAppContentsOverrideFunction });
635+ TestHook::SetLicensingHttpPipelineStage_Override licensingOverride (GetTestRestRequestHandler (web::http::status_codes::OK, TestLicensingResponse));
636+ context.Args .AddArg (Execution::Args::Type::Manifest, TestDataFile (" DownloadFlowTest_MSStore.yaml" ).GetPath ().u8string ());
637+ context.Args .AddArg (Execution::Args::Type::DownloadDirectory, tempDirectory);
638+ context.Args .AddArg (Execution::Args::Type::Locale, " en-US" sv);
639+ context.Args .AddArg (Execution::Args::Type::Platform, " Windows.Desktop" sv);
640+ context.Args .AddArg (Execution::Args::Type::OSVersion, " 9.0.0.0" sv);
641+
642+ DownloadCommand download ({});
643+ download.Execute (context);
644+ REQUIRE (context.GetTerminationHR () == S_OK);
645+ INFO (downloadOutput.str ());
646+
647+ // Verify downloaded files
648+ REQUIRE (std::filesystem::exists (tempDirectory.GetPath ()));
649+ REQUIRE (std::filesystem::exists (tempDirectory.GetPath () / L" Dependencies" ));
650+ REQUIRE (std::filesystem::exists (tempDirectory.GetPath () / L" Dependencies" / L" TestCategoryIdEnglish.Dependency_0.9.3.4_Universal_X64.appx" ));
651+ REQUIRE_FALSE (std::filesystem::exists (tempDirectory.GetPath () / L" Dependencies" / L" TestCategoryIdEnglish.Dependency_1.2.3.4_Universal_Arm.appx" ));
652+ REQUIRE (std::filesystem::exists (tempDirectory.GetPath () / L" TestCategoryIdEnglish_0.9.0.0_Desktop_X64.appx" ));
653+ REQUIRE_FALSE (std::filesystem::exists (tempDirectory.GetPath () / L" TestCategoryIdEnglish_1.0.0.0_Desktop_Arm.appx" ));
654+ REQUIRE_FALSE (std::filesystem::exists (tempDirectory.GetPath () / L" TestCategoryIdEnglish.IoT_2.0.0.0_IoT_Arm.appx" ));
655+
656+ // Verify license
657+ REQUIRE (std::filesystem::exists (tempDirectory.GetPath () / L" 9WZDNCRFJ364_License.xml" ));
658+ std::ifstream licenseFile (tempDirectory.GetPath () / L" 9WZDNCRFJ364_License.xml" );
659+ REQUIRE (licenseFile.is_open ());
660+ std::string licenseFileStr;
661+ std::getline (licenseFile, licenseFileStr);
662+ REQUIRE (licenseFileStr == LicenseContent);
663+ }
0 commit comments