Skip to content

Commit

Permalink
Merge pull request chocolatey#3001 from AdmiringWorm/readd-pack-valid…
Browse files Browse the repository at this point in the history
…ations

(chocolatey#3000) Create new rule service and read old validation messages
  • Loading branch information
gep13 authored Jan 27, 2023
2 parents c0e2f84 + c21b121 commit c6e30b7
Show file tree
Hide file tree
Showing 25 changed files with 930 additions and 93 deletions.
16 changes: 8 additions & 8 deletions src/chocolatey.tests.integration/scenarios/PackScenarios.cs
Original file line number Diff line number Diff line change
Expand Up @@ -439,63 +439,63 @@ public void should_throw_exception_on_all_unsupported_elements()
{
AddFile("myPackage.nuspec", NuspecContentWithAllUnsupportedElements);

ServiceAct.ShouldThrow<System.IO.FileFormatException>();
ServiceAct.ShouldThrow<System.IO.InvalidDataException>();
}

[Fact]
public void should_throw_exception_on_serviceable_element()
{
AddFile("myPackage.nuspec", NuspecContentWithServiceableElement);

ServiceAct.ShouldThrow<System.IO.FileFormatException>();
ServiceAct.ShouldThrow<System.IO.InvalidDataException>();
}

[Fact]
public void should_throw_exception_on_license_element()
{
AddFile("myPackage.nuspec", NuspecContentWithLicenseElement);

ServiceAct.ShouldThrow<System.IO.FileFormatException>();
ServiceAct.ShouldThrow<System.IO.InvalidDataException>();
}

[Fact]
public void should_throw_exception_on_repository_element()
{
AddFile("myPackage.nuspec", NuspecContentWithRepositoryElement);

ServiceAct.ShouldThrow<System.IO.FileFormatException>();
ServiceAct.ShouldThrow<System.IO.InvalidDataException>();
}

[Fact]
public void should_throw_exception_on_package_types_element()
{
AddFile("myPackage.nuspec", NuspecContentWithPackageTypesElement);

ServiceAct.ShouldThrow<System.IO.FileFormatException>();
ServiceAct.ShouldThrow<System.IO.InvalidDataException>();
}

[Fact]
public void should_throw_exception_on_framework_references_element()
{
AddFile("myPackage.nuspec", NuspecContentWithFrameWorkReferencesElement);

ServiceAct.ShouldThrow<System.IO.FileFormatException>();
ServiceAct.ShouldThrow<System.IO.InvalidDataException>();
}

[Fact]
public void should_throw_exception_on_readme_element()
{
AddFile("myPackage.nuspec", NuspecContentWithReadmeElement);

ServiceAct.ShouldThrow<System.IO.FileFormatException>();
ServiceAct.ShouldThrow<System.IO.InvalidDataException>();
}

[Fact]
public void should_throw_exception_on_icon_element()
{
AddFile("myPackage.nuspec", NuspecContentWithIconElement);

ServiceAct.ShouldThrow<System.IO.FileFormatException>();
ServiceAct.ShouldThrow<System.IO.InvalidDataException>();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ namespace chocolatey.tests.infrastructure.app.services
using chocolatey.infrastructure.app.configuration;
using chocolatey.infrastructure.app.domain;
using chocolatey.infrastructure.app.services;
using chocolatey.infrastructure.services;
using Moq;
using NuGet.Common;
using NuGet.Packaging;
Expand All @@ -40,6 +41,7 @@ public abstract class NugetServiceSpecsBase : TinySpec
protected Mock<IFilesService> filesService = new Mock<IFilesService>();
protected Mock<IPackageMetadata> package = new Mock<IPackageMetadata>();
protected Mock<IPackageDownloader> packageDownloader = new Mock<IPackageDownloader>();
protected Mock<IRuleService> ruleService = new Mock<IRuleService>();

public override void Context()
{
Expand All @@ -49,7 +51,7 @@ public override void Context()
filesService.ResetCalls();
package.ResetCalls();

service = new NugetService(fileSystem.Object, nugetLogger.Object, packageInfoService.Object, filesService.Object);
service = new NugetService(fileSystem.Object, nugetLogger.Object, packageInfoService.Object, filesService.Object, ruleService.Object);
}
}

Expand Down
91 changes: 88 additions & 3 deletions src/chocolatey.tests/infrastructure/guards/EnsureSpecs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,30 @@ public override void Context()
}

