Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/AppInstallerCLITests/AppInstallerCLITests.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -707,6 +707,9 @@
<CopyFileToFolders Include="TestData\Manifest-Good-DefaultExpectedReturnCodeInInstallerSuccessCodes.yaml">
<DeploymentContent>true</DeploymentContent>
</CopyFileToFolders>
<CopyFileToFolders Include="TestData\Manifest-Good-InstallerUrl-BlockScalar.yaml">
<DeploymentContent>true</DeploymentContent>
</CopyFileToFolders>
<CopyFileToFolders Include="TestData\Manifest-Good-MultipleArpVersionDeclared.yaml">
<DeploymentContent>true</DeploymentContent>
</CopyFileToFolders>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,9 @@
<CopyFileToFolders Include="TestData\Manifest-Good-DefaultExpectedReturnCodeInInstallerSuccessCodes.yaml">
<Filter>TestData</Filter>
</CopyFileToFolders>
<CopyFileToFolders Include="TestData\Manifest-Good-InstallerUrl-BlockScalar.yaml">
<Filter>TestData</Filter>
</CopyFileToFolders>
<CopyFileToFolders Include="TestData\Manifest-Good-InstallerTypeExeRoot-Silent.yaml">
<Filter>TestData</Filter>
</CopyFileToFolders>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# yaml-language-server: $schema=https://aka.ms/winget-manifest.singleton.1.1.0.schema.json

PackageIdentifier: microsoft.msixsdk
PackageName: MSIX SDK
PackageVersion: 1.07.32-beta
Publisher: Microsoft
ShortDescription: description
License: Test
PackageLocale: en-US
Installers:
- Architecture: x86
InstallerUrl: >
https://rubengustorage.blob.core.windows.net/publiccontainer/msixsdk-x86.msi

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don’t think this should be using a hardcoded live URL - Don’t other tests use placeholders that get resolved at test runtime?

InstallerSha256: 98B67758CEAFFCBB3FE47838FD0A8D7BD581C2650842D6B2B0E0D49A23270CCD
InstallerType: msi
ManifestType: singleton
ManifestVersion: 1.1.0
10 changes: 10 additions & 0 deletions src/AppInstallerCLITests/YamlManifest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -958,6 +958,15 @@ TEST_CASE("ReadGoodManifestWithSpaces", "[ManifestValidation]")
REQUIRE(manifest.DefaultInstallerInfo.FileExtensions == MultiValue{ "appx", "appxbundle", "msix", "msixbundle" });
}

TEST_CASE("ReadGoodManifestInstallerUrlBlockScalar", "[ManifestValidation]")
{
ManifestValidateOption validateOption = GetTestManifestValidateOption();
Manifest manifest = YamlParser::CreateFromPath(TestDataFile("Manifest-Good-InstallerUrl-BlockScalar.yaml"), validateOption);

REQUIRE(manifest.Installers.size() == 1);
REQUIRE(manifest.Installers[0].Url == "https://rubengustorage.blob.core.windows.net/publiccontainer/msixsdk-x86.msi");
}

TEST_CASE("ReadGoodManifests", "[ManifestValidation]")
{
ManifestTestCase TestCases[] =
Expand All @@ -973,6 +982,7 @@ TEST_CASE("ReadGoodManifests", "[ManifestValidation]")
{ "Manifest-Good-Minimum-InstallerType.yaml" },
{ "Manifest-Good-Switches.yaml" },
{ "Manifest-Good-DefaultExpectedReturnCodeInInstallerSuccessCodes.yaml" },
{ "Manifest-Good-InstallerUrl-BlockScalar.yaml" },
{ "Manifest-Good-InstallerTypeZip-PortableExe.yaml" },
{ "Manifest-Good-InstallerTypeZip-PortableExeUppercase.yaml" },
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,19 @@
return YamlScalarType::String;
}

// YAML block scalars with clip/keep chomping retain a trailing line break.
// Schema patterns anchored with `$` fail against that break under current
// MSVC std::regex ECMAScript semantics (LWG-2503), so strip it before validation.

