winget-cli

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

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 }