public class when_Ensure_is_being_set_to_a_type : EnsureSpecsBase
{
private object result;
private readonly object bob = "something";

public override void Because()
{
result = Ensure.that(() => bob);
}

[Fact]
public void should_return_a_type_of_object_for_ensuring()
{
result.ShouldBeType<Ensure<object>>();
}

[Fact]
public void should_have_the_value_specified()
{
var bobEnsure = result as Ensure<object>;
bobEnsure.Value.ShouldEqual(bob);
}
}

public class when_Ensure_is_a_string_type : EnsureSpecsBase
{
private object result;
private readonly string bob = "something";
Expand All @@ -42,19 +66,80 @@ public override void Because()
}

[Fact]
public void should_return_a_type_of_string_for_ensuring()
public void should_return_a_ensure_string_type()
{
result.ShouldBeType<Ensure<string>>();
result.ShouldBeType<EnsureString>();
}

[Fact]
public void should_have_the_value_specified()
{
var bobEnsure = result as Ensure<string>;
var bobEnsure = result as EnsureString;
bobEnsure.Value.ShouldEqual(bob);
}
}

public class when_using_EnsureString : EnsureSpecsBase
{
public override void Because()
{
}

[Fact]
public void when_testing_a_string_against_null_value_should_fail()
{
string test = null;

Action a = () => Ensure.that(() => test).is_not_null_or_whitespace();

a.ShouldThrow<ArgumentNullException>();
}

[Fact]
public void when_testing_a_string_against_an_empty_value_should_fail()
{
Action a = () => Ensure.that(() => string.Empty).is_not_null_or_whitespace();

a.ShouldThrow<ArgumentException>();
}

[Fact]
public void when_testing_a_string_against_a_whitespace_value_should_fail()
{
var test = " ";

Action a = () => Ensure.that(() => test).is_not_null_or_whitespace();

a.ShouldThrow<ArgumentException>();
}

[Fact]
public void when_testing_a_string_against_a_non_empty_value_should_pass()
{
var test = "some value";

Ensure.that(() => test).is_not_null_or_whitespace();
}

[Fact]
public void when_testing_a_string_without_expected_extension_should_fail()
{
var test = "some-file.png";

Action a = () => Ensure.that(() => test).has_any_extension(".jpg", ".bmp", ".gif");

a.ShouldThrow<ArgumentException>();
}

[Fact]
public void when_testing_a_string_with_expected_extension_should_pass()
{
var test = "some-file.png";

Ensure.that(() => test).has_any_extension(".jpg", ".bmp", ".gif", ".png");
}
}

