winget-cli

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

RestInterface_1_7.cpp (34342B)


      1 // Copyright (c) Microsoft Corporation.
      2 // Licensed under the MIT License.
      3 #include "pch.h"
      4 #include "TestCommon.h"
      5 #include "TestHooks.h"
      6 #include "TestRestRequestHandler.h"
      7 #include <Rest/Schema/1_7/Interface.h>
      8 #include <Rest/Schema/IRestClient.h>
      9 #include <AppInstallerVersions.h>
     10 #include <AppInstallerErrors.h>
     11 #include <winget/Authentication.h>
     12 #include <winget/JsonUtil.h>
     13 
     14 using namespace TestCommon;
     15 using namespace AppInstaller;
     16 using namespace AppInstaller::Authentication;
     17 using namespace AppInstaller::Http;
     18 using namespace AppInstaller::Utility;
     19 using namespace AppInstaller::Manifest;
     20 using namespace AppInstaller::Repository;
     21 using namespace AppInstaller::Repository::Rest;
     22 using namespace AppInstaller::Repository::Rest::Schema;
     23 using namespace AppInstaller::Repository::Rest::Schema::V1_7;
     24 
     25 namespace
     26 {
     27     const std::string TestRestUriString = "http://restsource.com/api";
     28 
     29     IRestClient::Information GetTestSourceInformation()
     30     {
     31         IRestClient::Information result;
     32 
     33         result.Authentication.Type = AuthenticationType::MicrosoftEntraId;
     34         MicrosoftEntraIdAuthenticationInfo microsoftEntraIdInfo;
     35         microsoftEntraIdInfo.Resource = "GUID";
     36         result.Authentication.MicrosoftEntraIdInfo = std::move(microsoftEntraIdInfo);
     37 
     38         return result;
     39     }
     40 
     41     AuthenticationArguments GetTestAuthenticationArguments()
     42     {
     43         AuthenticationArguments result;
     44         result.Mode = AuthenticationMode::Silent;
     45         return result;
     46     }
     47 
     48     utility::string_t SampleSearchResponse = _XPLATSTR(
     49         R"delimiter({
     50             "Data" : [
     51                {
     52               "PackageIdentifier": "git.package",
     53               "PackageName": "package",
     54               "Publisher": "git",
     55               "Versions": [
     56                 {   "PackageVersion": "1.0.0" }]
     57             }]
     58         })delimiter");
     59 
     60     utility::string_t SampleGetManifestResponse = _XPLATSTR(
     61         R"delimiter({
     62         "Data": {
     63             "PackageIdentifier": "Foo.Bar",
     64             "Versions": [
     65                 {
     66                     "PackageVersion": "5.0.0",
     67                     "DefaultLocale": {
     68                         "PackageLocale": "en-us",
     69                         "Publisher": "Foo",
     70                         "PackageName": "Bar",
     71                         "License": "Foo bar license",
     72                         "ShortDescription": "Foo bar description"
     73                     },
     74                     "Installers": [
     75                         {
     76                             "Architecture": "x64",
     77                             "InstallerSha256": "011048877dfaef109801b3f3ab2b60afc74f3fc4f7b3430e0c897f5da1df84b6",
     78                             "InstallerType": "exe",
     79                             "InstallerUrl": "https://installer.example.com/foobar.exe"
     80                         }
     81                     ]
     82                 }
     83             ]
     84         }
     85     })delimiter");
     86 
     87     struct GoodManifest_AllFields
     88     {
     89         utility::string_t GetSampleManifest_AllFields()
     90         {
     91             return _XPLATSTR(
     92                 R"delimiter(
     93         {
     94           "Data": {
     95             "PackageIdentifier": "Foo.Bar",
     96             "Versions": [
     97               {
     98                 "PackageVersion": "3.0.0abc",
     99                 "DefaultLocale": {
    100                   "PackageLocale": "en-US",
    101                   "Publisher": "Foo",
    102                   "PublisherUrl": "http://publisher.net",
    103                   "PublisherSupportUrl": "http://publisherSupport.net",
    104                   "PrivacyUrl": "http://packagePrivacyUrl.net",
    105                   "Author": "FooBar",
    106                   "PackageName": "Bar",
    107                   "PackageUrl": "http://packageUrl.net",
    108                   "License": "Foo Bar License",
    109                   "LicenseUrl": "http://licenseUrl.net",
    110                   "Copyright": "Foo Bar Copyright",
    111                   "CopyrightUrl": "http://copyrightUrl.net",
    112                   "ShortDescription": "Foo bar is a foo bar.",
    113                   "Description": "Foo bar is a placeholder.",
    114                   "Tags": [
    115                     "FooBar",
    116                     "Foo",
    117                     "Bar"
    118                   ],
    119                   "Moniker": "FooBarMoniker",
    120                   "ReleaseNotes": "Default release notes",
    121                   "ReleaseNotesUrl": "https://DefaultReleaseNotes.net",
    122                   "Agreements": [{
    123                     "AgreementLabel": "DefaultLabel",
    124                     "Agreement": "DefaultText",
    125                     "AgreementUrl": "https://DefaultAgreementUrl.net"
    126                   }],
    127                   "PurchaseUrl": "http://DefaultPurchaseUrl.net",
    128                   "InstallationNotes": "Default Installation Notes",
    129                   "Documentations": [{
    130                     "DocumentLabel": "Default Document Label",
    131                     "DocumentUrl": "http://DefaultDocumentUrl.net"
    132                   }],
    133                   "Icons": [{
    134                     "IconUrl": "https://DefaultTestIcon",
    135                     "IconFileType": "ico",
    136                     "IconResolution": "custom",
    137                     "IconTheme": "default",
    138                     "IconSha256": "69D84CA8899800A5575CE31798293CD4FEBAB1D734A07C2E51E56A28E0DF8123"
    139                   }]
    140                 },
    141                 "Channel": "",
    142                 "Locales": [
    143                   {
    144                     "PackageLocale": "fr-Fr",
    145                     "Publisher": "Foo French",
    146                     "PublisherUrl": "http://publisher-fr.net",
    147                     "PublisherSupportUrl": "http://publisherSupport-fr.net",
    148                     "PrivacyUrl": "http://packagePrivacyUrl-fr.net",
    149                     "Author": "FooBar French",
    150                     "PackageName": "Bar",
    151                     "PackageUrl": "http://packageUrl-fr.net",
    152                     "License": "Foo Bar License",
    153                     "LicenseUrl": "http://licenseUrl-fr.net",
    154                     "Copyright": "Foo Bar Copyright",
    155                     "CopyrightUrl": "http://copyrightUrl-fr.net",
    156                     "ShortDescription": "Foo bar is a foo bar French.",
    157                     "Description": "Foo bar is a placeholder French.",
    158                     "Tags": [
    159                       "FooBarFr",
    160                       "FooFr",
    161                       "BarFr"
    162                     ],
    163                     "ReleaseNotes": "Release notes",
    164                     "ReleaseNotesUrl": "https://ReleaseNotes.net",
    165                     "Agreements": [{
    166                       "AgreementLabel": "Label",
    167                       "Agreement": "Text",
    168                       "AgreementUrl": "https://AgreementUrl.net"
    169                     }],
    170                     "PurchaseUrl": "http://purchaseUrl.net",
    171                     "InstallationNotes": "Installation Notes",
    172                     "Documentations": [{
    173                       "DocumentLabel": "Document Label",
    174                       "DocumentUrl": "http://documentUrl.net"
    175                     }],
    176                     "Icons": [{
    177                       "IconUrl": "https://testIcon",
    178                       "IconFileType": "png",
    179                       "IconResolution": "32x32",
    180                       "IconTheme": "light",
    181                       "IconSha256": "69D84CA8899800A5575CE31798293CD4FEBAB1D734A07C2E51E56A28E0DF8321"
    182                     }]
    183                   }
    184                 ],)delimiter") _XPLATSTR(R"delimiter(
    185                 "Installers": [
    186                   {
    187                     "InstallerSha256": "011048877dfaef109801b3f3ab2b60afc74f3fc4f7b3430e0c897f5da1df84b6",
    188                     "InstallerUrl": "http://foobar.zip",
    189                     "Architecture": "x86",
    190                     "InstallerLocale": "en-US",
    191                     "Platform": [
    192                       "Windows.Desktop"
    193                     ],
    194                     "MinimumOSVersion": "1078",
    195                     "InstallerType": "zip",
    196                     "Scope": "user",
    197                     "InstallModes": [
    198                       "interactive"
    199                     ],
    200                     "InstallerSwitches": {
    201                       "Silent": "/s",
    202                       "SilentWithProgress": "/s",
    203                       "Interactive": "/i",
    204                       "InstallLocation": "C:\\Users\\User1",
    205                       "Log": "/l",
    206                       "Upgrade": "/u",
    207                       "Custom": "/custom",
    208                       "Repair": "/repair"
    209                     },
    210                     "InstallerSuccessCodes": [
    211                       0
    212                     ],
    213                     "UpgradeBehavior": "deny",
    214                     "Commands": [
    215                       "command1"
    216                     ],
    217                     "Protocols": [
    218                        "protocol1"
    219                     ],
    220                     "FileExtensions": [
    221                       ".file-extension"
    222                     ],
    223                     "Dependencies": {
    224                       "WindowsFeatures": [
    225                         "feature1"
    226                       ],
    227                       "WindowsLibraries": [
    228                         "library1"
    229                       ],
    230                       "PackageDependencies": [
    231                         {
    232                           "PackageIdentifier": "Foo.Baz",
    233                           "MinimumVersion": "2.0.0"
    234                         }
    235                       ],
    236                       "ExternalDependencies": [
    237                         "FooBarBaz"
    238                       ]
    239                     },
    240                     "ProductCode": "5b6e0f8a-3bbf-4a17-aefd-024c2b3e075d",
    241                     "ReleaseDate": "2021-01-01",
    242                     "InstallerAbortsTerminal": true,
    243                     "InstallLocationRequired": true,
    244                     "RequireExplicitUpgrade": true,
    245                     "UnsupportedOSArchitectures": [ "arm" ],
    246                     "ElevationRequirement": "elevatesSelf",
    247                     "AppsAndFeaturesEntries": [{
    248                       "DisplayName": "DisplayName",
    249                       "DisplayVersion": "DisplayVersion",
    250                       "Publisher": "Publisher",
    251                       "ProductCode": "ProductCode",
    252                       "UpgradeCode": "UpgradeCode",
    253                       "InstallerType": "exe"
    254                     }],
    255                     "Markets" : {
    256                       "AllowedMarkets": [ "US" ]
    257                     },
    258                     "ExpectedReturnCodes": [{
    259                       "InstallerReturnCode": 3,
    260                       "ReturnResponse": "custom",
    261                       "ReturnResponseUrl": "http://returnResponseUrl.net"
    262                     }],
    263                     "NestedInstallerType": "portable",
    264                     "DisplayInstallWarnings": true,
    265                     "UnsupportedArguments": [ "log" ],
    266                     "NestedInstallerFiles": [{
    267                       "RelativeFilePath": "test\\app.exe",
    268                       "PortableCommandAlias": "test.exe"
    269                     }],
    270                     "InstallationMetadata": {
    271                       "DefaultInstallLocation": "%TEMP%\\DefaultInstallLocation",
    272                       "Files": [{
    273                         "RelativeFilePath": "test\\app.exe",
    274                         "FileSha256": "011048877dfaef109801b3f3ab2b60afc74f3fc4f7b3430e0c897f5da1df84b6",
    275                         "FileType": "launch",
    276                         "InvocationParameter": "/parameter",
    277                         "DisplayName": "test"
    278                       }]
    279                     },
    280                     "DownloadCommandProhibited": true,
    281                     "RepairBehavior": "uninstaller"
    282                   }
    283                 ]
    284               }
    285             ]
    286           },
    287           "ContinuationToken": "abcd"
    288         })delimiter");
    289         }
    290 
    291         void VerifyLocalizations_AllFields(const AppInstaller::Manifest::Manifest& manifest)
    292         {
    293             REQUIRE(manifest.DefaultLocalization.Locale == "en-US");
    294             REQUIRE(manifest.DefaultLocalization.Get<Localization::Publisher>() == "Foo");
    295             REQUIRE(manifest.DefaultLocalization.Get<Localization::PublisherUrl>() == "http://publisher.net");
    296             REQUIRE(manifest.DefaultLocalization.Get<Localization::PublisherSupportUrl>() == "http://publisherSupport.net");
    297             REQUIRE(manifest.DefaultLocalization.Get<Localization::PrivacyUrl>() == "http://packagePrivacyUrl.net");
    298             REQUIRE(manifest.DefaultLocalization.Get<Localization::Author>() == "FooBar");
    299             REQUIRE(manifest.DefaultLocalization.Get<Localization::PackageName>() == "Bar");
    300             REQUIRE(manifest.DefaultLocalization.Get<Localization::PackageUrl>() == "http://packageUrl.net");
    301             REQUIRE(manifest.DefaultLocalization.Get<Localization::License>() == "Foo Bar License");
    302             REQUIRE(manifest.DefaultLocalization.Get<Localization::LicenseUrl>() == "http://licenseUrl.net");
    303             REQUIRE(manifest.DefaultLocalization.Get<Localization::Copyright>() == "Foo Bar Copyright");
    304             REQUIRE(manifest.DefaultLocalization.Get<Localization::CopyrightUrl>() == "http://copyrightUrl.net");
    305             REQUIRE(manifest.DefaultLocalization.Get<Localization::ShortDescription>() == "Foo bar is a foo bar.");
    306             REQUIRE(manifest.DefaultLocalization.Get<Localization::Description>() == "Foo bar is a placeholder.");
    307             REQUIRE(manifest.DefaultLocalization.Get<Localization::Tags>().size() == 3);
    308             REQUIRE(manifest.DefaultLocalization.Get<Localization::Tags>().at(0) == "FooBar");
    309             REQUIRE(manifest.DefaultLocalization.Get<Localization::Tags>().at(1) == "Foo");
    310             REQUIRE(manifest.DefaultLocalization.Get<Localization::Tags>().at(2) == "Bar");
    311             REQUIRE(manifest.DefaultLocalization.Get<Localization::ReleaseNotes>() == "Default release notes");
    312             REQUIRE(manifest.DefaultLocalization.Get<Localization::ReleaseNotesUrl>() == "https://DefaultReleaseNotes.net");
    313             REQUIRE(manifest.DefaultLocalization.Get<Localization::Agreements>().size() == 1);
    314             REQUIRE(manifest.DefaultLocalization.Get<Localization::Agreements>().at(0).Label == "DefaultLabel");
    315             REQUIRE(manifest.DefaultLocalization.Get<Localization::Agreements>().at(0).AgreementText == "DefaultText");
    316             REQUIRE(manifest.DefaultLocalization.Get<Localization::Agreements>().at(0).AgreementUrl == "https://DefaultAgreementUrl.net");
    317             REQUIRE(manifest.DefaultLocalization.Get<Localization::PurchaseUrl>() == "http://DefaultPurchaseUrl.net");
    318             REQUIRE(manifest.DefaultLocalization.Get<Localization::InstallationNotes>() == "Default Installation Notes");
    319             REQUIRE(manifest.DefaultLocalization.Get<Localization::Documentations>().size() == 1);
    320             REQUIRE(manifest.DefaultLocalization.Get<Localization::Documentations>().at(0).DocumentLabel == "Default Document Label");
    321             REQUIRE(manifest.DefaultLocalization.Get<Localization::Documentations>().at(0).DocumentUrl == "http://DefaultDocumentUrl.net");
    322             REQUIRE(manifest.DefaultLocalization.Get<Localization::Icons>().size() == 1);
    323             REQUIRE(manifest.DefaultLocalization.Get<Localization::Icons>().at(0).Url == "https://DefaultTestIcon");
    324             REQUIRE(manifest.DefaultLocalization.Get<Localization::Icons>().at(0).FileType == IconFileTypeEnum::Ico);
    325             REQUIRE(manifest.DefaultLocalization.Get<Localization::Icons>().at(0).Resolution == IconResolutionEnum::Custom);
    326             REQUIRE(manifest.DefaultLocalization.Get<Localization::Icons>().at(0).Theme == IconThemeEnum::Default);
    327             REQUIRE(manifest.DefaultLocalization.Get<Localization::Icons>().at(0).Sha256 == AppInstaller::Utility::SHA256::ConvertToBytes("69D84CA8899800A5575CE31798293CD4FEBAB1D734A07C2E51E56A28E0DF8123"));
    328 
    329             REQUIRE(manifest.Localizations.size() == 1);
    330             ManifestLocalization frenchLocalization = manifest.Localizations.at(0);
    331             REQUIRE(frenchLocalization.Locale == "fr-Fr");
    332             REQUIRE(frenchLocalization.Get<Localization::Publisher>() == "Foo French");
    333             REQUIRE(frenchLocalization.Get<Localization::PublisherUrl>() == "http://publisher-fr.net");
    334             REQUIRE(frenchLocalization.Get<Localization::PublisherSupportUrl>() == "http://publisherSupport-fr.net");
    335             REQUIRE(frenchLocalization.Get<Localization::PrivacyUrl>() == "http://packagePrivacyUrl-fr.net");
    336             REQUIRE(frenchLocalization.Get<Localization::Author>() == "FooBar French");
    337             REQUIRE(frenchLocalization.Get<Localization::PackageName>() == "Bar");
    338             REQUIRE(frenchLocalization.Get<Localization::PackageUrl>() == "http://packageUrl-fr.net");
    339             REQUIRE(frenchLocalization.Get<Localization::License>() == "Foo Bar License");
    340             REQUIRE(frenchLocalization.Get<Localization::LicenseUrl>() == "http://licenseUrl-fr.net");
    341             REQUIRE(frenchLocalization.Get<Localization::Copyright>() == "Foo Bar Copyright");
    342             REQUIRE(frenchLocalization.Get<Localization::CopyrightUrl>() == "http://copyrightUrl-fr.net");
    343             REQUIRE(frenchLocalization.Get<Localization::ShortDescription>() == "Foo bar is a foo bar French.");
    344             REQUIRE(frenchLocalization.Get<Localization::Description>() == "Foo bar is a placeholder French.");
    345             REQUIRE(frenchLocalization.Get<Localization::Tags>().size() == 3);
    346             REQUIRE(frenchLocalization.Get<Localization::Tags>().at(0) == "FooBarFr");
    347             REQUIRE(frenchLocalization.Get<Localization::Tags>().at(1) == "FooFr");
    348             REQUIRE(frenchLocalization.Get<Localization::Tags>().at(2) == "BarFr");
    349             REQUIRE(frenchLocalization.Get<Localization::ReleaseNotes>() == "Release notes");
    350             REQUIRE(frenchLocalization.Get<Localization::ReleaseNotesUrl>() == "https://ReleaseNotes.net");
    351             REQUIRE(frenchLocalization.Get<Localization::Agreements>().size() == 1);
    352             REQUIRE(frenchLocalization.Get<Localization::Agreements>().at(0).Label == "Label");
    353             REQUIRE(frenchLocalization.Get<Localization::Agreements>().at(0).AgreementText == "Text");
    354             REQUIRE(frenchLocalization.Get<Localization::Agreements>().at(0).AgreementUrl == "https://AgreementUrl.net");
    355             REQUIRE(frenchLocalization.Get<Localization::PurchaseUrl>() == "http://purchaseUrl.net");
    356             REQUIRE(frenchLocalization.Get<Localization::InstallationNotes>() == "Installation Notes");
    357             REQUIRE(frenchLocalization.Get<Localization::Documentations>().size() == 1);
    358             REQUIRE(frenchLocalization.Get<Localization::Documentations>().at(0).DocumentLabel == "Document Label");
    359             REQUIRE(frenchLocalization.Get<Localization::Documentations>().at(0).DocumentUrl == "http://documentUrl.net");
    360             REQUIRE(frenchLocalization.Get<Localization::Icons>().size() == 1);
    361             REQUIRE(frenchLocalization.Get<Localization::Icons>().at(0).Url == "https://testIcon");
    362             REQUIRE(frenchLocalization.Get<Localization::Icons>().at(0).FileType == IconFileTypeEnum::Png);
    363             REQUIRE(frenchLocalization.Get<Localization::Icons>().at(0).Resolution == IconResolutionEnum::Square32);
    364             REQUIRE(frenchLocalization.Get<Localization::Icons>().at(0).Theme == IconThemeEnum::Light);
    365             REQUIRE(frenchLocalization.Get<Localization::Icons>().at(0).Sha256 == AppInstaller::Utility::SHA256::ConvertToBytes("69D84CA8899800A5575CE31798293CD4FEBAB1D734A07C2E51E56A28E0DF8321"));
    366         }
    367 
    368         void VerifyInstallers_AllFields(const AppInstaller::Manifest::Manifest& manifest)
    369         {
    370             REQUIRE(manifest.Installers.size() == 1);
    371 
    372             ManifestInstaller actualInstaller = manifest.Installers.at(0);
    373             REQUIRE(actualInstaller.Sha256 == AppInstaller::Utility::SHA256::ConvertToBytes("011048877dfaef109801b3f3ab2b60afc74f3fc4f7b3430e0c897f5da1df84b6"));
    374             REQUIRE(actualInstaller.Url == "http://foobar.zip");
    375             REQUIRE(actualInstaller.Arch == Architecture::X86);
    376             REQUIRE(actualInstaller.Locale == "en-US");
    377             REQUIRE(actualInstaller.Platform.size() == 1);
    378             REQUIRE(actualInstaller.Platform[0] == PlatformEnum::Desktop);
    379             REQUIRE(actualInstaller.MinOSVersion == "1078");
    380             REQUIRE(actualInstaller.BaseInstallerType == InstallerTypeEnum::Zip);
    381             REQUIRE(actualInstaller.Scope == ScopeEnum::User);
    382             REQUIRE(actualInstaller.InstallModes.size() == 1);
    383             REQUIRE(actualInstaller.InstallModes.at(0) == InstallModeEnum::Interactive);
    384             REQUIRE(actualInstaller.Switches.size() == 8);
    385             REQUIRE(actualInstaller.Switches.at(InstallerSwitchType::Silent) == "/s");
    386             REQUIRE(actualInstaller.Switches.at(InstallerSwitchType::SilentWithProgress) == "/s");
    387             REQUIRE(actualInstaller.Switches.at(InstallerSwitchType::Interactive) == "/i");
    388             REQUIRE(actualInstaller.Switches.at(InstallerSwitchType::InstallLocation) == "C:\\Users\\User1");
    389             REQUIRE(actualInstaller.Switches.at(InstallerSwitchType::Log) == "/l");
    390             REQUIRE(actualInstaller.Switches.at(InstallerSwitchType::Update) == "/u");
    391             REQUIRE(actualInstaller.Switches.at(InstallerSwitchType::Custom) == "/custom");
    392             REQUIRE(actualInstaller.Switches.at(InstallerSwitchType::Repair) == "/repair");
    393             REQUIRE(actualInstaller.InstallerSuccessCodes.size() == 1);
    394             REQUIRE(actualInstaller.InstallerSuccessCodes.at(0) == 0);
    395             REQUIRE(actualInstaller.UpdateBehavior == UpdateBehaviorEnum::Deny);
    396             REQUIRE(actualInstaller.Commands.at(0) == "command1");
    397             REQUIRE(actualInstaller.Protocols.at(0) == "protocol1");
    398             REQUIRE(actualInstaller.FileExtensions.at(0) == ".file-extension");
    399             REQUIRE(actualInstaller.Dependencies.HasExactDependency(DependencyType::WindowsFeature, "feature1"));
    400             REQUIRE(actualInstaller.Dependencies.HasExactDependency(DependencyType::WindowsLibrary, "library1"));
    401             REQUIRE(actualInstaller.Dependencies.HasExactDependency(DependencyType::Package, "Foo.Baz", "2.0.0"));
    402             REQUIRE(actualInstaller.Dependencies.HasExactDependency(DependencyType::External, "FooBarBaz"));
    403             REQUIRE(actualInstaller.PackageFamilyName == "");
    404             REQUIRE(actualInstaller.ProductCode == "5b6e0f8a-3bbf-4a17-aefd-024c2b3e075d");
    405             REQUIRE(actualInstaller.ReleaseDate == "2021-01-01");
    406             REQUIRE(actualInstaller.InstallerAbortsTerminal);
    407             REQUIRE(actualInstaller.InstallLocationRequired);
    408             REQUIRE(actualInstaller.RequireExplicitUpgrade);
    409             REQUIRE(actualInstaller.ElevationRequirement == ElevationRequirementEnum::ElevatesSelf);
    410             REQUIRE(actualInstaller.UnsupportedOSArchitectures.size() == 1);
    411             REQUIRE(actualInstaller.UnsupportedOSArchitectures.at(0) == Architecture::Arm);
    412             REQUIRE(actualInstaller.AppsAndFeaturesEntries.size() == 1);
    413             REQUIRE(actualInstaller.AppsAndFeaturesEntries.at(0).DisplayName == "DisplayName");
    414             REQUIRE(actualInstaller.AppsAndFeaturesEntries.at(0).DisplayVersion == "DisplayVersion");
    415             REQUIRE(actualInstaller.AppsAndFeaturesEntries.at(0).Publisher == "Publisher");
    416             REQUIRE(actualInstaller.AppsAndFeaturesEntries.at(0).ProductCode == "ProductCode");
    417             REQUIRE(actualInstaller.AppsAndFeaturesEntries.at(0).UpgradeCode == "UpgradeCode");
    418             REQUIRE(actualInstaller.AppsAndFeaturesEntries.at(0).InstallerType == InstallerTypeEnum::Exe);
    419             REQUIRE(actualInstaller.Markets.AllowedMarkets.size() == 1);
    420             REQUIRE(actualInstaller.Markets.AllowedMarkets.at(0) == "US");
    421             REQUIRE(actualInstaller.ExpectedReturnCodes.at(3).ReturnResponseEnum == ExpectedReturnCodeEnum::Custom);
    422             REQUIRE(actualInstaller.ExpectedReturnCodes.at(3).ReturnResponseUrl == "http://returnResponseUrl.net");
    423             REQUIRE(actualInstaller.NestedInstallerType == InstallerTypeEnum::Portable);
    424             REQUIRE(actualInstaller.DisplayInstallWarnings);
    425             REQUIRE(actualInstaller.UnsupportedArguments.size() == 1);
    426             REQUIRE(actualInstaller.UnsupportedArguments.at(0) == UnsupportedArgumentEnum::Log);
    427             REQUIRE(actualInstaller.NestedInstallerFiles.size() == 1);
    428             REQUIRE(actualInstaller.NestedInstallerFiles.at(0).RelativeFilePath == "test\\app.exe");
    429             REQUIRE(actualInstaller.NestedInstallerFiles.at(0).PortableCommandAlias == "test.exe");
    430             REQUIRE(actualInstaller.InstallationMetadata.DefaultInstallLocation == "%TEMP%\\DefaultInstallLocation");
    431             REQUIRE(actualInstaller.InstallationMetadata.Files.size() == 1);
    432             REQUIRE(actualInstaller.InstallationMetadata.Files.at(0).RelativeFilePath == "test\\app.exe");
    433             REQUIRE(actualInstaller.InstallationMetadata.Files.at(0).FileType == InstalledFileTypeEnum::Launch);
    434             REQUIRE(actualInstaller.InstallationMetadata.Files.at(0).FileSha256 == AppInstaller::Utility::SHA256::ConvertToBytes("011048877dfaef109801b3f3ab2b60afc74f3fc4f7b3430e0c897f5da1df84b6"));
    435             REQUIRE(actualInstaller.InstallationMetadata.Files.at(0).InvocationParameter == "/parameter");
    436             REQUIRE(actualInstaller.InstallationMetadata.Files.at(0).DisplayName == "test");
    437             REQUIRE(actualInstaller.DownloadCommandProhibited);
    438             REQUIRE(actualInstaller.RepairBehavior == RepairBehaviorEnum::Uninstaller);
    439         }
    440     };
    441 }
    442 
    443 TEST_CASE("GetManifests_GoodRequest_Authentication", "[RestSource][Interface_1_7]")
    444 {
    445     if (Runtime::IsRunningAsSystem())
    446     {
    447         WARN("Test does not support running as system. Skipped.");
    448         return;
    449     }
    450 
    451     std::string expectedToken = "TestToken";
    452 
    453     // Set good authentication result
    454     AuthenticationResult authResultOverride;
    455     authResultOverride.Status = S_OK;
    456     authResultOverride.Token = expectedToken;
    457     TestHook::SetAuthenticationResult_Override setAuthenticationResultOverride(authResultOverride);
    458 
    459     // GetManifest should succeed with expected value.
    460     HttpClientHelper helper{ GetHeaderVerificationHandler(web::http::status_codes::OK, SampleGetManifestResponse, { web::http::header_names::authorization, JSON::GetUtilityString(CreateBearerToken(expectedToken)) }, web::http::status_codes::Unauthorized) };
    461     Interface v1_7{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {}, GetTestAuthenticationArguments() };
    462     auto manifestResult = v1_7.GetManifestByVersion("Foo.Bar", "5.0.0", "");
    463     REQUIRE(manifestResult.has_value());
    464     const auto& manifest = manifestResult.value();
    465     REQUIRE(manifest.Id == "Foo.Bar");
    466     REQUIRE(manifest.Version == "5.0.0");
    467 }
    468 
    469 TEST_CASE("GetManifests_BadRequest_AuthenticationFailed", "[RestSource][Interface_1_7]")
    470 {
    471     if (Runtime::IsRunningAsSystem())
    472     {
    473         WARN("Test does not support running as system. Skipped.");
    474         return;
    475     }
    476 
    477     std::string expectedToken = "TestToken";
    478 
    479     // Set authentication failed result
    480     AuthenticationResult authResultOverride;
    481     authResultOverride.Status = APPINSTALLER_CLI_ERROR_AUTHENTICATION_FAILED;
    482     TestHook::SetAuthenticationResult_Override setAuthenticationResultOverride(authResultOverride);
    483 
    484     // GetManifest should fail with authentication failure
    485     HttpClientHelper helper{ GetHeaderVerificationHandler(web::http::status_codes::OK, SampleGetManifestResponse, { web::http::header_names::authorization, JSON::GetUtilityString(CreateBearerToken(expectedToken)) }, web::http::status_codes::Unauthorized) };
    486     Interface v1_7{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {}, GetTestAuthenticationArguments() };
    487     REQUIRE_THROWS_HR(v1_7.GetManifestByVersion("Foo.Bar", "5.0.0", ""), APPINSTALLER_CLI_ERROR_AUTHENTICATION_FAILED);
    488 }
    489 
    490 TEST_CASE("GetManifests_BadRequest_InvalidAuthenticationToken", "[RestSource][Interface_1_7]")
    491 {
    492     if (Runtime::IsRunningAsSystem())
    493     {
    494         WARN("Test does not support running as system. Skipped.");
    495         return;
    496     }
    497 
    498     std::string expectedToken = "TestToken";
    499 
    500     // Set authentication result with incorrect token
    501     AuthenticationResult authResultOverride;
    502     authResultOverride.Status = S_OK;
    503     authResultOverride.Token = "OtherToken";
    504     TestHook::SetAuthenticationResult_Override setAuthenticationResultOverride(authResultOverride);
    505 
    506     // GetManifest should fail with access denied
    507     HttpClientHelper helper{ GetHeaderVerificationHandler(web::http::status_codes::OK, SampleGetManifestResponse, { web::http::header_names::authorization, JSON::GetUtilityString(CreateBearerToken(expectedToken)) }, web::http::status_codes::Unauthorized) };
    508     Interface v1_7{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {}, GetTestAuthenticationArguments() };
    509     REQUIRE_THROWS_HR(v1_7.GetManifestByVersion("Foo.Bar", "5.0.0", ""), HTTP_E_STATUS_DENIED);
    510 }
    511 
    512 TEST_CASE("Search_GoodRequest_Authentication", "[RestSource][Interface_1_7]")
    513 {
    514     if (Runtime::IsRunningAsSystem())
    515     {
    516         WARN("Test does not support running as system. Skipped.");
    517         return;
    518     }
    519 
    520     std::string expectedToken = "TestToken";
    521 
    522     // Set good authentication result
    523     AuthenticationResult authResultOverride;
    524     authResultOverride.Status = S_OK;
    525     authResultOverride.Token = expectedToken;
    526     TestHook::SetAuthenticationResult_Override setAuthenticationResultOverride(authResultOverride);
    527 
    528     // Search should succeed with expected value.
    529     HttpClientHelper helper{ GetHeaderVerificationHandler(web::http::status_codes::OK, SampleSearchResponse, { web::http::header_names::authorization, JSON::GetUtilityString(CreateBearerToken(expectedToken)) }, web::http::status_codes::Unauthorized) };
    530     Interface v1_7{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {}, GetTestAuthenticationArguments() };
    531     SearchRequest request;
    532     PackageMatchFilter filter{ PackageMatchField::Name, MatchType::Exact, "package" };
    533     request.Filters.emplace_back(std::move(filter));
    534     IRestClient::SearchResult searchResponse = v1_7.Search(request);
    535     REQUIRE(searchResponse.Matches.size() == 1);
    536     IRestClient::Package package = searchResponse.Matches.at(0);
    537     REQUIRE(package.PackageInformation.PackageIdentifier.compare("git.package") == 0);
    538 }
    539 
    540 TEST_CASE("Search_BadRequest_AuthenticationFailed", "[RestSource][Interface_1_7]")
    541 {
    542     if (Runtime::IsRunningAsSystem())
    543     {
    544         WARN("Test does not support running as system. Skipped.");
    545         return;
    546     }
    547 
    548     std::string expectedToken = "TestToken";
    549 
    550     // Set authentication failed result
    551     AuthenticationResult authResultOverride;
    552     authResultOverride.Status = APPINSTALLER_CLI_ERROR_AUTHENTICATION_FAILED;
    553     TestHook::SetAuthenticationResult_Override setAuthenticationResultOverride(authResultOverride);
    554 
    555     // Search should fail with authentication failure
    556     HttpClientHelper helper{ GetHeaderVerificationHandler(web::http::status_codes::OK, SampleSearchResponse, { web::http::header_names::authorization, JSON::GetUtilityString(CreateBearerToken(expectedToken)) }, web::http::status_codes::Unauthorized) };
    557     Interface v1_7{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {}, GetTestAuthenticationArguments() };
    558     SearchRequest request;
    559     PackageMatchFilter filter{ PackageMatchField::Name, MatchType::Exact, "package" };
    560     request.Filters.emplace_back(std::move(filter));
    561     REQUIRE_THROWS_HR(v1_7.Search(request), APPINSTALLER_CLI_ERROR_AUTHENTICATION_FAILED);
    562 }
    563 
    564 TEST_CASE("Search_BadRequest_InvalidAuthenticationToken", "[RestSource][Interface_1_7]")
    565 {
    566     if (Runtime::IsRunningAsSystem())
    567     {
    568         WARN("Test does not support running as system. Skipped.");
    569         return;
    570     }
    571 
    572     std::string expectedToken = "TestToken";
    573 
    574     // Set authentication result with incorrect token
    575     AuthenticationResult authResultOverride;
    576     authResultOverride.Status = S_OK;
    577     authResultOverride.Token = "OtherToken";
    578     TestHook::SetAuthenticationResult_Override setAuthenticationResultOverride(authResultOverride);
    579 
    580     // Search should fail with access denied
    581     HttpClientHelper helper{ GetHeaderVerificationHandler(web::http::status_codes::OK, SampleSearchResponse, { web::http::header_names::authorization, JSON::GetUtilityString(CreateBearerToken(expectedToken)) }, web::http::status_codes::Unauthorized) };
    582     Interface v1_7{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {}, GetTestAuthenticationArguments() };
    583     SearchRequest request;
    584     PackageMatchFilter filter{ PackageMatchField::Name, MatchType::Exact, "package" };
    585     request.Filters.emplace_back(std::move(filter));
    586     REQUIRE_THROWS_HR(v1_7.Search(request), HTTP_E_STATUS_DENIED);
    587 }
    588 
    589 TEST_CASE("GetManifests_GoodResponse_V1_7", "[RestSource][Interface_1_7]")
    590 {
    591     GoodManifest_AllFields sampleManifest;
    592     utility::string_t sample = sampleManifest.GetSampleManifest_AllFields();
    593     HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) };
    594     Interface v1_7{ TestRestUriString, std::move(helper), {} };
    595     std::vector<AppInstaller::Manifest::Manifest> manifests = v1_7.GetManifests("Foo.Bar");
    596     REQUIRE(manifests.size() == 1);
    597 
    598     // Verify manifest is populated
    599     AppInstaller::Manifest::Manifest& manifest = manifests[0];
    600     REQUIRE(manifest.Id == "Foo.Bar");
    601     REQUIRE(manifest.Version == "3.0.0abc");
    602     REQUIRE(manifest.Moniker == "FooBarMoniker");
    603     REQUIRE(manifest.Channel == "");
    604     REQUIRE(manifest.ManifestVersion == AppInstaller::Manifest::ManifestVer{ "1.7.0" });
    605     sampleManifest.VerifyLocalizations_AllFields(manifest);
    606     sampleManifest.VerifyInstallers_AllFields(manifest);
    607 }