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 }