public class when_using_Ensure : EnsureSpecsBase
{
public override void Because()
Expand Down
17 changes: 17 additions & 0 deletions src/chocolatey/chocolatey.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,19 @@
<Compile Include="infrastructure.app\nuget\ChocolateyNuGetProjectContext.cs" />
<Compile Include="infrastructure.app\nuget\ChocolateyNuGetSettings.cs" />
<Compile Include="infrastructure.app\nuget\ChocolateySourceCacheContext.cs" />
<Compile Include="infrastructure.app\rules\MetadataRuleBase.cs" />
<Compile Include="infrastructure.app\rules\RequiredMetadataRule.cs" />
<Compile Include="infrastructure.app\rules\EmptyOrInvalidUrlMetadataRule.cs" />
<Compile Include="infrastructure.app\rules\FrameWorkReferencesMetadataRule.cs" />
<Compile Include="infrastructure.app\rules\IconMetadataRule.cs" />
<Compile Include="infrastructure.app\rules\LicenseMetadataRule.cs" />
<Compile Include="infrastructure.app\rules\PackageTypesMetadataRule.cs" />
<Compile Include="infrastructure.app\rules\ReadmeMetadataRule.cs" />
<Compile Include="infrastructure.app\rules\RepositoryMetadataRule.cs" />
<Compile Include="infrastructure.app\rules\RequireLicenseAcceptanceMetadataRule.cs" />
<Compile Include="infrastructure.app\rules\ServicableMetadataRule.cs" />
<Compile Include="infrastructure.app\rules\VersionMetadataRule.cs" />
<Compile Include="infrastructure.app\services\RuleService.cs" />
<Compile Include="infrastructure\cryptography\DefaultEncryptionUtility.cs" />
<Compile Include="infrastructure\adapters\IEncryptionUtility.cs" />
<Compile Include="infrastructure.app\validations\GlobalConfigurationValidation.cs" />
Expand Down Expand Up @@ -251,6 +264,10 @@
<Compile Include="infrastructure\logging\LogMessage.cs" />
<Compile Include="infrastructure\logging\LogSinkLog.cs" />
<Compile Include="infrastructure\registration\AssemblyResolution.cs" />
<Compile Include="infrastructure\rules\IMetadataRule.cs" />
<Compile Include="infrastructure\rules\RuleResult.cs" />
<Compile Include="infrastructure\rules\RuleType.cs" />
<Compile Include="infrastructure\services\IRuleService.cs" />
<Compile Include="infrastructure\synchronization\GlobalMutex.cs" />
<Compile Include="infrastructure\logging\TraceLog.cs" />
<Compile Include="infrastructure\registration\SecurityProtocol.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright © 2017 - 2022 Chocolatey Software, Inc
// Copyright © 2017 - 2023 Chocolatey Software, Inc
// Copyright © 2011 - 2017 RealDimensions Software, LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -32,6 +32,9 @@ namespace chocolatey.infrastructure.app.registration
using NuGet.Common;
using NuGet.PackageManagement;
using NuGet.Packaging;
using chocolatey.infrastructure.rules;
using chocolatey.infrastructure.app.rules;
using System.Linq;

internal class ChocolateyRegistrationModule : IExtensionModule
{
Expand Down Expand Up @@ -78,6 +81,16 @@ public void register_dependencies(IContainerRegistrator registrator, ChocolateyC
registrator.register_service<IValidation>(
typeof(GlobalConfigurationValidation),
typeof(SystemStateValidation));

// Rule registrations
registrator.register_service<IRuleService, RuleService>();

var availableRules = GetType().Assembly
.GetTypes()
.Where(t => !t.IsInterface && !t.IsAbstract && typeof(IMetadataRule).IsAssignableFrom(t))
.ToArray();

registrator.register_service<IMetadataRule>(availableRules);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright © 2023-Present Chocolatey Software, Inc
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
//
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

namespace chocolatey.infrastructure.app.rules
{
using System;
using System.Collections.Generic;
using chocolatey.infrastructure.rules;
using NuGet.Packaging;

internal sealed class EmptyOrInvalidUrlMetadataRule : MetadataRuleBase
{
public override IEnumerable<RuleResult> validate(NuspecReader reader)
{
var items = new[]
{
"projectUrl",
"projectSourceUrl",
"docsUrl",
"bugTrackerUrl",
"mailingListUrl",
"iconUrl",
"licenseUrl"
};

foreach (var item in items)
{
if (has_element(reader, item))
{
var value = get_element_value(reader, item);

if (string.IsNullOrWhiteSpace(value))
{
yield return new RuleResult(RuleType.Error, "The {0} element in the package nuspec file cannot be empty.".format_with(item));
}
else if (!Uri.TryCreate(value, UriKind.Absolute, out _))
{
yield return new RuleResult(RuleType.Error, "'{0}' is not a valid URL for the {1} element in the package nuspec file.".format_with(value, item));
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright © 2023-Present Chocolatey Software, Inc
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
//
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

namespace chocolatey.infrastructure.app.rules
{
using System.Collections.Generic;
using chocolatey.infrastructure.rules;
using NuGet.Packaging;

internal sealed class FrameWorkReferencesMetadataRule : MetadataRuleBase
{
public override IEnumerable<RuleResult> validate(NuspecReader reader)
{
if (has_element(reader, "frameworkReferences"))
{
yield return new RuleResult(RuleType.Error, "<frameworkReferences> elements are not supported in Chocolatey CLI.");
}
}
}
}
32 changes: 32 additions & 0 deletions src/chocolatey/infrastructure.app/rules/IconMetadataRule.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright © 2023-Present Chocolatey Software, Inc
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
//
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

namespace chocolatey.infrastructure.app.rules
{
using System.Collections.Generic;
using chocolatey.infrastructure.rules;
using NuGet.Packaging;

internal sealed class IconMetadataRule : IMetadataRule
{
public IEnumerable<RuleResult> validate(NuspecReader reader)
{
if (!(reader.GetIcon() is null))
{
yield return new RuleResult(RuleType.Error, "<icon> elements are not supported in Chocolatey CLI, use <iconUrl> instead.");
}
}
}
}
Loading

0 comments on commit c6e30b7

Please sign in to comment.