Check failure on line 52 in src/AppInstallerCommonCore/Manifest/ManifestSchemaValidation.cpp

View workflow job for this annotation

GitHub Actions / Check Spelling

`LWG` is not a recognized word (unrecognized-spelling)
std::string TrimTrailingLineBreaks(std::string value)
{
while (!value.empty() && (value.back() == '\n' || value.back() == '\r'))
{
value.pop_back();
}

return value;
}

Json::Value YamlScalarNodeToJson(const YAML::Node& scalarNode, YamlScalarType scalarType)
{
if (scalarType == YamlScalarType::Int)
Expand All @@ -59,7 +72,7 @@
}
else
{
return Json::Value(scalarNode.as<std::string>());
return Json::Value(TrimTrailingLineBreaks(scalarNode.as<std::string>()));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ namespace AppInstaller::Manifest
std::vector<FieldProcessInfo> installerOnlyFields =
{
{ "Arch", [](const YAML::Node& value, const VariantManifestPtr& v)->ValidationErrors { variant_ptr<ManifestInstaller>(v)->Arch = Utility::ConvertToArchitectureEnum(value.as<std::string>()); return {}; } },
{ "Url", [](const YAML::Node& value, const VariantManifestPtr& v)->ValidationErrors { variant_ptr<ManifestInstaller>(v)->Url = value.as<std::string>(); return {}; } },
{ "Url", [](const YAML::Node& value, const VariantManifestPtr& v)->ValidationErrors { variant_ptr<ManifestInstaller>(v)->Url = Utility::Trim(value.as<std::string>()); return {}; } },

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applying the trim only to specific fields seems prone to failure. What happens when a new pattern field is added in the future ? The user would have to remember to add the trim?

{ "Sha256", [](const YAML::Node& value, const VariantManifestPtr& v)->ValidationErrors { variant_ptr<ManifestInstaller>(v)->Sha256 = Utility::SHA256::ConvertToBytes(value.as<std::string>()); return {}; } },
{ "SignatureSha256", [](const YAML::Node& value, const VariantManifestPtr& v)->ValidationErrors { variant_ptr<ManifestInstaller>(v)->SignatureSha256 = Utility::SHA256::ConvertToBytes(value.as<std::string>()); return {}; } },
{ "Language", [](const YAML::Node& value, const VariantManifestPtr& v)->ValidationErrors { variant_ptr<ManifestInstaller>(v)->Locale = value.as<std::string>(); return {}; } },
Expand Down Expand Up @@ -307,7 +307,7 @@ namespace AppInstaller::Manifest
std::vector<FieldProcessInfo> v1InstallerFields =
{
{ "Architecture", [](const YAML::Node& value, const VariantManifestPtr& v)->ValidationErrors { variant_ptr<ManifestInstaller>(v)->Arch = Utility::ConvertToArchitectureEnum(value.as<std::string>()); return {}; } },
{ "InstallerUrl", [](const YAML::Node& value, const VariantManifestPtr& v)->ValidationErrors { variant_ptr<ManifestInstaller>(v)->Url = value.as<std::string>(); return {}; } },
{ "InstallerUrl", [](const YAML::Node& value, const VariantManifestPtr& v)->ValidationErrors { variant_ptr<ManifestInstaller>(v)->Url = Utility::Trim(value.as<std::string>()); return {}; } },
{ "InstallerSha256", [](const YAML::Node& value, const VariantManifestPtr& v)->ValidationErrors { variant_ptr<ManifestInstaller>(v)->Sha256 = Utility::SHA256::ConvertToBytes(value.as<std::string>()); return {}; } },
{ "SignatureSha256", [](const YAML::Node& value, const VariantManifestPtr& v)->ValidationErrors { variant_ptr<ManifestInstaller>(v)->SignatureSha256 = Utility::SHA256::ConvertToBytes(value.as<std::string>()); return {}; } },
// No custom validation needed at field populating time since we have semantic validation later to block msstore and productId from community repo.
Expand Down
Loading