winget-cli

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

RestInterface_1_4.cpp (24601B)


      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_4/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_4;
     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                   "PurchaseUrl": "http://DefaultPurchaseUrl.net",
     77                   "InstallationNotes": "Default Installation Notes",
     78                   "Documentations": [{
     79                     "DocumentLabel": "Default Document Label",
     80                     "DocumentUrl": "http://DefaultDocumentUrl.net"
     81                   }]
     82                 },
     83                 "Channel": "",
     84                 "Locales": [
     85                   {
     86                     "PackageLocale": "fr-Fr",
     87                     "Publisher": "Foo French",
     88                     "PublisherUrl": "http://publisher-fr.net",
     89                     "PublisherSupportUrl": "http://publisherSupport-fr.net",
     90                     "PrivacyUrl": "http://packagePrivacyUrl-fr.net",
     91                     "Author": "FooBar French",
     92                     "PackageName": "Bar",
     93                     "PackageUrl": "http://packageUrl-fr.net",
     94                     "License": "Foo Bar License",
     95                     "LicenseUrl": "http://licenseUrl-fr.net",
     96                     "Copyright": "Foo Bar Copyright",
     97                     "CopyrightUrl": "http://copyrightUrl-fr.net",
     98                     "ShortDescription": "Foo bar is a foo bar French.",
     99                     "Description": "Foo bar is a placeholder French.",
    100                     "Tags": [
    101                       "FooBarFr",
    102                       "FooFr",
    103                       "BarFr"
    104                     ],
    105                     "ReleaseNotes": "Release notes",
    106                     "ReleaseNotesUrl": "https://ReleaseNotes.net",
    107                     "Agreements": [{
    108                       "AgreementLabel": "Label",
    109                       "Agreement": "Text",
    110                       "AgreementUrl": "https://AgreementUrl.net"
    111                     }],
    112                     "PurchaseUrl": "http://purchaseUrl.net",
    113                     "InstallationNotes": "Installation Notes",
    114                     "Documentations": [{
    115                       "DocumentLabel": "Document Label",
    116                       "DocumentUrl": "http://documentUrl.net"
    117                     }]
    118                   }
    119                 ],
    120                 "Installers": [
    121                   {
    122                     "InstallerSha256": "011048877dfaef109801b3f3ab2b60afc74f3fc4f7b3430e0c897f5da1df84b6",
    123                     "InstallerUrl": "http://foobar.zip",
    124                     "Architecture": "x86",
    125                     "InstallerLocale": "en-US",
    126                     "Platform": [
    127                       "Windows.Desktop"
    128                     ],
    129                     "MinimumOSVersion": "1078",
    130                     "InstallerType": "zip",
    131                     "Scope": "user",
    132                     "InstallModes": [
    133                       "interactive"
    134                     ],
    135                     "InstallerSwitches": {
    136                       "Silent": "/s",
    137                       "SilentWithProgress": "/s",
    138                       "Interactive": "/i",
    139                       "InstallLocation": "C:\\Users\\User1",
    140                       "Log": "/l",
    141                       "Upgrade": "/u",
    142                       "Custom": "/custom"
    143                     },
    144                     "InstallerSuccessCodes": [
    145                       0
    146                     ],
    147                     "UpgradeBehavior": "install",
    148                     "Commands": [
    149                       "command1"
    150                     ],
    151                     "Protocols": [
    152                        "protocol1"
    153                     ],
    154                     "FileExtensions": [
    155                       ".file-extension"
    156                     ],
    157                     "Dependencies": {
    158                       "WindowsFeatures": [
    159                         "feature1"
    160                       ],
    161                       "WindowsLibraries": [
    162                         "library1"
    163                       ],
    164                       "PackageDependencies": [
    165                         {
    166                           "PackageIdentifier": "Foo.Baz",
    167                           "MinimumVersion": "2.0.0"
    168                         }
    169                       ],
    170                       "ExternalDependencies": [
    171                         "FooBarBaz"
    172                       ]
    173                     },
    174                     "ProductCode": "5b6e0f8a-3bbf-4a17-aefd-024c2b3e075d",
    175                     "ReleaseDate": "2021-01-01",
    176                     "InstallerAbortsTerminal": true,
    177                     "InstallLocationRequired": true,
    178                     "RequireExplicitUpgrade": true,
    179                     "UnsupportedOSArchitectures": [ "arm" ],
    180                     "ElevationRequirement": "elevatesSelf",
    181                     "AppsAndFeaturesEntries": [{
    182                       "DisplayName": "DisplayName",
    183                       "DisplayVersion": "DisplayVersion",
    184                       "Publisher": "Publisher",
    185                       "ProductCode": "ProductCode",
    186                       "UpgradeCode": "UpgradeCode",
    187                       "InstallerType": "exe"
    188                     }],
    189                     "Markets" : {
    190                       "AllowedMarkets": [ "US" ]
    191                     },
    192                     "ExpectedReturnCodes": [{
    193                       "InstallerReturnCode": 3,
    194                       "ReturnResponse": "custom",
    195                       "ReturnResponseUrl": "http://returnResponseUrl.net"
    196                     }],
    197                     "NestedInstallerType": "portable",
    198                     "DisplayInstallWarnings": true,
    199                     "UnsupportedArguments": [ "log" ],
    200                     "NestedInstallerFiles": [{
    201                       "RelativeFilePath": "test\\app.exe",
    202                       "PortableCommandAlias": "test.exe"
    203                     }],
    204                     "InstallationMetadata": {
    205                       "DefaultInstallLocation": "%TEMP%\\DefaultInstallLocation",
    206                       "Files": [{
    207                         "RelativeFilePath": "test\\app.exe",
    208                         "FileSha256": "011048877dfaef109801b3f3ab2b60afc74f3fc4f7b3430e0c897f5da1df84b6",
    209                         "FileType": "launch",
    210                         "InvocationParameter": "/parameter",
    211                         "DisplayName": "test"
    212                       }]
    213                     }
    214                   }
    215                 ]
    216               }
    217             ]
    218           },
    219           "ContinuationToken": "abcd"
    220         })delimiter");
    221         }
    222 
    223         void VerifyLocalizations_AllFields(const Manifest& manifest)
    224         {
    225             REQUIRE(manifest.DefaultLocalization.Locale == "en-US");
    226             REQUIRE(manifest.DefaultLocalization.Get<Localization::Publisher>() == "Foo");
    227             REQUIRE(manifest.DefaultLocalization.Get<Localization::PublisherUrl>() == "http://publisher.net");
    228             REQUIRE(manifest.DefaultLocalization.Get<Localization::PublisherSupportUrl>() == "http://publisherSupport.net");
    229             REQUIRE(manifest.DefaultLocalization.Get<Localization::PrivacyUrl>() == "http://packagePrivacyUrl.net");
    230             REQUIRE(manifest.DefaultLocalization.Get<Localization::Author>() == "FooBar");
    231             REQUIRE(manifest.DefaultLocalization.Get<Localization::PackageName>() == "Bar");
    232             REQUIRE(manifest.DefaultLocalization.Get<Localization::PackageUrl>() == "http://packageUrl.net");
    233             REQUIRE(manifest.DefaultLocalization.Get<Localization::License>() == "Foo Bar License");
    234             REQUIRE(manifest.DefaultLocalization.Get<Localization::LicenseUrl>() == "http://licenseUrl.net");
    235             REQUIRE(manifest.DefaultLocalization.Get<Localization::Copyright>() == "Foo Bar Copyright");
    236             REQUIRE(manifest.DefaultLocalization.Get<Localization::CopyrightUrl>() == "http://copyrightUrl.net");
    237             REQUIRE(manifest.DefaultLocalization.Get<Localization::ShortDescription>() == "Foo bar is a foo bar.");
    238             REQUIRE(manifest.DefaultLocalization.Get<Localization::Description>() == "Foo bar is a placeholder.");
    239             REQUIRE(manifest.DefaultLocalization.Get<Localization::Tags>().size() == 3);
    240             REQUIRE(manifest.DefaultLocalization.Get<Localization::Tags>().at(0) == "FooBar");
    241             REQUIRE(manifest.DefaultLocalization.Get<Localization::Tags>().at(1) == "Foo");
    242             REQUIRE(manifest.DefaultLocalization.Get<Localization::Tags>().at(2) == "Bar");
    243             REQUIRE(manifest.DefaultLocalization.Get<Localization::ReleaseNotes>() == "Default release notes");
    244             REQUIRE(manifest.DefaultLocalization.Get<Localization::ReleaseNotesUrl>() == "https://DefaultReleaseNotes.net");
    245             REQUIRE(manifest.DefaultLocalization.Get<Localization::Agreements>().size() == 1);
    246             REQUIRE(manifest.DefaultLocalization.Get<Localization::Agreements>().at(0).Label == "DefaultLabel");
    247             REQUIRE(manifest.DefaultLocalization.Get<Localization::Agreements>().at(0).AgreementText == "DefaultText");
    248             REQUIRE(manifest.DefaultLocalization.Get<Localization::Agreements>().at(0).AgreementUrl == "https://DefaultAgreementUrl.net");
    249             REQUIRE(manifest.DefaultLocalization.Get<Localization::PurchaseUrl>() == "http://DefaultPurchaseUrl.net");
    250             REQUIRE(manifest.DefaultLocalization.Get<Localization::InstallationNotes>() == "Default Installation Notes");
    251             REQUIRE(manifest.DefaultLocalization.Get<Localization::Documentations>().size() == 1);
    252             REQUIRE(manifest.DefaultLocalization.Get<Localization::Documentations>().at(0).DocumentLabel == "Default Document Label");
    253             REQUIRE(manifest.DefaultLocalization.Get<Localization::Documentations>().at(0).DocumentUrl == "http://DefaultDocumentUrl.net");
    254 
    255             REQUIRE(manifest.Localizations.size() == 1);
    256             ManifestLocalization frenchLocalization = manifest.Localizations.at(0);
    257             REQUIRE(frenchLocalization.Locale == "fr-Fr");
    258             REQUIRE(frenchLocalization.Get<Localization::Publisher>() == "Foo French");
    259             REQUIRE(frenchLocalization.Get<Localization::PublisherUrl>() == "http://publisher-fr.net");
    260             REQUIRE(frenchLocalization.Get<Localization::PublisherSupportUrl>() == "http://publisherSupport-fr.net");
    261             REQUIRE(frenchLocalization.Get<Localization::PrivacyUrl>() == "http://packagePrivacyUrl-fr.net");
    262             REQUIRE(frenchLocalization.Get<Localization::Author>() == "FooBar French");
    263             REQUIRE(frenchLocalization.Get<Localization::PackageName>() == "Bar");
    264             REQUIRE(frenchLocalization.Get<Localization::PackageUrl>() == "http://packageUrl-fr.net");
    265             REQUIRE(frenchLocalization.Get<Localization::License>() == "Foo Bar License");
    266             REQUIRE(frenchLocalization.Get<Localization::LicenseUrl>() == "http://licenseUrl-fr.net");
    267             REQUIRE(frenchLocalization.Get<Localization::Copyright>() == "Foo Bar Copyright");
    268             REQUIRE(frenchLocalization.Get<Localization::CopyrightUrl>() == "http://copyrightUrl-fr.net");
    269             REQUIRE(frenchLocalization.Get<Localization::ShortDescription>() == "Foo bar is a foo bar French.");
    270             REQUIRE(frenchLocalization.Get<Localization::Description>() == "Foo bar is a placeholder French.");
    271             REQUIRE(frenchLocalization.Get<Localization::Tags>().size() == 3);
    272             REQUIRE(frenchLocalization.Get<Localization::Tags>().at(0) == "FooBarFr");
    273             REQUIRE(frenchLocalization.Get<Localization::Tags>().at(1) == "FooFr");
    274             REQUIRE(frenchLocalization.Get<Localization::Tags>().at(2) == "BarFr");
    275             REQUIRE(frenchLocalization.Get<Localization::ReleaseNotes>() == "Release notes");
    276             REQUIRE(frenchLocalization.Get<Localization::ReleaseNotesUrl>() == "https://ReleaseNotes.net");
    277             REQUIRE(frenchLocalization.Get<Localization::Agreements>().size() == 1);
    278             REQUIRE(frenchLocalization.Get<Localization::Agreements>().at(0).Label == "Label");
    279             REQUIRE(frenchLocalization.Get<Localization::Agreements>().at(0).AgreementText == "Text");
    280             REQUIRE(frenchLocalization.Get<Localization::Agreements>().at(0).AgreementUrl == "https://AgreementUrl.net");
    281             REQUIRE(frenchLocalization.Get<Localization::PurchaseUrl>() == "http://purchaseUrl.net");
    282             REQUIRE(frenchLocalization.Get<Localization::InstallationNotes>() == "Installation Notes");
    283             REQUIRE(frenchLocalization.Get<Localization::Documentations>().size() == 1);
    284             REQUIRE(frenchLocalization.Get<Localization::Documentations>().at(0).DocumentLabel == "Document Label");
    285             REQUIRE(frenchLocalization.Get<Localization::Documentations>().at(0).DocumentUrl == "http://documentUrl.net");
    286         }
    287 
    288         void VerifyInstallers_AllFields(const Manifest& manifest)
    289         {
    290             REQUIRE(manifest.Installers.size() == 1);
    291 
    292             ManifestInstaller actualInstaller = manifest.Installers.at(0);
    293             REQUIRE(actualInstaller.Sha256 == AppInstaller::Utility::SHA256::ConvertToBytes("011048877dfaef109801b3f3ab2b60afc74f3fc4f7b3430e0c897f5da1df84b6"));
    294             REQUIRE(actualInstaller.Url == "http://foobar.zip");
    295             REQUIRE(actualInstaller.Arch == Architecture::X86);
    296             REQUIRE(actualInstaller.Locale == "en-US");
    297             REQUIRE(actualInstaller.Platform.size() == 1);
    298             REQUIRE(actualInstaller.Platform[0] == PlatformEnum::Desktop);
    299             REQUIRE(actualInstaller.MinOSVersion == "1078");
    300             REQUIRE(actualInstaller.BaseInstallerType == InstallerTypeEnum::Zip);
    301             REQUIRE(actualInstaller.Scope == ScopeEnum::User);
    302             REQUIRE(actualInstaller.InstallModes.size() == 1);
    303             REQUIRE(actualInstaller.InstallModes.at(0) == InstallModeEnum::Interactive);
    304             REQUIRE(actualInstaller.Switches.size() == 7);
    305             REQUIRE(actualInstaller.Switches.at(InstallerSwitchType::Silent) == "/s");
    306             REQUIRE(actualInstaller.Switches.at(InstallerSwitchType::SilentWithProgress) == "/s");
    307             REQUIRE(actualInstaller.Switches.at(InstallerSwitchType::Interactive) == "/i");
    308             REQUIRE(actualInstaller.Switches.at(InstallerSwitchType::InstallLocation) == "C:\\Users\\User1");
    309             REQUIRE(actualInstaller.Switches.at(InstallerSwitchType::Log) == "/l");
    310             REQUIRE(actualInstaller.Switches.at(InstallerSwitchType::Update) == "/u");
    311             REQUIRE(actualInstaller.Switches.at(InstallerSwitchType::Custom) == "/custom");
    312             REQUIRE(actualInstaller.InstallerSuccessCodes.size() == 1);
    313             REQUIRE(actualInstaller.InstallerSuccessCodes.at(0) == 0);
    314             REQUIRE(actualInstaller.UpdateBehavior == UpdateBehaviorEnum::Install);
    315             REQUIRE(actualInstaller.Commands.at(0) == "command1");
    316             REQUIRE(actualInstaller.Protocols.at(0) == "protocol1");
    317             REQUIRE(actualInstaller.FileExtensions.at(0) == ".file-extension");
    318             REQUIRE(actualInstaller.Dependencies.HasExactDependency(DependencyType::WindowsFeature, "feature1"));
    319             REQUIRE(actualInstaller.Dependencies.HasExactDependency(DependencyType::WindowsLibrary, "library1"));
    320             REQUIRE(actualInstaller.Dependencies.HasExactDependency(DependencyType::Package, "Foo.Baz", "2.0.0"));
    321             REQUIRE(actualInstaller.Dependencies.HasExactDependency(DependencyType::External, "FooBarBaz"));
    322             REQUIRE(actualInstaller.PackageFamilyName == "");
    323             REQUIRE(actualInstaller.ProductCode == "5b6e0f8a-3bbf-4a17-aefd-024c2b3e075d");
    324             REQUIRE(actualInstaller.ReleaseDate == "2021-01-01");
    325             REQUIRE(actualInstaller.InstallerAbortsTerminal);
    326             REQUIRE(actualInstaller.InstallLocationRequired);
    327             REQUIRE(actualInstaller.RequireExplicitUpgrade);
    328             REQUIRE(actualInstaller.ElevationRequirement == ElevationRequirementEnum::ElevatesSelf);
    329             REQUIRE(actualInstaller.UnsupportedOSArchitectures.size() == 1);
    330             REQUIRE(actualInstaller.UnsupportedOSArchitectures.at(0) == Architecture::Arm);
    331             REQUIRE(actualInstaller.AppsAndFeaturesEntries.size() == 1);
    332             REQUIRE(actualInstaller.AppsAndFeaturesEntries.at(0).DisplayName == "DisplayName");
    333             REQUIRE(actualInstaller.AppsAndFeaturesEntries.at(0).DisplayVersion == "DisplayVersion");
    334             REQUIRE(actualInstaller.AppsAndFeaturesEntries.at(0).Publisher == "Publisher");
    335             REQUIRE(actualInstaller.AppsAndFeaturesEntries.at(0).ProductCode == "ProductCode");
    336             REQUIRE(actualInstaller.AppsAndFeaturesEntries.at(0).UpgradeCode == "UpgradeCode");
    337             REQUIRE(actualInstaller.AppsAndFeaturesEntries.at(0).InstallerType == InstallerTypeEnum::Exe);
    338             REQUIRE(actualInstaller.Markets.AllowedMarkets.size() == 1);
    339             REQUIRE(actualInstaller.Markets.AllowedMarkets.at(0) == "US");
    340             REQUIRE(actualInstaller.ExpectedReturnCodes.at(3).ReturnResponseEnum == ExpectedReturnCodeEnum::Custom);
    341             REQUIRE(actualInstaller.ExpectedReturnCodes.at(3).ReturnResponseUrl == "http://returnResponseUrl.net");
    342             REQUIRE(actualInstaller.NestedInstallerType == InstallerTypeEnum::Portable);
    343             REQUIRE(actualInstaller.DisplayInstallWarnings);
    344             REQUIRE(actualInstaller.UnsupportedArguments.size() == 1);
    345             REQUIRE(actualInstaller.UnsupportedArguments.at(0) == UnsupportedArgumentEnum::Log);
    346             REQUIRE(actualInstaller.NestedInstallerFiles.size() == 1);
    347             REQUIRE(actualInstaller.NestedInstallerFiles.at(0).RelativeFilePath == "test\\app.exe");
    348             REQUIRE(actualInstaller.NestedInstallerFiles.at(0).PortableCommandAlias == "test.exe");
    349             REQUIRE(actualInstaller.InstallationMetadata.DefaultInstallLocation == "%TEMP%\\DefaultInstallLocation");
    350             REQUIRE(actualInstaller.InstallationMetadata.Files.size() == 1);
    351             REQUIRE(actualInstaller.InstallationMetadata.Files.at(0).RelativeFilePath == "test\\app.exe");
    352             REQUIRE(actualInstaller.InstallationMetadata.Files.at(0).FileType == InstalledFileTypeEnum::Launch);
    353             REQUIRE(actualInstaller.InstallationMetadata.Files.at(0).FileSha256 == AppInstaller::Utility::SHA256::ConvertToBytes("011048877dfaef109801b3f3ab2b60afc74f3fc4f7b3430e0c897f5da1df84b6"));
    354             REQUIRE(actualInstaller.InstallationMetadata.Files.at(0).InvocationParameter == "/parameter");
    355             REQUIRE(actualInstaller.InstallationMetadata.Files.at(0).DisplayName == "test");
    356         }
    357     };
    358 }
    359 
    360 TEST_CASE("GetManifests_GoodResponse_V1_4", "[RestSource][Interface_1_4]")
    361 {
    362     GoodManifest_AllFields sampleManifest;
    363     utility::string_t sample = sampleManifest.GetSampleManifest_AllFields();
    364     HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) };
    365     Interface v1_4{ TestRestUriString, std::move(helper), {} };
    366     std::vector<Manifest> manifests = v1_4.GetManifests("Foo.Bar");
    367     REQUIRE(manifests.size() == 1);
    368 
    369     // Verify manifest is populated
    370     Manifest& manifest = manifests[0];
    371     REQUIRE(manifest.Id == "Foo.Bar");
    372     REQUIRE(manifest.Version == "3.0.0abc");
    373     REQUIRE(manifest.Moniker == "FooBarMoniker");
    374     REQUIRE(manifest.Channel == "");
    375     REQUIRE(manifest.ManifestVersion == AppInstaller::Manifest::ManifestVer{ "1.4.0" });
    376     sampleManifest.VerifyLocalizations_AllFields(manifest);
    377     sampleManifest.VerifyInstallers_AllFields(manifest);
    378 }
    379 
    380 TEST_CASE("Search_GoodResponse_V1_4", "[RestSource][Interface_1_4]")
    381 {
    382     utility::string_t sample = _XPLATSTR(
    383         R"delimiter({
    384             "Data" : [{
    385               "PackageIdentifier": "git.package",
    386               "PackageName": "package",
    387               "Publisher": "git",
    388               "Versions": [{
    389                 "PackageVersion": "1.0.0",
    390                 "PackageFamilyNames": [
    391                     "pfn1"
    392                 ],
    393                 "ProductCodes": [
    394                     "pc1"
    395                 ],
    396                 "UpgradeCodes": [
    397                     "upgradeCode"
    398                 ],
    399                 "AppsAndFeaturesEntryVersions": [
    400                     "2.0",
    401                     "1.0"
    402                 ]
    403               }]
    404             }]
    405         })delimiter");
    406 
    407     HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) };
    408     Interface v1_4{ TestRestUriString, std::move(helper), {} };
    409     Schema::IRestClient::SearchResult searchResponse = v1_4.Search({});
    410     REQUIRE(searchResponse.Matches.size() == 1);
    411     Schema::IRestClient::Package package = searchResponse.Matches.at(0);
    412     REQUIRE(package.PackageInformation.PackageIdentifier.compare("git.package") == 0);
    413     REQUIRE(package.PackageInformation.Publisher.compare("git") == 0);
    414     REQUIRE(package.PackageInformation.PackageName.compare("package") == 0);
    415     REQUIRE(package.Versions.size() == 1);
    416     REQUIRE(package.Versions.at(0).VersionAndChannel.GetVersion().ToString().compare("1.0.0") == 0);
    417     REQUIRE(package.Versions.at(0).PackageFamilyNames.size() == 1);
    418     REQUIRE(package.Versions.at(0).PackageFamilyNames.at(0) == "pfn1");
    419     REQUIRE(package.Versions.at(0).ProductCodes.size() == 1);
    420     REQUIRE(package.Versions.at(0).ProductCodes.at(0) == "pc1");
    421     REQUIRE(package.Versions.at(0).UpgradeCodes.size() == 1);
    422     REQUIRE(package.Versions.at(0).UpgradeCodes.at(0) == "upgradeCode");
    423     REQUIRE(package.Versions.at(0).ArpVersions.size() == 2);
    424     REQUIRE(package.Versions.at(0).ArpVersions.at(0).ToString() == "1.0");
    425     REQUIRE(package.Versions.at(0).ArpVersions.at(1).ToString() == "2.0");
    426 }