From 010b5f9513782bf8091da56ab698ddbb13e08c5a Mon Sep 17 00:00:00 2001 From: Robert Dailey Date: Mon, 2 Oct 2023 13:22:39 -0500 Subject: [PATCH] fix: Add QP validation for groups with less than 2 qualities --- CHANGELOG.md | 3 +- .../ConfigYamlDataObjectsValidation.cs | 17 ++++ .../ConfigYamlDataObjectsValidationTest.cs | 79 +++++++++++++++++++ 3 files changed, 98 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 373f8064..e2c7df12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed -- Sync file naming configuration even if `rename` is not set to `true`. +- Media Naming: Sync file naming configuration even if `rename` is not set to `true`. +- Quality Profiles: Validation check added for quality groups with less than 2 qualities. ## [6.0.0] - 2023-09-29 diff --git a/src/Recyclarr.Config/Parsing/ConfigYamlDataObjectsValidation.cs b/src/Recyclarr.Config/Parsing/ConfigYamlDataObjectsValidation.cs index b14f88c9..cb3cf9d1 100644 --- a/src/Recyclarr.Config/Parsing/ConfigYamlDataObjectsValidation.cs +++ b/src/Recyclarr.Config/Parsing/ConfigYamlDataObjectsValidation.cs @@ -116,6 +116,7 @@ public class QualityProfileConfigYamlValidator : AbstractValidator x.Qualities) .Custom(ValidateHaveNoDuplicates!) + .Custom(ValidateGroupQualityCount!) .Must(x => x!.Any(y => y.Enabled is true or null)) .WithMessage(x => $"For profile {x.Name}, at least one explicitly listed quality under 'qualities' must be enabled.") @@ -137,6 +138,22 @@ public class QualityProfileConfigYamlValidator : AbstractValidator x is {Upgrade.Allowed: not false, Qualities.Count: > 0}); } + private static void ValidateGroupQualityCount( + IReadOnlyCollection qualities, + ValidationContext context) + { + // Find groups with less than 2 items + var invalidCount = qualities + .Count(x => x.Qualities?.Count < 2); + + if (invalidCount != 0) + { + var profile = context.InstanceToValidate; + context.AddFailure( + $"For profile {profile.Name}, 'qualities' contains {invalidCount} groups with less than 2 qualities"); + } + } + private static void ValidateHaveNoDuplicates( IReadOnlyCollection qualities, ValidationContext context) diff --git a/src/tests/Recyclarr.Tests/Config/Parsing/ConfigYamlDataObjectsValidationTest.cs b/src/tests/Recyclarr.Tests/Config/Parsing/ConfigYamlDataObjectsValidationTest.cs index 188046c5..a4118061 100644 --- a/src/tests/Recyclarr.Tests/Config/Parsing/ConfigYamlDataObjectsValidationTest.cs +++ b/src/tests/Recyclarr.Tests/Config/Parsing/ConfigYamlDataObjectsValidationTest.cs @@ -174,4 +174,83 @@ public class ConfigYamlDataObjectsValidationTest result.Errors.Select(x => x.ErrorMessage).Should().BeEquivalentTo( $"For profile {data.Name}, 'until_quality' must not refer to explicitly disabled qualities"); } + + [Test] + public void Empty_qualities_in_groups_not_allowed() + { + var data = new QualityProfileConfigYaml + { + Name = "Profile", + Qualities = new[] + { + new QualityProfileQualityConfigYaml + { + Name = "Group", + Qualities = Array.Empty() + } + } + }; + + var validator = new QualityProfileConfigYamlValidator(); + var result = validator.TestValidate(data); + + result.ShouldHaveValidationErrorFor(x => x.Qualities); + + result.Errors.Select(x => x.ErrorMessage).Should().BeEquivalentTo( + $"For profile {data.Name}, 'qualities' contains 1 groups with less than 2 qualities"); + } + + [Test] + public void Only_one_quality_in_groups_not_allowed() + { + var data = new QualityProfileConfigYaml + { + Name = "Profile", + Qualities = new[] + { + new QualityProfileQualityConfigYaml + { + Name = "Group", + Qualities = new[] + { + "One Quality" + } + } + } + }; + + var validator = new QualityProfileConfigYamlValidator(); + var result = validator.TestValidate(data); + + result.ShouldHaveValidationErrorFor(x => x.Qualities); + + result.Errors.Select(x => x.ErrorMessage).Should().BeEquivalentTo( + $"For profile {data.Name}, 'qualities' contains 1 groups with less than 2 qualities"); + } + + [Test] + public void Two_qualities_in_group_passes_validation() + { + var data = new QualityProfileConfigYaml + { + Name = "Profile", + Qualities = new[] + { + new QualityProfileQualityConfigYaml + { + Name = "Group", + Qualities = new[] + { + "One Quality", + "Two Quality" + } + } + } + }; + + var validator = new QualityProfileConfigYamlValidator(); + var result = validator.TestValidate(data); + + result.ShouldNotHaveAnyValidationErrors(); + } }