From 042840b8bc560e71a78eb4d994416d27c1652560 Mon Sep 17 00:00:00 2001 From: Robert Dailey Date: Sat, 17 Aug 2024 12:41:08 -0500 Subject: [PATCH] fix: Use new quality size limits in Radarr & Sonarr - Max/Preferred in Sonarr bumped to 1000/995. - Max/Preferred in Radarr bumped to 2000/1999. --- CHANGELOG.md | 6 ++++ .../PipelinePhases/CustomFormatConfigPhase.cs | 2 +- .../Pipelines/Generic/GenericSyncPipeline.cs | 2 +- .../Pipelines/Generic/IConfigPipelinePhase.cs | 2 +- .../PipelinePhases/MediaNamingConfigPhase.cs | 2 +- .../QualityProfileConfigPhase.cs | 2 +- .../Limits/QualityItemLimitFactory.cs | 8 ++--- .../Limits/RadarrQualityItemLimitFetcher.cs | 25 ++++++++++++++ .../Limits/RadarrQualityItemLimits.cs | 9 ----- .../Limits/SonarrQualityItemLimitFetcher.cs | 25 ++++++++++++++ .../Limits/SonarrQualityItemLimits.cs | 9 ----- .../PipelinePhases/QualitySizeConfigPhase.cs | 13 ++++---- .../QualitySize/QualitySizeAutofacModule.cs | 8 +++-- .../Radarr/RadarrCapabilities.cs | 7 ++-- .../Radarr/RadarrCapabilityFetcher.cs | 2 +- .../Sonarr/SonarrCapabilities.cs | 13 ++------ .../Sonarr/SonarrCapabilityFetcher.cs | 5 +-- .../QualitySize/IQualityItemLimitFetcher.cs | 8 +++++ .../QualitySize/IQualityItemLimits.cs | 7 ---- .../QualitySize/QualityItemWithLimits.cs | 33 +++++++++++-------- .../CustomFormatConfigPhaseTest.cs | 4 +-- .../QualityProfileConfigPhaseTest.cs | 14 ++++---- .../QualitySizeConfigPhaseTest.cs | 25 +++++++------- .../NewQualitySize.cs | 4 ++- .../TestQualityItemLimits.cs | 7 +--- .../QualitySize/QualityItemWithLimitsTest.cs | 26 ++++++--------- 26 files changed, 146 insertions(+), 122 deletions(-) create mode 100644 src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/Limits/RadarrQualityItemLimitFetcher.cs delete mode 100644 src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/Limits/RadarrQualityItemLimits.cs create mode 100644 src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/Limits/SonarrQualityItemLimitFetcher.cs delete mode 100644 src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/Limits/SonarrQualityItemLimits.cs create mode 100644 src/Recyclarr.TrashGuide/QualitySize/IQualityItemLimitFetcher.cs delete mode 100644 src/Recyclarr.TrashGuide/QualitySize/IQualityItemLimits.cs diff --git a/CHANGELOG.md b/CHANGELOG.md index f23a6796..27f9c19a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed + +- Quality Definition: Support new quality upper limits for Sonarr (1000) and Radarr (2000). This is + a backward compatible change, so older versions of Sonarr and Radarr will continue to use the + correct upper limits. + ## [7.2.1] - 2024-08-03 ### Fixed diff --git a/src/Recyclarr.Cli/Pipelines/CustomFormat/PipelinePhases/CustomFormatConfigPhase.cs b/src/Recyclarr.Cli/Pipelines/CustomFormat/PipelinePhases/CustomFormatConfigPhase.cs index 929f6c6d..c4cb016f 100644 --- a/src/Recyclarr.Cli/Pipelines/CustomFormat/PipelinePhases/CustomFormatConfigPhase.cs +++ b/src/Recyclarr.Cli/Pipelines/CustomFormat/PipelinePhases/CustomFormatConfigPhase.cs @@ -15,7 +15,7 @@ public class CustomFormatConfigPhase( IServiceConfiguration config) : IConfigPipelinePhase { - public Task Execute(CustomFormatPipelineContext context) + public Task Execute(CustomFormatPipelineContext context, CancellationToken ct) { // Match custom formats in the YAML config to those in the guide, by Trash ID // diff --git a/src/Recyclarr.Cli/Pipelines/Generic/GenericSyncPipeline.cs b/src/Recyclarr.Cli/Pipelines/Generic/GenericSyncPipeline.cs index 44fabea5..11a57572 100644 --- a/src/Recyclarr.Cli/Pipelines/Generic/GenericSyncPipeline.cs +++ b/src/Recyclarr.Cli/Pipelines/Generic/GenericSyncPipeline.cs @@ -22,7 +22,7 @@ public class GenericSyncPipeline( return; } - await phases.ConfigPhase.Execute(context); + await phases.ConfigPhase.Execute(context, ct); if (phases.LogPhase.LogConfigPhaseAndExitIfNeeded(context)) { return; diff --git a/src/Recyclarr.Cli/Pipelines/Generic/IConfigPipelinePhase.cs b/src/Recyclarr.Cli/Pipelines/Generic/IConfigPipelinePhase.cs index b1dcc361..20b8aa6b 100644 --- a/src/Recyclarr.Cli/Pipelines/Generic/IConfigPipelinePhase.cs +++ b/src/Recyclarr.Cli/Pipelines/Generic/IConfigPipelinePhase.cs @@ -3,5 +3,5 @@ namespace Recyclarr.Cli.Pipelines.Generic; public interface IConfigPipelinePhase where TContext : IPipelineContext { - Task Execute(TContext context); + Task Execute(TContext context, CancellationToken ct); } diff --git a/src/Recyclarr.Cli/Pipelines/MediaNaming/PipelinePhases/MediaNamingConfigPhase.cs b/src/Recyclarr.Cli/Pipelines/MediaNaming/PipelinePhases/MediaNamingConfigPhase.cs index e103d719..c183de66 100644 --- a/src/Recyclarr.Cli/Pipelines/MediaNaming/PipelinePhases/MediaNamingConfigPhase.cs +++ b/src/Recyclarr.Cli/Pipelines/MediaNaming/PipelinePhases/MediaNamingConfigPhase.cs @@ -22,7 +22,7 @@ public class MediaNamingConfigPhase( IServiceConfiguration config) : IConfigPipelinePhase { - public async Task Execute(MediaNamingPipelineContext context) + public async Task Execute(MediaNamingPipelineContext context, CancellationToken ct) { var lookup = new NamingFormatLookup(); var strategy = configPhaseStrategyFactory[config.ServiceType]; diff --git a/src/Recyclarr.Cli/Pipelines/QualityProfile/PipelinePhases/QualityProfileConfigPhase.cs b/src/Recyclarr.Cli/Pipelines/QualityProfile/PipelinePhases/QualityProfileConfigPhase.cs index 00424e42..77d7a6c3 100644 --- a/src/Recyclarr.Cli/Pipelines/QualityProfile/PipelinePhases/QualityProfileConfigPhase.cs +++ b/src/Recyclarr.Cli/Pipelines/QualityProfile/PipelinePhases/QualityProfileConfigPhase.cs @@ -10,7 +10,7 @@ namespace Recyclarr.Cli.Pipelines.QualityProfile.PipelinePhases; public class QualityProfileConfigPhase(ILogger log, ProcessedCustomFormatCache cache, IServiceConfiguration config) : IConfigPipelinePhase { - public Task Execute(QualityProfilePipelineContext context) + public Task Execute(QualityProfilePipelineContext context, CancellationToken ct) { // 1. For each group of CFs that has a quality profile specified // 2. For each quality profile score config in that CF group diff --git a/src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/Limits/QualityItemLimitFactory.cs b/src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/Limits/QualityItemLimitFactory.cs index 66a7c8c1..c9fdf7a1 100644 --- a/src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/Limits/QualityItemLimitFactory.cs +++ b/src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/Limits/QualityItemLimitFactory.cs @@ -4,16 +4,16 @@ using Recyclarr.TrashGuide.QualitySize; namespace Recyclarr.Cli.Pipelines.QualitySize.PipelinePhases.Limits; -public class QualityItemLimitFactory(IIndex limitFactory) +public class QualityItemLimitFactory(IIndex limitFactory) { - public QualityItemWithLimits Create(QualityItem item, SupportedServices serviceType) + public async Task Create(SupportedServices serviceType, CancellationToken ct) { - if (!limitFactory.TryGetValue(serviceType, out var limits)) + if (!limitFactory.TryGetValue(serviceType, out var limitFetcher)) { throw new ArgumentOutOfRangeException(nameof(serviceType), serviceType, "No quality item limits defined for this service type"); } - return new QualityItemWithLimits(item, limits); + return await limitFetcher.GetLimits(ct); } } diff --git a/src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/Limits/RadarrQualityItemLimitFetcher.cs b/src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/Limits/RadarrQualityItemLimitFetcher.cs new file mode 100644 index 00000000..f0262e10 --- /dev/null +++ b/src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/Limits/RadarrQualityItemLimitFetcher.cs @@ -0,0 +1,25 @@ +using Recyclarr.Compatibility.Radarr; +using Recyclarr.TrashGuide.QualitySize; + +namespace Recyclarr.Cli.Pipelines.QualitySize.PipelinePhases.Limits; + +public class RadarrQualityItemLimitFetcher(IRadarrCapabilityFetcher capabilityFetcher) : IQualityItemLimitFetcher +{ + private QualityItemLimits? _cachedLimits; + + public async Task GetLimits(CancellationToken ct) + { + // ReSharper disable once InvertIf + if (_cachedLimits is null) + { + var capabilities = await capabilityFetcher.GetCapabilities(ct); + _cachedLimits = capabilities switch + { + {QualityDefinitionLimitsIncreased: true} => new QualityItemLimits(2000m, 1999m), + _ => new QualityItemLimits(400m, 399m) + }; + } + + return _cachedLimits; + } +} diff --git a/src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/Limits/RadarrQualityItemLimits.cs b/src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/Limits/RadarrQualityItemLimits.cs deleted file mode 100644 index 993d071b..00000000 --- a/src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/Limits/RadarrQualityItemLimits.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Recyclarr.TrashGuide.QualitySize; - -namespace Recyclarr.Cli.Pipelines.QualitySize.PipelinePhases.Limits; - -public class RadarrQualityItemLimits : IQualityItemLimits -{ - public decimal MaxLimit => 400m; - public decimal PreferredLimit => 399m; -} diff --git a/src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/Limits/SonarrQualityItemLimitFetcher.cs b/src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/Limits/SonarrQualityItemLimitFetcher.cs new file mode 100644 index 00000000..1bcb930d --- /dev/null +++ b/src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/Limits/SonarrQualityItemLimitFetcher.cs @@ -0,0 +1,25 @@ +using Recyclarr.Compatibility.Sonarr; +using Recyclarr.TrashGuide.QualitySize; + +namespace Recyclarr.Cli.Pipelines.QualitySize.PipelinePhases.Limits; + +public class SonarrQualityItemLimitFetcher(ISonarrCapabilityFetcher capabilityFetcher) : IQualityItemLimitFetcher +{ + private QualityItemLimits? _cachedLimits; + + public async Task GetLimits(CancellationToken ct) + { + // ReSharper disable once InvertIf + if (_cachedLimits is null) + { + var capabilities = await capabilityFetcher.GetCapabilities(ct); + _cachedLimits = capabilities switch + { + {QualityDefinitionLimitsIncreased: true} => new QualityItemLimits(1000m, 995m), + _ => new QualityItemLimits(400m, 395m) + }; + } + + return _cachedLimits; + } +} diff --git a/src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/Limits/SonarrQualityItemLimits.cs b/src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/Limits/SonarrQualityItemLimits.cs deleted file mode 100644 index 0fe96eac..00000000 --- a/src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/Limits/SonarrQualityItemLimits.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Recyclarr.TrashGuide.QualitySize; - -namespace Recyclarr.Cli.Pipelines.QualitySize.PipelinePhases.Limits; - -public class SonarrQualityItemLimits : IQualityItemLimits -{ - public decimal MaxLimit => 400m; - public decimal PreferredLimit => 395m; -} diff --git a/src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/QualitySizeConfigPhase.cs b/src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/QualitySizeConfigPhase.cs index 382e3513..88bf71fb 100644 --- a/src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/QualitySizeConfigPhase.cs +++ b/src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/QualitySizeConfigPhase.cs @@ -11,16 +11,16 @@ public class QualitySizeConfigPhase( ILogger log, IQualitySizeGuideService guide, IServiceConfiguration config, - QualityItemLimitFactory itemFactory) + QualityItemLimitFactory limitFactory) : IConfigPipelinePhase { - public Task Execute(QualitySizePipelineContext context) + public async Task Execute(QualitySizePipelineContext context, CancellationToken ct) { var configSizeData = config.QualityDefinition; if (configSizeData is null) { log.Debug("{Instance} has no quality definition", config.InstanceName); - return Task.CompletedTask; + return; } var guideSizeData = guide.GetQualitySizeData(config.ServiceType) @@ -29,16 +29,17 @@ public class QualitySizeConfigPhase( if (guideSizeData == null) { context.ConfigError = $"The specified quality definition type does not exist: {configSizeData.Type}"; - return Task.CompletedTask; + return; } + var itemLimits = await limitFactory.Create(config.ServiceType, ct); + var sizeDataWithThresholds = guideSizeData.Qualities - .Select(x => itemFactory.Create(x, config.ServiceType)) + .Select(x => new QualityItemWithLimits(x, itemLimits)) .ToList(); AdjustPreferredRatio(configSizeData, sizeDataWithThresholds); context.ConfigOutput = new ProcessedQualitySizeData(configSizeData.Type, sizeDataWithThresholds); - return Task.CompletedTask; } private void AdjustPreferredRatio(QualityDefinitionConfig configSizeData, List guideSizeData) diff --git a/src/Recyclarr.Cli/Pipelines/QualitySize/QualitySizeAutofacModule.cs b/src/Recyclarr.Cli/Pipelines/QualitySize/QualitySizeAutofacModule.cs index e0e0fe75..2f9a64cf 100644 --- a/src/Recyclarr.Cli/Pipelines/QualitySize/QualitySizeAutofacModule.cs +++ b/src/Recyclarr.Cli/Pipelines/QualitySize/QualitySizeAutofacModule.cs @@ -15,8 +15,12 @@ public class QualitySizeAutofacModule : Module // Setup factory for creation of concrete IQualityItemLimits types builder.RegisterType(); - builder.RegisterType().Keyed(SupportedServices.Radarr); - builder.RegisterType().Keyed(SupportedServices.Sonarr); + builder.RegisterType() + .Keyed(SupportedServices.Radarr) + .InstancePerLifetimeScope(); + builder.RegisterType() + .Keyed(SupportedServices.Sonarr) + .InstancePerLifetimeScope(); builder.RegisterTypes( typeof(QualitySizeConfigPhase), diff --git a/src/Recyclarr.Compatibility/Radarr/RadarrCapabilities.cs b/src/Recyclarr.Compatibility/Radarr/RadarrCapabilities.cs index e2f1bf79..ccf499f3 100644 --- a/src/Recyclarr.Compatibility/Radarr/RadarrCapabilities.cs +++ b/src/Recyclarr.Compatibility/Radarr/RadarrCapabilities.cs @@ -4,10 +4,7 @@ namespace Recyclarr.Compatibility.Radarr; // // May get used one day; keep the parameter around so that calling // code does not need to be changed later. -public record RadarrCapabilities(Version? Version) +public record RadarrCapabilities(Version Version) { - public RadarrCapabilities() - : this((Version?) null) - { - } + public bool QualityDefinitionLimitsIncreased => Version >= new Version(5, 9, 0, 9049); } diff --git a/src/Recyclarr.Compatibility/Radarr/RadarrCapabilityFetcher.cs b/src/Recyclarr.Compatibility/Radarr/RadarrCapabilityFetcher.cs index bd7d9aa2..bc5aa801 100644 --- a/src/Recyclarr.Compatibility/Radarr/RadarrCapabilityFetcher.cs +++ b/src/Recyclarr.Compatibility/Radarr/RadarrCapabilityFetcher.cs @@ -3,7 +3,7 @@ namespace Recyclarr.Compatibility.Radarr; public class RadarrCapabilityFetcher(IServiceInformation info) : ServiceCapabilityFetcher(info), IRadarrCapabilityFetcher { - protected override RadarrCapabilities BuildCapabilitiesObject(Version? version) + protected override RadarrCapabilities BuildCapabilitiesObject(Version version) { return new RadarrCapabilities(version); } diff --git a/src/Recyclarr.Compatibility/Sonarr/SonarrCapabilities.cs b/src/Recyclarr.Compatibility/Sonarr/SonarrCapabilities.cs index da9aad56..14739242 100644 --- a/src/Recyclarr.Compatibility/Sonarr/SonarrCapabilities.cs +++ b/src/Recyclarr.Compatibility/Sonarr/SonarrCapabilities.cs @@ -1,17 +1,8 @@ namespace Recyclarr.Compatibility.Sonarr; -public record SonarrCapabilities +public record SonarrCapabilities(Version Version) { - public SonarrCapabilities() - { - } - - public SonarrCapabilities(Version version) - { - Version = version; - } - public static Version MinimumVersion { get; } = new("4.0.0.0"); - public Version Version { get; init; } = new(); + public bool QualityDefinitionLimitsIncreased => Version >= new Version(4, 0, 8, 2158); } diff --git a/src/Recyclarr.Compatibility/Sonarr/SonarrCapabilityFetcher.cs b/src/Recyclarr.Compatibility/Sonarr/SonarrCapabilityFetcher.cs index 24991351..c7d25cd6 100644 --- a/src/Recyclarr.Compatibility/Sonarr/SonarrCapabilityFetcher.cs +++ b/src/Recyclarr.Compatibility/Sonarr/SonarrCapabilityFetcher.cs @@ -5,9 +5,6 @@ public class SonarrCapabilityFetcher(IServiceInformation info) { protected override SonarrCapabilities BuildCapabilitiesObject(Version version) { - return new SonarrCapabilities - { - Version = version - }; + return new SonarrCapabilities(version); } } diff --git a/src/Recyclarr.TrashGuide/QualitySize/IQualityItemLimitFetcher.cs b/src/Recyclarr.TrashGuide/QualitySize/IQualityItemLimitFetcher.cs new file mode 100644 index 00000000..1ac60411 --- /dev/null +++ b/src/Recyclarr.TrashGuide/QualitySize/IQualityItemLimitFetcher.cs @@ -0,0 +1,8 @@ +namespace Recyclarr.TrashGuide.QualitySize; + +public record QualityItemLimits(decimal MaxLimit, decimal PreferredLimit); + +public interface IQualityItemLimitFetcher +{ + Task GetLimits(CancellationToken ct); +} diff --git a/src/Recyclarr.TrashGuide/QualitySize/IQualityItemLimits.cs b/src/Recyclarr.TrashGuide/QualitySize/IQualityItemLimits.cs deleted file mode 100644 index f6d7c456..00000000 --- a/src/Recyclarr.TrashGuide/QualitySize/IQualityItemLimits.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Recyclarr.TrashGuide.QualitySize; - -public interface IQualityItemLimits -{ - decimal MaxLimit { get; } - decimal PreferredLimit { get; } -} diff --git a/src/Recyclarr.TrashGuide/QualitySize/QualityItemWithLimits.cs b/src/Recyclarr.TrashGuide/QualitySize/QualityItemWithLimits.cs index 879fbb1b..9e811ec2 100644 --- a/src/Recyclarr.TrashGuide/QualitySize/QualityItemWithLimits.cs +++ b/src/Recyclarr.TrashGuide/QualitySize/QualityItemWithLimits.cs @@ -3,18 +3,23 @@ using System.Text; namespace Recyclarr.TrashGuide.QualitySize; -public class QualityItemWithLimits(QualityItem item, IQualityItemLimits limits) +public class QualityItemWithLimits(QualityItem item, QualityItemLimits limits) { - public QualityItem Item => item; - public IQualityItemLimits Limits => limits; + public QualityItem Item { get; } = item with + { + Max = Math.Min(item.Max, limits.MaxLimit), + Preferred = Math.Min(item.Preferred, limits.PreferredLimit) + }; + + public QualityItemLimits Limits => limits; - public decimal MinForApi => item.Min; - public decimal? PreferredForApi => item.Preferred < limits.PreferredLimit ? item.Preferred : null; - public decimal? MaxForApi => item.Max < limits.MaxLimit ? item.Max : null; + public decimal MinForApi => Item.Min; + public decimal? PreferredForApi => Item.Preferred < Limits.PreferredLimit ? Item.Preferred : null; + public decimal? MaxForApi => Item.Max < Limits.MaxLimit ? Item.Max : null; - public string AnnotatedMin => item.Min.ToString(CultureInfo.InvariantCulture); - public string AnnotatedPreferred => AnnotatedValue(item.Preferred, limits.PreferredLimit); - public string AnnotatedMax => AnnotatedValue(item.Max, limits.MaxLimit); + public string AnnotatedMin => Item.Min.ToString(CultureInfo.InvariantCulture); + public string AnnotatedPreferred => AnnotatedValue(Item.Preferred, Limits.PreferredLimit); + public string AnnotatedMax => AnnotatedValue(Item.Max, Limits.MaxLimit); private static string AnnotatedValue(decimal value, decimal threshold) { @@ -29,17 +34,17 @@ public class QualityItemWithLimits(QualityItem item, IQualityItemLimits limits) public bool IsMinDifferent(decimal serviceValue) { - return serviceValue != item.Min; + return serviceValue != Item.Min; } public bool IsPreferredDifferent(decimal? serviceValue) { - return ValueWithThresholdIsDifferent(serviceValue, item.Preferred, limits.PreferredLimit); + return ValueWithThresholdIsDifferent(serviceValue, Item.Preferred, Limits.PreferredLimit); } public bool IsMaxDifferent(decimal? serviceValue) { - return ValueWithThresholdIsDifferent(serviceValue, item.Max, limits.MaxLimit); + return ValueWithThresholdIsDifferent(serviceValue, Item.Max, Limits.MaxLimit); } private static bool ValueWithThresholdIsDifferent(decimal? serviceValue, decimal guideValue, decimal threshold) @@ -54,7 +59,7 @@ public class QualityItemWithLimits(QualityItem item, IQualityItemLimits limits) public decimal InterpolatedPreferred(decimal ratio) { - var cappedMax = Math.Min(item.Max, limits.PreferredLimit); - return Math.Round(item.Min + (cappedMax - item.Min) * ratio, 1); + var cappedMax = Math.Min(Item.Max, Limits.PreferredLimit); + return Math.Round(Item.Min + (cappedMax - Item.Min) * ratio, 1); } } diff --git a/tests/Recyclarr.Cli.Tests/Pipelines/CustomFormat/PipelinePhases/CustomFormatConfigPhaseTest.cs b/tests/Recyclarr.Cli.Tests/Pipelines/CustomFormat/PipelinePhases/CustomFormatConfigPhaseTest.cs index c5dcd2ef..66d0ff78 100644 --- a/tests/Recyclarr.Cli.Tests/Pipelines/CustomFormat/PipelinePhases/CustomFormatConfigPhaseTest.cs +++ b/tests/Recyclarr.Cli.Tests/Pipelines/CustomFormat/PipelinePhases/CustomFormatConfigPhaseTest.cs @@ -38,7 +38,7 @@ public class CustomFormatConfigPhaseTest var context = new CustomFormatPipelineContext(); var sut = fixture.Create(); - sut.Execute(context); + sut.Execute(context, CancellationToken.None); context.ConfigOutput.Should().BeEquivalentTo([ NewCf.Data("one", "cf1"), @@ -74,7 +74,7 @@ public class CustomFormatConfigPhaseTest var context = new CustomFormatPipelineContext(); var sut = fixture.Create(); - sut.Execute(context); + sut.Execute(context, CancellationToken.None); context.ConfigOutput.Should().BeEmpty(); } diff --git a/tests/Recyclarr.Cli.Tests/Pipelines/QualityProfile/PipelinePhases/QualityProfileConfigPhaseTest.cs b/tests/Recyclarr.Cli.Tests/Pipelines/QualityProfile/PipelinePhases/QualityProfileConfigPhaseTest.cs index e77c6918..eea8ccad 100644 --- a/tests/Recyclarr.Cli.Tests/Pipelines/QualityProfile/PipelinePhases/QualityProfileConfigPhaseTest.cs +++ b/tests/Recyclarr.Cli.Tests/Pipelines/QualityProfile/PipelinePhases/QualityProfileConfigPhaseTest.cs @@ -45,7 +45,7 @@ public class QualityProfileConfigPhaseTest var context = new QualityProfilePipelineContext(); var sut = fixture.Create(); - sut.Execute(context); + sut.Execute(context, CancellationToken.None); context.ConfigOutput.Should().BeEquivalentTo([ NewQp.Processed("test_profile", ("id1", 1, 100), ("id2", 2, 100)) @@ -78,7 +78,7 @@ public class QualityProfileConfigPhaseTest var context = new QualityProfilePipelineContext(); var sut = fixture.Create(); - sut.Execute(context); + sut.Execute(context, CancellationToken.None); context.ConfigOutput.Should().BeEquivalentTo([ NewQp.Processed("test_profile", ("id1", 1, 100), ("id2", 2, 200)) @@ -111,7 +111,7 @@ public class QualityProfileConfigPhaseTest var context = new QualityProfilePipelineContext(); var sut = fixture.Create(); - sut.Execute(context); + sut.Execute(context, CancellationToken.None); context.ConfigOutput.Should().BeEquivalentTo([ NewQp.Processed("test_profile") @@ -170,7 +170,7 @@ public class QualityProfileConfigPhaseTest var context = new QualityProfilePipelineContext(); var sut = fixture.Create(); - sut.Execute(context); + sut.Execute(context, CancellationToken.None); context.ConfigOutput.Should().BeEquivalentTo([ NewQp.Processed("test_profile1", ("id1", 1, 100)), @@ -216,7 +216,7 @@ public class QualityProfileConfigPhaseTest var context = new QualityProfilePipelineContext(); var sut = fixture.Create(); - sut.Execute(context); + sut.Execute(context, CancellationToken.None); context.ConfigOutput.Should().BeEquivalentTo([ NewQp.Processed("test_profile", ("id1", 1, 102), ("id2", 2, 201)) with @@ -247,7 +247,7 @@ public class QualityProfileConfigPhaseTest var context = new QualityProfilePipelineContext(); var sut = fixture.Create(); - sut.Execute(context); + sut.Execute(context, CancellationToken.None); context.ConfigOutput.Should().BeEmpty(); } @@ -271,7 +271,7 @@ public class QualityProfileConfigPhaseTest var context = new QualityProfilePipelineContext(); var sut = fixture.Create(); - sut.Execute(context); + sut.Execute(context, CancellationToken.None); context.ConfigOutput.Should().BeEmpty(); } diff --git a/tests/Recyclarr.Cli.Tests/Pipelines/QualitySize/PipelinePhases/QualitySizeConfigPhaseTest.cs b/tests/Recyclarr.Cli.Tests/Pipelines/QualitySize/PipelinePhases/QualitySizeConfigPhaseTest.cs index 9c58f650..1e3f48f6 100644 --- a/tests/Recyclarr.Cli.Tests/Pipelines/QualitySize/PipelinePhases/QualitySizeConfigPhaseTest.cs +++ b/tests/Recyclarr.Cli.Tests/Pipelines/QualitySize/PipelinePhases/QualitySizeConfigPhaseTest.cs @@ -2,7 +2,6 @@ using NSubstitute.ReturnsExtensions; using Recyclarr.Cli.Pipelines.QualitySize; using Recyclarr.Cli.Pipelines.QualitySize.PipelinePhases; using Recyclarr.Config.Models; -using Recyclarr.Tests.TestLibrary; using Recyclarr.TrashGuide.QualitySize; namespace Recyclarr.Cli.Tests.Pipelines.QualitySize.PipelinePhases; @@ -11,20 +10,20 @@ namespace Recyclarr.Cli.Tests.Pipelines.QualitySize.PipelinePhases; public class QualitySizeConfigPhaseTest { [Test, AutoMockData] - public void Do_nothing_if_no_quality_definition( + public async Task Do_nothing_if_no_quality_definition( [Frozen] IServiceConfiguration config, QualitySizeConfigPhase sut) { var context = new QualitySizePipelineContext(); config.QualityDefinition.ReturnsNull(); - sut.Execute(context); + await sut.Execute(context, CancellationToken.None); context.ConfigOutput.Should().BeNull(); } [Test, AutoMockData] - public void Do_nothing_if_no_matching_quality_definition( + public async Task Do_nothing_if_no_matching_quality_definition( [Frozen] IQualitySizeGuideService guide, [Frozen] IServiceConfiguration config, QualitySizeConfigPhase sut) @@ -37,7 +36,7 @@ public class QualitySizeConfigPhaseTest var context = new QualitySizePipelineContext(); - sut.Execute(context); + await sut.Execute(context, CancellationToken.None); context.ConfigOutput.Should().BeNull(); } @@ -45,7 +44,7 @@ public class QualitySizeConfigPhaseTest [Test] [InlineAutoMockData("-0.1", "0")] [InlineAutoMockData("1.1", "1")] - public void Preferred_ratio_clamping_works( + public async Task Preferred_ratio_clamping_works( string testPreferred, string expectedPreferred, [Frozen] IQualitySizeGuideService guide, @@ -64,17 +63,16 @@ public class QualitySizeConfigPhaseTest var context = new QualitySizePipelineContext(); - sut.Execute(context); + await sut.Execute(context, CancellationToken.None); config.QualityDefinition.Should().NotBeNull(); config.QualityDefinition!.PreferredRatio.Should().Be(decimal.Parse(expectedPreferred)); } [Test, AutoMockData] - public void Preferred_is_set_via_ratio( + public async Task Preferred_is_set_via_ratio( [Frozen] IQualitySizeGuideService guide, [Frozen] IServiceConfiguration config, - [Frozen(Matching.ImplementedInterfaces)] TestQualityItemLimits limits, QualitySizeConfigPhase sut) { config.QualityDefinition.Returns(new QualityDefinitionConfig @@ -83,7 +81,8 @@ public class QualitySizeConfigPhaseTest PreferredRatio = 0.5m }); - guide.GetQualitySizeData(default!).ReturnsForAnyArgs([ + guide.GetQualitySizeData(default!).ReturnsForAnyArgs( + [ new QualitySizeData { Type = "real", @@ -96,7 +95,7 @@ public class QualitySizeConfigPhaseTest var context = new QualitySizePipelineContext(); - sut.Execute(context); + await sut.Execute(context, CancellationToken.None); context.ConfigOutput.Should().NotBeNull(); context.ConfigOutput!.Qualities.Select(x => x.Item).Should().BeEquivalentTo([ @@ -105,7 +104,7 @@ public class QualitySizeConfigPhaseTest } [Test, AutoMockData] - public void Preferred_is_set_via_guide( + public async Task Preferred_is_set_via_guide( [Frozen] IQualitySizeGuideService guide, [Frozen] IServiceConfiguration config, QualitySizeConfigPhase sut) @@ -128,7 +127,7 @@ public class QualitySizeConfigPhaseTest var context = new QualitySizePipelineContext(); - sut.Execute(context); + await sut.Execute(context, CancellationToken.None); context.ConfigOutput.Should().NotBeNull(); context.ConfigOutput!.Qualities.Select(x => x.Item).Should().BeEquivalentTo([ diff --git a/tests/Recyclarr.Tests.TestLibrary/NewQualitySize.cs b/tests/Recyclarr.Tests.TestLibrary/NewQualitySize.cs index bbab025a..243e9e90 100644 --- a/tests/Recyclarr.Tests.TestLibrary/NewQualitySize.cs +++ b/tests/Recyclarr.Tests.TestLibrary/NewQualitySize.cs @@ -7,6 +7,8 @@ public static class NewQualitySize public static QualityItemWithLimits WithLimits(string quality, decimal min, decimal max, decimal preferred) { var item = new QualityItem(quality, min, max, preferred); - return new QualityItemWithLimits(item, new TestQualityItemLimits()); + return new QualityItemWithLimits(item, new QualityItemLimits( + TestQualityItemLimits.MaxUnlimitedThreshold, + TestQualityItemLimits.PreferredUnlimitedThreshold)); } } diff --git a/tests/Recyclarr.Tests.TestLibrary/TestQualityItemLimits.cs b/tests/Recyclarr.Tests.TestLibrary/TestQualityItemLimits.cs index 98362e10..91f67986 100644 --- a/tests/Recyclarr.Tests.TestLibrary/TestQualityItemLimits.cs +++ b/tests/Recyclarr.Tests.TestLibrary/TestQualityItemLimits.cs @@ -1,12 +1,7 @@ -using Recyclarr.TrashGuide.QualitySize; - namespace Recyclarr.Tests.TestLibrary; -public class TestQualityItemLimits : IQualityItemLimits +public static class TestQualityItemLimits { public const decimal MaxUnlimitedThreshold = 400m; public const decimal PreferredUnlimitedThreshold = 400m; - - public decimal MaxLimit { get; set; } = MaxUnlimitedThreshold; - public decimal PreferredLimit { get; set; } = PreferredUnlimitedThreshold; } diff --git a/tests/Recyclarr.Tests/TrashGuide/QualitySize/QualityItemWithLimitsTest.cs b/tests/Recyclarr.Tests/TrashGuide/QualitySize/QualityItemWithLimitsTest.cs index 22ed397a..cb1f1ae5 100644 --- a/tests/Recyclarr.Tests/TrashGuide/QualitySize/QualityItemWithLimitsTest.cs +++ b/tests/Recyclarr.Tests/TrashGuide/QualitySize/QualityItemWithLimitsTest.cs @@ -1,4 +1,5 @@ using Recyclarr.Tests.TestLibrary; +using Recyclarr.TrashGuide.QualitySize; namespace Recyclarr.Tests.TrashGuide.QualitySize; @@ -70,14 +71,6 @@ public class QualityItemWithLimitsTest data.AnnotatedMax.Should().Be($"{testVal}"); } - [Test] - public void Max_AboveThreshold_EqualsSameValue() - { - const decimal testVal = TestQualityItemLimits.MaxUnlimitedThreshold + 1; - var data = NewQualitySize.WithLimits("", 0, testVal, 0); - data.Item.Max.Should().Be(testVal); - } - [Test] public void MaxForApi_AboveThreshold_EqualsNull() { @@ -187,14 +180,6 @@ public class QualityItemWithLimitsTest data.AnnotatedPreferred.Should().Be($"{testVal}"); } - [Test] - public void Preferred_AboveThreshold_EqualsSameValue() - { - const decimal testVal = TestQualityItemLimits.PreferredUnlimitedThreshold + 1; - var data = NewQualitySize.WithLimits("", 0, 0, testVal); - data.Item.Preferred.Should().Be(testVal); - } - [Test] public void PreferredForApi_AboveThreshold_EqualsNull() { @@ -217,4 +202,13 @@ public class QualityItemWithLimitsTest var data = NewQualitySize.WithLimits("", 0, 0, 0); data.PreferredForApi.Should().Be(0); } + + [Test] + public void Max_and_preferred_are_capped_when_over_limit() + { + var sut = new QualityItemWithLimits(new QualityItem("TestQuality", 10m, 100m, 100m), + new QualityItemLimits(50m, 70m)); + + sut.Item.Should().BeEquivalentTo(new QualityItem("TestQuality", 10m, 50m, 70m)); + } }