RestInterface_1_1.cpp (29084B)
1 // Copyright (c) Microsoft Corporation. 2 // Licensed under the MIT License. 3 #include "pch.h" 4 #include "TestCommon.h" 5 #include "TestRestRequestHandler.h" 6 #include <Rest/Schema/1_1/Interface.h> 7 #include <Rest/Schema/IRestClient.h> 8 #include <AppInstallerVersions.h> 9 #include <AppInstallerErrors.h> 10 11 using namespace TestCommon; 12 using namespace AppInstaller::Http; 13 using namespace AppInstaller::Utility; 14 using namespace AppInstaller::Manifest; 15 using namespace AppInstaller::Repository; 16 using namespace AppInstaller::Repository::Rest; 17 using namespace AppInstaller::Repository::Rest::Schema; 18 using namespace AppInstaller::Repository::Rest::Schema::V1_1; 19 20 namespace 21 { 22 const std::string TestRestUriString = "http://restsource.com/api"; 23 24 IRestClient::Information GetTestSourceInformation() 25 { 26 IRestClient::Information result; 27 28 result.RequiredPackageMatchFields.emplace_back("Market"); 29 result.RequiredQueryParameters.emplace_back("Market"); 30 result.UnsupportedPackageMatchFields.emplace_back("Moniker"); 31 result.UnsupportedQueryParameters.emplace_back("Channel"); 32 33 return result; 34 } 35 36 struct GoodManifest_AllFields 37 { 38 utility::string_t GetSampleManifest_AllFields() 39 { 40 return _XPLATSTR( 41 R"delimiter( 42 { 43 "Data": { 44 "PackageIdentifier": "Foo.Bar", 45 "Versions": [ 46 { 47 "PackageVersion": "3.0.0abc", 48 "DefaultLocale": { 49 "PackageLocale": "en-US", 50 "Publisher": "Foo", 51 "PublisherUrl": "http://publisher.net", 52 "PublisherSupportUrl": "http://publisherSupport.net", 53 "PrivacyUrl": "http://packagePrivacyUrl.net", 54 "Author": "FooBar", 55 "PackageName": "Bar", 56 "PackageUrl": "http://packageUrl.net", 57 "License": "Foo Bar License", 58 "LicenseUrl": "http://licenseUrl.net", 59 "Copyright": "Foo Bar Copyright", 60 "CopyrightUrl": "http://copyrightUrl.net", 61 "ShortDescription": "Foo bar is a foo bar.", 62 "Description": "Foo bar is a placeholder.", 63 "Tags": [ 64 "FooBar", 65 "Foo", 66 "Bar" 67 ], 68 "Moniker": "FooBarMoniker", 69 "ReleaseNotes": "Default release notes", 70 "ReleaseNotesUrl": "https://DefaultReleaseNotes.net", 71 "Agreements": [{ 72 "AgreementLabel": "DefaultLabel", 73 "Agreement": "DefaultText", 74 "AgreementUrl": "https://DefaultAgreementUrl.net" 75 }] 76 }, 77 "Channel": "", 78 "Locales": [ 79 { 80 "PackageLocale": "fr-Fr", 81 "Publisher": "Foo French", 82 "PublisherUrl": "http://publisher-fr.net", 83 "PublisherSupportUrl": "http://publisherSupport-fr.net", 84 "PrivacyUrl": "http://packagePrivacyUrl-fr.net", 85 "Author": "FooBar French", 86 "PackageName": "Bar", 87 "PackageUrl": "http://packageUrl-fr.net", 88 "License": "Foo Bar License", 89 "LicenseUrl": "http://licenseUrl-fr.net", 90 "Copyright": "Foo Bar Copyright", 91 "CopyrightUrl": "http://copyrightUrl-fr.net", 92 "ShortDescription": "Foo bar is a foo bar French.", 93 "Description": "Foo bar is a placeholder French.", 94 "Tags": [ 95 "FooBarFr", 96 "FooFr", 97 "BarFr" 98 ], 99 "ReleaseNotes": "Release notes", 100 "ReleaseNotesUrl": "https://ReleaseNotes.net", 101 "Agreements": [{ 102 "AgreementLabel": "Label", 103 "Agreement": "Text", 104 "AgreementUrl": "https://AgreementUrl.net" 105 }] 106 } 107 ], 108 "Installers": [ 109 { 110 "InstallerSha256": "011048877dfaef109801b3f3ab2b60afc74f3fc4f7b3430e0c897f5da1df84b6", 111 "InstallerUrl": "http://foobar.exe", 112 "Architecture": "x86", 113 "InstallerLocale": "en-US", 114 "Platform": [ 115 "Windows.Desktop" 116 ], 117 "MinimumOSVersion": "1078", 118 "InstallerType": "msi", 119 "Scope": "user", 120 "InstallModes": [ 121 "interactive" 122 ], 123 "InstallerSwitches": { 124 "Silent": "/s", 125 "SilentWithProgress": "/s", 126 "Interactive": "/i", 127 "InstallLocation": "C:\\Users\\User1", 128 "Log": "/l", 129 "Upgrade": "/u", 130 "Custom": "/custom" 131 }, 132 "InstallerSuccessCodes": [ 133 0 134 ], 135 "UpgradeBehavior": "install", 136 "Commands": [ 137 "command1" 138 ], 139 "Protocols": [ 140 "protocol1" 141 ], 142 "FileExtensions": [ 143 ".file-extension" 144 ], 145 "Dependencies": { 146 "WindowsFeatures": [ 147 "feature1" 148 ], 149 "WindowsLibraries": [ 150 "library1" 151 ], 152 "PackageDependencies": [ 153 { 154 "PackageIdentifier": "Foo.Baz", 155 "MinimumVersion": "2.0.0" 156 } 157 ], 158 "ExternalDependencies": [ 159 "FooBarBaz" 160 ] 161 }, 162 "ProductCode": "5b6e0f8a-3bbf-4a17-aefd-024c2b3e075d", 163 "ReleaseDate": "2021-01-01", 164 "InstallerAbortsTerminal": true, 165 "InstallLocationRequired": true, 166 "RequireExplicitUpgrade": true, 167 "UnsupportedOSArchitectures": [ "arm" ], 168 "ElevationRequirement": "elevatesSelf", 169 "AppsAndFeaturesEntries": [{ 170 "DisplayName": "DisplayName", 171 "DisplayVersion": "DisplayVersion", 172 "Publisher": "Publisher", 173 "ProductCode": "ProductCode", 174 "UpgradeCode": "UpgradeCode", 175 "InstallerType": "exe" 176 }], 177 "Markets" : { 178 "AllowedMarkets": [ "US" ] 179 }, 180 "ExpectedReturnCodes": [{ 181 "InstallerReturnCode": 3, 182 "ReturnResponse": "InstallInProgress" 183 }] 184 } 185 ] 186 } 187 ] 188 }, 189 "ContinuationToken": "abcd" 190 })delimiter"); 191 } 192 193 void VerifyLocalizations_AllFields(const Manifest& manifest) 194 { 195 REQUIRE(manifest.DefaultLocalization.Locale == "en-US"); 196 REQUIRE(manifest.DefaultLocalization.Get<Localization::Publisher>() == "Foo"); 197 REQUIRE(manifest.DefaultLocalization.Get<Localization::PublisherUrl>() == "http://publisher.net"); 198 REQUIRE(manifest.DefaultLocalization.Get<Localization::PublisherSupportUrl>() == "http://publisherSupport.net"); 199 REQUIRE(manifest.DefaultLocalization.Get<Localization::PrivacyUrl>() == "http://packagePrivacyUrl.net"); 200 REQUIRE(manifest.DefaultLocalization.Get<Localization::Author>() == "FooBar"); 201 REQUIRE(manifest.DefaultLocalization.Get<Localization::PackageName>() == "Bar"); 202 REQUIRE(manifest.DefaultLocalization.Get<Localization::PackageUrl>() == "http://packageUrl.net"); 203 REQUIRE(manifest.DefaultLocalization.Get<Localization::License>() == "Foo Bar License"); 204 REQUIRE(manifest.DefaultLocalization.Get<Localization::LicenseUrl>() == "http://licenseUrl.net"); 205 REQUIRE(manifest.DefaultLocalization.Get<Localization::Copyright>() == "Foo Bar Copyright"); 206 REQUIRE(manifest.DefaultLocalization.Get<Localization::CopyrightUrl>() == "http://copyrightUrl.net"); 207 REQUIRE(manifest.DefaultLocalization.Get<Localization::ShortDescription>() == "Foo bar is a foo bar."); 208 REQUIRE(manifest.DefaultLocalization.Get<Localization::Description>() == "Foo bar is a placeholder."); 209 REQUIRE(manifest.DefaultLocalization.Get<Localization::Tags>().size() == 3); 210 REQUIRE(manifest.DefaultLocalization.Get<Localization::Tags>().at(0) == "FooBar"); 211 REQUIRE(manifest.DefaultLocalization.Get<Localization::Tags>().at(1) == "Foo"); 212 REQUIRE(manifest.DefaultLocalization.Get<Localization::Tags>().at(2) == "Bar"); 213 REQUIRE(manifest.DefaultLocalization.Get<Localization::ReleaseNotes>() == "Default release notes"); 214 REQUIRE(manifest.DefaultLocalization.Get<Localization::ReleaseNotesUrl>() == "https://DefaultReleaseNotes.net"); 215 REQUIRE(manifest.DefaultLocalization.Get<Localization::Agreements>().size() == 1); 216 REQUIRE(manifest.DefaultLocalization.Get<Localization::Agreements>().at(0).Label == "DefaultLabel"); 217 REQUIRE(manifest.DefaultLocalization.Get<Localization::Agreements>().at(0).AgreementText == "DefaultText"); 218 REQUIRE(manifest.DefaultLocalization.Get<Localization::Agreements>().at(0).AgreementUrl == "https://DefaultAgreementUrl.net"); 219 220 REQUIRE(manifest.Localizations.size() == 1); 221 ManifestLocalization frenchLocalization = manifest.Localizations.at(0); 222 REQUIRE(frenchLocalization.Locale == "fr-Fr"); 223 REQUIRE(frenchLocalization.Get<Localization::Publisher>() == "Foo French"); 224 REQUIRE(frenchLocalization.Get<Localization::PublisherUrl>() == "http://publisher-fr.net"); 225 REQUIRE(frenchLocalization.Get<Localization::PublisherSupportUrl>() == "http://publisherSupport-fr.net"); 226 REQUIRE(frenchLocalization.Get<Localization::PrivacyUrl>() == "http://packagePrivacyUrl-fr.net"); 227 REQUIRE(frenchLocalization.Get<Localization::Author>() == "FooBar French"); 228 REQUIRE(frenchLocalization.Get<Localization::PackageName>() == "Bar"); 229 REQUIRE(frenchLocalization.Get<Localization::PackageUrl>() == "http://packageUrl-fr.net"); 230 REQUIRE(frenchLocalization.Get<Localization::License>() == "Foo Bar License"); 231 REQUIRE(frenchLocalization.Get<Localization::LicenseUrl>() == "http://licenseUrl-fr.net"); 232 REQUIRE(frenchLocalization.Get<Localization::Copyright>() == "Foo Bar Copyright"); 233 REQUIRE(frenchLocalization.Get<Localization::CopyrightUrl>() == "http://copyrightUrl-fr.net"); 234 REQUIRE(frenchLocalization.Get<Localization::ShortDescription>() == "Foo bar is a foo bar French."); 235 REQUIRE(frenchLocalization.Get<Localization::Description>() == "Foo bar is a placeholder French."); 236 REQUIRE(frenchLocalization.Get<Localization::Tags>().size() == 3); 237 REQUIRE(frenchLocalization.Get<Localization::Tags>().at(0) == "FooBarFr"); 238 REQUIRE(frenchLocalization.Get<Localization::Tags>().at(1) == "FooFr"); 239 REQUIRE(frenchLocalization.Get<Localization::Tags>().at(2) == "BarFr"); 240 REQUIRE(frenchLocalization.Get<Localization::ReleaseNotes>() == "Release notes"); 241 REQUIRE(frenchLocalization.Get<Localization::ReleaseNotesUrl>() == "https://ReleaseNotes.net"); 242 REQUIRE(frenchLocalization.Get<Localization::Agreements>().size() == 1); 243 REQUIRE(frenchLocalization.Get<Localization::Agreements>().at(0).Label == "Label"); 244 REQUIRE(frenchLocalization.Get<Localization::Agreements>().at(0).AgreementText == "Text"); 245 REQUIRE(frenchLocalization.Get<Localization::Agreements>().at(0).AgreementUrl == "https://AgreementUrl.net"); 246 } 247 248 void VerifyInstallers_AllFields(const Manifest& manifest) 249 { 250 REQUIRE(manifest.Installers.size() == 1); 251 252 ManifestInstaller actualInstaller = manifest.Installers.at(0); 253 REQUIRE(actualInstaller.Sha256 == AppInstaller::Utility::SHA256::ConvertToBytes("011048877dfaef109801b3f3ab2b60afc74f3fc4f7b3430e0c897f5da1df84b6")); 254 REQUIRE(actualInstaller.Url == "http://foobar.exe"); 255 REQUIRE(actualInstaller.Arch == Architecture::X86); 256 REQUIRE(actualInstaller.Locale == "en-US"); 257 REQUIRE(actualInstaller.Platform.size() == 1); 258 REQUIRE(actualInstaller.Platform[0] == PlatformEnum::Desktop); 259 REQUIRE(actualInstaller.MinOSVersion == "1078"); 260 REQUIRE(actualInstaller.BaseInstallerType == InstallerTypeEnum::Msi); 261 REQUIRE(actualInstaller.Scope == ScopeEnum::User); 262 REQUIRE(actualInstaller.InstallModes.size() == 1); 263 REQUIRE(actualInstaller.InstallModes.at(0) == InstallModeEnum::Interactive); 264 REQUIRE(actualInstaller.Switches.size() == 7); 265 REQUIRE(actualInstaller.Switches.at(InstallerSwitchType::Silent) == "/s"); 266 REQUIRE(actualInstaller.Switches.at(InstallerSwitchType::SilentWithProgress) == "/s"); 267 REQUIRE(actualInstaller.Switches.at(InstallerSwitchType::Interactive) == "/i"); 268 REQUIRE(actualInstaller.Switches.at(InstallerSwitchType::InstallLocation) == "C:\\Users\\User1"); 269 REQUIRE(actualInstaller.Switches.at(InstallerSwitchType::Log) == "/l"); 270 REQUIRE(actualInstaller.Switches.at(InstallerSwitchType::Update) == "/u"); 271 REQUIRE(actualInstaller.Switches.at(InstallerSwitchType::Custom) == "/custom"); 272 REQUIRE(actualInstaller.InstallerSuccessCodes.size() == 1); 273 REQUIRE(actualInstaller.InstallerSuccessCodes.at(0) == 0); 274 REQUIRE(actualInstaller.UpdateBehavior == UpdateBehaviorEnum::Install); 275 REQUIRE(actualInstaller.Commands.at(0) == "command1"); 276 REQUIRE(actualInstaller.Protocols.at(0) == "protocol1"); 277 REQUIRE(actualInstaller.FileExtensions.at(0) == ".file-extension"); 278 REQUIRE(actualInstaller.Dependencies.HasExactDependency(DependencyType::WindowsFeature, "feature1")); 279 REQUIRE(actualInstaller.Dependencies.HasExactDependency(DependencyType::WindowsLibrary, "library1")); 280 REQUIRE(actualInstaller.Dependencies.HasExactDependency(DependencyType::Package, "Foo.Baz", "2.0.0")); 281 REQUIRE(actualInstaller.Dependencies.HasExactDependency(DependencyType::External, "FooBarBaz")); 282 REQUIRE(actualInstaller.PackageFamilyName == ""); 283 REQUIRE(actualInstaller.ProductCode == "5b6e0f8a-3bbf-4a17-aefd-024c2b3e075d"); 284 REQUIRE(actualInstaller.ReleaseDate == "2021-01-01"); 285 REQUIRE(actualInstaller.InstallerAbortsTerminal); 286 REQUIRE(actualInstaller.InstallLocationRequired); 287 REQUIRE(actualInstaller.RequireExplicitUpgrade); 288 REQUIRE(actualInstaller.ElevationRequirement == ElevationRequirementEnum::ElevatesSelf); 289 REQUIRE(actualInstaller.UnsupportedOSArchitectures.size() == 1); 290 REQUIRE(actualInstaller.UnsupportedOSArchitectures.at(0) == Architecture::Arm); 291 REQUIRE(actualInstaller.AppsAndFeaturesEntries.size() == 1); 292 REQUIRE(actualInstaller.AppsAndFeaturesEntries.at(0).DisplayName == "DisplayName"); 293 REQUIRE(actualInstaller.AppsAndFeaturesEntries.at(0).DisplayVersion == "DisplayVersion"); 294 REQUIRE(actualInstaller.AppsAndFeaturesEntries.at(0).Publisher == "Publisher"); 295 REQUIRE(actualInstaller.AppsAndFeaturesEntries.at(0).ProductCode == "ProductCode"); 296 REQUIRE(actualInstaller.AppsAndFeaturesEntries.at(0).UpgradeCode == "UpgradeCode"); 297 REQUIRE(actualInstaller.AppsAndFeaturesEntries.at(0).InstallerType == InstallerTypeEnum::Exe); 298 REQUIRE(actualInstaller.Markets.AllowedMarkets.size() == 1); 299 REQUIRE(actualInstaller.Markets.AllowedMarkets.at(0) == "US"); 300 REQUIRE(actualInstaller.ExpectedReturnCodes.at(3).ReturnResponseEnum == ExpectedReturnCodeEnum::InstallInProgress); 301 } 302 }; 303 } 304 305 TEST_CASE("Search_BadResponse_UnsupportedPackageMatchFields", "[RestSource][Interface_1_1]") 306 { 307 utility::string_t sample = _XPLATSTR( 308 R"delimiter({ 309 "Data" : [], 310 "UnsupportedPackageMatchFields" : [ "Moniker" ] 311 })delimiter"); 312 313 HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) }; 314 Interface v1_1{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {} }; 315 AppInstaller::Repository::SearchRequest request; 316 PackageMatchFilter filter{ PackageMatchField::Name, MatchType::Exact, "Foo" }; 317 request.Filters.emplace_back(std::move(filter)); 318 REQUIRE_THROWS_HR(v1_1.Search(request), APPINSTALLER_CLI_ERROR_UNSUPPORTED_SOURCE_REQUEST); 319 } 320 321 TEST_CASE("Search_BadResponse_RequiredPackageMatchFields", "[RestSource][Interface_1_1]") 322 { 323 utility::string_t sample = _XPLATSTR( 324 R"delimiter({ 325 "Data" : [], 326 "RequiredPackageMatchFields" : [ "Moniker" ] 327 })delimiter"); 328 329 HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) }; 330 Interface v1_1{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {} }; 331 AppInstaller::Repository::SearchRequest request; 332 PackageMatchFilter filter{ PackageMatchField::Name, MatchType::Exact, "Foo" }; 333 request.Filters.emplace_back(std::move(filter)); 334 REQUIRE_THROWS_HR(v1_1.Search(request), APPINSTALLER_CLI_ERROR_UNSUPPORTED_SOURCE_REQUEST); 335 } 336 337 TEST_CASE("GetManifests_BadResponse_UnsupportedQueryParameters", "[RestSource][Interface_1_1]") 338 { 339 utility::string_t sample = _XPLATSTR( 340 R"delimiter({ 341 "Data" : null, 342 "UnsupportedQueryParameters" : [ "Channel" ] 343 })delimiter"); 344 345 HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) }; 346 Interface v1_1{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {} }; 347 REQUIRE_THROWS_HR(v1_1.GetManifests("Foo"), APPINSTALLER_CLI_ERROR_UNSUPPORTED_SOURCE_REQUEST); 348 } 349 350 TEST_CASE("GetManifests_BadResponse_RequiredQueryParameters", "[RestSource][Interface_1_1]") 351 { 352 utility::string_t sample = _XPLATSTR( 353 R"delimiter({ 354 "Data" : null, 355 "RequiredQueryParameters" : [ "Version" ] 356 })delimiter"); 357 358 HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) }; 359 Interface v1_1{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {} }; 360 REQUIRE_THROWS_HR(v1_1.GetManifests("Foo"), APPINSTALLER_CLI_ERROR_UNSUPPORTED_SOURCE_REQUEST); 361 } 362 363 TEST_CASE("Search_BadRequest_UnsupportedPackageMatchFields", "[RestSource][Interface_1_1]") 364 { 365 utility::string_t sample = _XPLATSTR( 366 R"delimiter({ 367 "Data" : [ 368 { 369 "PackageIdentifier": "git.package", 370 "PackageName": "package", 371 "Publisher": "git", 372 "Versions": [ 373 { "PackageVersion": "1.0.0" }, 374 { "PackageVersion": "2.0.0" }] 375 }] 376 })delimiter"); 377 378 HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) }; 379 Interface v1_1{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {} }; 380 AppInstaller::Repository::SearchRequest request; 381 PackageMatchFilter filter{ PackageMatchField::Moniker, MatchType::Exact, "Foo" }; 382 request.Filters.emplace_back(std::move(filter)); 383 REQUIRE_THROWS_HR(v1_1.Search(request), APPINSTALLER_CLI_ERROR_UNSUPPORTED_SOURCE_REQUEST); 384 } 385 386 TEST_CASE("Search_GoodRequest_OnlyMarketRequired", "[RestSource][Interface_1_1]") 387 { 388 utility::string_t sample = _XPLATSTR( 389 R"delimiter({ 390 "Data" : [ 391 { 392 "PackageIdentifier": "git.package", 393 "PackageName": "package", 394 "Publisher": "git", 395 "Versions": [ 396 { "PackageVersion": "1.0.0" }, 397 { "PackageVersion": "2.0.0" }] 398 }] 399 })delimiter"); 400 401 HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) }; 402 Interface v1_1{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {} }; 403 AppInstaller::Repository::SearchRequest request; 404 PackageMatchFilter filter{ PackageMatchField::Name, MatchType::Exact, "Foo" }; 405 request.Filters.emplace_back(std::move(filter)); 406 Schema::IRestClient::SearchResult searchResponse = v1_1.Search(request); 407 REQUIRE(searchResponse.Matches.size() == 1); 408 Schema::IRestClient::Package package = searchResponse.Matches.at(0); 409 REQUIRE(package.PackageInformation.PackageIdentifier.compare("git.package") == 0); 410 REQUIRE(package.PackageInformation.Publisher.compare("git") == 0); 411 REQUIRE(package.PackageInformation.PackageName.compare("package") == 0); 412 REQUIRE(package.Versions.size() == 2); 413 REQUIRE(package.Versions.at(0).VersionAndChannel.GetVersion().ToString().compare("1.0.0") == 0); 414 REQUIRE(package.Versions.at(1).VersionAndChannel.GetVersion().ToString().compare("2.0.0") == 0); 415 } 416 417 TEST_CASE("GetManifests_BadRequest_UnsupportedQueryParameters", "[RestSource][Interface_1_1]") 418 { 419 utility::string_t sample = _XPLATSTR( 420 R"delimiter({ 421 "Data": { 422 "PackageIdentifier": "Foo.Bar", 423 "Versions": [ 424 { 425 "PackageVersion": "5.0.0", 426 "DefaultLocale": { 427 "PackageLocale": "en-us", 428 "Publisher": "Foo", 429 "PackageName": "Bar", 430 "License": "Foo bar license", 431 "ShortDescription": "Foo bar description" 432 }, 433 "Installers": [ 434 { 435 "Architecture": "x64", 436 "InstallerSha256": "011048877dfaef109801b3f3ab2b60afc74f3fc4f7b3430e0c897f5da1df84b6", 437 "InstallerType": "exe", 438 "InstallerUrl": "https://installer.example.com/foobar.exe" 439 } 440 ] 441 } 442 ] 443 } 444 })delimiter"); 445 446 HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) }; 447 Interface v1_1{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {} }; 448 REQUIRE_THROWS_HR(v1_1.GetManifestByVersion("Foo", "1.0", "beta"), APPINSTALLER_CLI_ERROR_UNSUPPORTED_SOURCE_REQUEST); 449 } 450 451 TEST_CASE("GetManifests_GoodRequest_OnlyMarketRequired", "[RestSource][Interface_1_1]") 452 { 453 utility::string_t sample = _XPLATSTR( 454 R"delimiter({ 455 "Data": { 456 "PackageIdentifier": "Foo.Bar", 457 "Versions": [ 458 { 459 "PackageVersion": "5.0.0", 460 "DefaultLocale": { 461 "PackageLocale": "en-us", 462 "Publisher": "Foo", 463 "PackageName": "Bar", 464 "License": "Foo bar license", 465 "ShortDescription": "Foo bar description" 466 }, 467 "Installers": [ 468 { 469 "Architecture": "x64", 470 "InstallerSha256": "011048877dfaef109801b3f3ab2b60afc74f3fc4f7b3430e0c897f5da1df84b6", 471 "InstallerType": "exe", 472 "InstallerUrl": "https://installer.example.com/foobar.exe" 473 } 474 ] 475 } 476 ] 477 } 478 })delimiter"); 479 480 IRestClient::Information info = GetTestSourceInformation(); 481 info.UnsupportedQueryParameters.clear(); 482 HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) }; 483 Interface v1_1{ TestRestUriString, std::move(helper), info, {} }; 484 auto manifestResult = v1_1.GetManifestByVersion("Foo", "5.0.0", ""); 485 REQUIRE(manifestResult.has_value()); 486 const Manifest& manifest = manifestResult.value(); 487 REQUIRE(manifest.Id == "Foo.Bar"); 488 REQUIRE(manifest.Version == "5.0.0"); 489 REQUIRE(manifest.DefaultLocalization.Locale == "en-us"); 490 REQUIRE(manifest.DefaultLocalization.Get<Localization::Publisher>() == "Foo"); 491 REQUIRE(manifest.DefaultLocalization.Get<Localization::PackageName>() == "Bar"); 492 REQUIRE(manifest.DefaultLocalization.Get<Localization::License>() == "Foo bar license"); 493 REQUIRE(manifest.DefaultLocalization.Get<Localization::ShortDescription>() == "Foo bar description"); 494 REQUIRE(manifest.Installers.size() == 1); 495 REQUIRE(manifest.Installers[0].Arch == Architecture::X64); 496 REQUIRE(manifest.Installers[0].Sha256 == AppInstaller::Utility::SHA256::ConvertToBytes("011048877dfaef109801b3f3ab2b60afc74f3fc4f7b3430e0c897f5da1df84b6")); 497 REQUIRE(manifest.Installers[0].BaseInstallerType == InstallerTypeEnum::Exe); 498 REQUIRE(manifest.Installers[0].Url == "https://installer.example.com/foobar.exe"); 499 } 500 501 TEST_CASE("GetManifests_GoodResponse_MSStoreType", "[RestSource][Interface_1_1]") 502 { 503 utility::string_t msstoreInstallerResponse = _XPLATSTR( 504 R"delimiter({ 505 "Data": { 506 "PackageIdentifier": "Foo.Bar", 507 "Versions": [ 508 { 509 "PackageVersion": "5.0.0", 510 "DefaultLocale": { 511 "PackageLocale": "en-us", 512 "Publisher": "Foo", 513 "PackageName": "Bar", 514 "License": "Foo bar license", 515 "ShortDescription": "Foo bar description" 516 }, 517 "Installers": [ 518 { 519 "Architecture": "x64", 520 "InstallerType": "msstore", 521 "MSStoreProductIdentifier": "9nblggh4nns1" 522 } 523 ] 524 } 525 ] 526 } 527 })delimiter"); 528 529 HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(msstoreInstallerResponse)) }; 530 Interface v1_1{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {} }; 531 std::vector<Manifest> manifests = v1_1.GetManifests("Foo.Bar"); 532 REQUIRE(manifests.size() == 1); 533 534 // Verify manifest is populated and manifest validation passed 535 Manifest manifest = manifests[0]; 536 REQUIRE(manifest.Installers.size() == 1); 537 REQUIRE(manifest.Installers.at(0).BaseInstallerType == InstallerTypeEnum::MSStore); 538 REQUIRE(manifest.Installers.at(0).ProductId == "9nblggh4nns1"); 539 } 540 541 TEST_CASE("GetManifests_GoodResponse_V1_1", "[RestSource][Interface_1_1]") 542 { 543 GoodManifest_AllFields sampleManifest; 544 utility::string_t sample = sampleManifest.GetSampleManifest_AllFields(); 545 HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) }; 546 Interface v1_1{ TestRestUriString, std::move(helper), {} }; 547 std::vector<Manifest> manifests = v1_1.GetManifests("Foo.Bar"); 548 REQUIRE(manifests.size() == 1); 549 550 // Verify manifest is populated 551 Manifest& manifest = manifests[0]; 552 REQUIRE(manifest.Id == "Foo.Bar"); 553 REQUIRE(manifest.Version == "3.0.0abc"); 554 REQUIRE(manifest.Moniker == "FooBarMoniker"); 555 REQUIRE(manifest.Channel == ""); 556 REQUIRE(manifest.ManifestVersion == AppInstaller::Manifest::ManifestVer{ "1.1.0" }); 557 sampleManifest.VerifyLocalizations_AllFields(manifest); 558 sampleManifest.VerifyInstallers_AllFields(manifest); 559 }