Fixed: Cutoff Specification not Respecting Profile Order (#660)
* Fixed: Cutoff Specification not Repsecting Profile Order * Fixed: Incorrect wording in UpgradeAllowed logging * Fixed: Change Logic to update if upgrade for any, downgrade for none. * Fixed: Removed Double Preferred Word Logic * New: Add Test Cases to Disk Upgrade Spec * Fixed: Cleanup UpgradableSpecification * Add ConcatToString extension and fix logging * Fixed: Enum Naming, Commaspull/693/head
parent
0ebaa90f54
commit
4d8bcd12e3
@ -0,0 +1,293 @@
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Profiles.Qualities;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.DecisionEngine.Specifications;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Languages;
|
||||
using NzbDrone.Core.Profiles.Languages;
|
||||
using NzbDrone.Core.Test.Languages;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class UpgradeAllowedSpecificationFixture : CoreTest<UpgradableSpecification>
|
||||
{
|
||||
[Test]
|
||||
public void should_return_false_when_quality_are_the_same_language_is_better_and_upgrade_allowed_is_false_for_language_profile()
|
||||
{
|
||||
Subject.IsUpgradeAllowed(
|
||||
new QualityProfile
|
||||
{
|
||||
Cutoff = Quality.FLAC.Id,
|
||||
Items = Qualities.QualityFixture.GetDefaultQualities(),
|
||||
UpgradeAllowed = true
|
||||
},
|
||||
new LanguageProfile
|
||||
{
|
||||
Languages = LanguageFixture.GetDefaultLanguages(Language.English, Language.French),
|
||||
Cutoff = Language.French,
|
||||
UpgradeAllowed = false
|
||||
},
|
||||
new List<QualityModel> { new QualityModel(Quality.MP3_320) },
|
||||
new List<Language> { Language.English },
|
||||
new QualityModel(Quality.MP3_320),
|
||||
Language.French
|
||||
).Should().BeFalse();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_false_when_quality_is_better_languages_are_the_same_and_upgrade_allowed_is_false_for_quality_profile()
|
||||
{
|
||||
Subject.IsUpgradeAllowed(
|
||||
new QualityProfile
|
||||
{
|
||||
Cutoff = Quality.FLAC.Id,
|
||||
Items = Qualities.QualityFixture.GetDefaultQualities(),
|
||||
UpgradeAllowed = false
|
||||
},
|
||||
new LanguageProfile
|
||||
{
|
||||
Languages = LanguageFixture.GetDefaultLanguages(Language.English),
|
||||
Cutoff = Language.English,
|
||||
UpgradeAllowed = true
|
||||
},
|
||||
new List<QualityModel> { new QualityModel(Quality.MP3_320) },
|
||||
new List<Language> { Language.English },
|
||||
new QualityModel(Quality.FLAC),
|
||||
Language.English
|
||||
).Should().BeFalse();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_true_for_language_upgrade_when_upgrading_is_allowed()
|
||||
{
|
||||
Subject.IsUpgradeAllowed(
|
||||
new QualityProfile
|
||||
{
|
||||
Cutoff = Quality.FLAC.Id,
|
||||
Items = Qualities.QualityFixture.GetDefaultQualities(),
|
||||
UpgradeAllowed = true
|
||||
},
|
||||
new LanguageProfile
|
||||
{
|
||||
Languages = LanguageFixture.GetDefaultLanguages(Language.English, Language.French),
|
||||
Cutoff = Language.French,
|
||||
UpgradeAllowed = true
|
||||
},
|
||||
new List<QualityModel> { new QualityModel(Quality.MP3_320) },
|
||||
new List<Language> { Language.English },
|
||||
new QualityModel(Quality.MP3_320),
|
||||
Language.French
|
||||
).Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_true_for_same_language_when_upgrading_is_allowed()
|
||||
{
|
||||
Subject.IsUpgradeAllowed(
|
||||
new QualityProfile
|
||||
{
|
||||
Cutoff = Quality.FLAC.Id,
|
||||
Items = Qualities.QualityFixture.GetDefaultQualities(),
|
||||
UpgradeAllowed = true
|
||||
},
|
||||
new LanguageProfile
|
||||
{
|
||||
Languages = LanguageFixture.GetDefaultLanguages(Language.English, Language.French),
|
||||
Cutoff = Language.French,
|
||||
UpgradeAllowed = true
|
||||
},
|
||||
new List<QualityModel> { new QualityModel(Quality.MP3_320) },
|
||||
new List<Language> { Language.English },
|
||||
new QualityModel(Quality.MP3_320),
|
||||
Language.English
|
||||
).Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_true_for_same_language_when_upgrading_is_not_allowed()
|
||||
{
|
||||
Subject.IsUpgradeAllowed(
|
||||
new QualityProfile
|
||||
{
|
||||
Cutoff = Quality.FLAC.Id,
|
||||
Items = Qualities.QualityFixture.GetDefaultQualities(),
|
||||
UpgradeAllowed = true
|
||||
},
|
||||
new LanguageProfile
|
||||
{
|
||||
Languages = LanguageFixture.GetDefaultLanguages(Language.English, Language.French),
|
||||
Cutoff = Language.French,
|
||||
UpgradeAllowed = false
|
||||
},
|
||||
new List<QualityModel> { new QualityModel(Quality.MP3_320) },
|
||||
new List<Language> { Language.French },
|
||||
new QualityModel(Quality.MP3_320),
|
||||
Language.English
|
||||
).Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_true_for_lower_language_when_upgrading_is_allowed()
|
||||
{
|
||||
Subject.IsUpgradeAllowed(
|
||||
new QualityProfile
|
||||
{
|
||||
Cutoff = Quality.FLAC.Id,
|
||||
Items = Qualities.QualityFixture.GetDefaultQualities(),
|
||||
UpgradeAllowed = true
|
||||
},
|
||||
new LanguageProfile
|
||||
{
|
||||
Languages = LanguageFixture.GetDefaultLanguages(Language.English, Language.French),
|
||||
Cutoff = Language.French,
|
||||
UpgradeAllowed = true
|
||||
},
|
||||
new List<QualityModel> { new QualityModel(Quality.MP3_320) },
|
||||
new List<Language> { Language.French },
|
||||
new QualityModel(Quality.MP3_320),
|
||||
Language.English
|
||||
).Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_true_for_lower_language_when_upgrading_is_not_allowed()
|
||||
{
|
||||
Subject.IsUpgradeAllowed(
|
||||
new QualityProfile
|
||||
{
|
||||
Cutoff = Quality.FLAC.Id,
|
||||
Items = Qualities.QualityFixture.GetDefaultQualities(),
|
||||
UpgradeAllowed = true
|
||||
},
|
||||
new LanguageProfile
|
||||
{
|
||||
Languages = LanguageFixture.GetDefaultLanguages(Language.English, Language.French),
|
||||
Cutoff = Language.French,
|
||||
UpgradeAllowed = false
|
||||
},
|
||||
new List<QualityModel> { new QualityModel(Quality.MP3_320) },
|
||||
new List<Language> { Language.French },
|
||||
new QualityModel(Quality.MP3_320),
|
||||
Language.English
|
||||
).Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_true_for_quality_upgrade_when_upgrading_is_allowed()
|
||||
{
|
||||
Subject.IsUpgradeAllowed(
|
||||
new QualityProfile
|
||||
{
|
||||
Cutoff = Quality.FLAC.Id,
|
||||
Items = Qualities.QualityFixture.GetDefaultQualities(),
|
||||
UpgradeAllowed = true
|
||||
},
|
||||
new LanguageProfile
|
||||
{
|
||||
Languages = LanguageFixture.GetDefaultLanguages(Language.English),
|
||||
Cutoff = Language.English,
|
||||
UpgradeAllowed = true
|
||||
},
|
||||
new List<QualityModel> { new QualityModel(Quality.MP3_320) },
|
||||
new List<Language> { Language.English },
|
||||
new QualityModel(Quality.FLAC),
|
||||
Language.English
|
||||
).Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_true_for_same_quality_when_upgrading_is_allowed()
|
||||
{
|
||||
Subject.IsUpgradeAllowed(
|
||||
new QualityProfile
|
||||
{
|
||||
Cutoff = Quality.FLAC.Id,
|
||||
Items = Qualities.QualityFixture.GetDefaultQualities(),
|
||||
UpgradeAllowed = true
|
||||
},
|
||||
new LanguageProfile
|
||||
{
|
||||
Languages = LanguageFixture.GetDefaultLanguages(Language.English),
|
||||
Cutoff = Language.English,
|
||||
UpgradeAllowed = true
|
||||
},
|
||||
new List<QualityModel> { new QualityModel(Quality.MP3_320) },
|
||||
new List<Language> { Language.English },
|
||||
new QualityModel(Quality.MP3_320),
|
||||
Language.English
|
||||
).Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_true_for_same_quality_when_upgrading_is_not_allowed()
|
||||
{
|
||||
Subject.IsUpgradeAllowed(
|
||||
new QualityProfile
|
||||
{
|
||||
Cutoff = Quality.FLAC.Id,
|
||||
Items = Qualities.QualityFixture.GetDefaultQualities(),
|
||||
UpgradeAllowed = false
|
||||
},
|
||||
new LanguageProfile
|
||||
{
|
||||
Languages = LanguageFixture.GetDefaultLanguages(Language.English),
|
||||
Cutoff = Language.English,
|
||||
UpgradeAllowed = true
|
||||
},
|
||||
new List<QualityModel> { new QualityModel(Quality.MP3_320) },
|
||||
new List<Language> { Language.English },
|
||||
new QualityModel(Quality.MP3_320),
|
||||
Language.English
|
||||
).Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_true_for_lower_quality_when_upgrading_is_allowed()
|
||||
{
|
||||
Subject.IsUpgradeAllowed(
|
||||
new QualityProfile
|
||||
{
|
||||
Cutoff = Quality.FLAC.Id,
|
||||
Items = Qualities.QualityFixture.GetDefaultQualities(),
|
||||
UpgradeAllowed = true
|
||||
},
|
||||
new LanguageProfile
|
||||
{
|
||||
Languages = LanguageFixture.GetDefaultLanguages(Language.English),
|
||||
Cutoff = Language.English,
|
||||
UpgradeAllowed = true
|
||||
},
|
||||
new List<QualityModel> { new QualityModel(Quality.MP3_320) },
|
||||
new List<Language> { Language.English },
|
||||
new QualityModel(Quality.MP3_256),
|
||||
Language.English
|
||||
).Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_true_for_lower_quality_when_upgrading_is_not_allowed()
|
||||
{
|
||||
Subject.IsUpgradeAllowed(
|
||||
new QualityProfile
|
||||
{
|
||||
Cutoff = Quality.FLAC.Id,
|
||||
Items = Qualities.QualityFixture.GetDefaultQualities(),
|
||||
UpgradeAllowed = false
|
||||
},
|
||||
new LanguageProfile
|
||||
{
|
||||
Languages = LanguageFixture.GetDefaultLanguages(Language.English),
|
||||
Cutoff = Language.English,
|
||||
UpgradeAllowed = true
|
||||
},
|
||||
new List<QualityModel>{ new QualityModel(Quality.MP3_320) },
|
||||
new List<Language> { Language.English },
|
||||
new QualityModel(Quality.MP3_256),
|
||||
Language.English
|
||||
).Should().BeTrue();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
using NLog;
|
||||
using NzbDrone.Core.Languages;
|
||||
using NzbDrone.Core.Profiles;
|
||||
using NzbDrone.Core.Qualities;
|
||||
|
||||
namespace NzbDrone.Core.DecisionEngine
|
||||
{
|
||||
public interface ILanguageUpgradableSpecification
|
||||
{
|
||||
bool IsUpgradable(Profile profile, LanguageModel currentLanguage, LanguageModel newLanguage = null);
|
||||
bool CutoffNotMet(Profile profile, LanguageModel currentLanguage, LanguageModel newLanguage = null);
|
||||
bool IsRevisionUpgrade(LanguageModel currentLanguage, LanguageModel newLanguage);
|
||||
}
|
||||
|
||||
public class LanguageUpgradableSpecification : ILanguageUpgradableSpecification
|
||||
{
|
||||
private readonly Logger _logger;
|
||||
|
||||
public LanguageUpgradableSpecification(Logger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public bool IsUpgradable(Profile profile, LanguageModel currentLanguage, LanguageModel newLanguage = null)
|
||||
{
|
||||
if (newLanguage != null)
|
||||
{
|
||||
int compare = new LanguageModelComparer(profile).Compare(newLanguage, currentLanguage);
|
||||
if (compare <= 0)
|
||||
{
|
||||
_logger.Debug("existing item has better or equal language. skipping");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsRevisionUpgrade(currentLanguage, newLanguage))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool CutoffNotMet(Profile profile, LanguageModel currentLanguage, LanguageModel newLanguage = null)
|
||||
{
|
||||
int compare = new LanguageModelComparer(profile).Compare(currentLanguage.Language, profile.Languages.Find(v => v.Allowed == true).Language);
|
||||
|
||||
if (compare >= 0)
|
||||
{
|
||||
if (newLanguage != null && IsRevisionUpgrade(currentLanguage, newLanguage))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
_logger.Debug("Existing item meets cut-off. skipping.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool IsRevisionUpgrade(LanguageModel currentLanguage, LanguageModel newLanguage)
|
||||
{
|
||||
int compare = newLanguage.Revision.CompareTo(currentLanguage.Revision);
|
||||
|
||||
if (currentLanguage.Language == newLanguage.Language && compare > 0)
|
||||
{
|
||||
_logger.Debug("New language is a better revision for existing quality");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.Music;
|
||||
using NzbDrone.Common.Cache;
|
||||
using NzbDrone.Core.Profiles.Releases;
|
||||
using NzbDrone.Common.Extensions;
|
||||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class UpgradeAllowedSpecification : IDecisionEngineSpecification
|
||||
{
|
||||
private readonly UpgradableSpecification _upgradableSpecification;
|
||||
private readonly IMediaFileService _mediaFileService;
|
||||
private readonly ITrackService _trackService;
|
||||
private readonly Logger _logger;
|
||||
private readonly ICached<bool> _missingFilesCache;
|
||||
|
||||
public UpgradeAllowedSpecification(UpgradableSpecification upgradableSpecification,
|
||||
Logger logger,
|
||||
ICacheManager cacheManager,
|
||||
IMediaFileService mediaFileService,
|
||||
ITrackService trackService)
|
||||
{
|
||||
_upgradableSpecification = upgradableSpecification;
|
||||
_mediaFileService = mediaFileService;
|
||||
_trackService = trackService;
|
||||
_missingFilesCache = cacheManager.GetCache<bool>(GetType());
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||
public RejectionType Type => RejectionType.Permanent;
|
||||
|
||||
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
var qualityProfile = subject.Artist.QualityProfile.Value;
|
||||
var languageProfile = subject.Artist.LanguageProfile.Value;
|
||||
|
||||
foreach (var album in subject.Albums)
|
||||
{
|
||||
var tracksMissing = _missingFilesCache.Get(album.Id.ToString(), () => _trackService.TracksWithoutFiles(album.Id).Any(),
|
||||
TimeSpan.FromSeconds(30));
|
||||
|
||||
var trackFiles = _mediaFileService.GetFilesByAlbum(album.Id);
|
||||
|
||||
if (!tracksMissing && trackFiles.Any())
|
||||
{
|
||||
// Get a distinct list of all current track qualities and languages for a given album
|
||||
var currentQualities = trackFiles.Select(c => c.Quality).Distinct().ToList();
|
||||
var currentLanguages = trackFiles.Select(c => c.Language).Distinct().ToList();
|
||||
|
||||
_logger.Debug("Comparing file quality and language with report. Existing files contain {0} : {1}", currentQualities.ConcatToString(), currentLanguages.ConcatToString());
|
||||
|
||||
if (!_upgradableSpecification.IsUpgradeAllowed(qualityProfile,
|
||||
languageProfile,
|
||||
currentQualities,
|
||||
currentLanguages,
|
||||
subject.ParsedAlbumInfo.Quality,
|
||||
subject.ParsedAlbumInfo.Language))
|
||||
{
|
||||
_logger.Debug("Upgrading is not allowed by the quality or language profile");
|
||||
|
||||
return Decision.Reject("Existing files and the Quality or Language profile does not allow upgrades");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in new issue