diff --git a/NzbDrone.Api/AutomapperBootstraper.cs b/NzbDrone.Api/AutomapperBootstraper.cs index e68f25fdd..10a1219f0 100644 --- a/NzbDrone.Api/AutomapperBootstraper.cs +++ b/NzbDrone.Api/AutomapperBootstraper.cs @@ -36,13 +36,6 @@ public static void InitializeAutomapper() Mapper.CreateMap() .ForMember(dest => dest.QualityId, opt => opt.MapFrom(src => src.Id)); - //Series - Mapper.CreateMap() - .ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.Id)) - .ForMember(dest => dest.CustomStartDate, opt => opt.ResolveUsing().FromMember(src => src.CustomStartDate)) - .ForMember(dest => dest.BacklogSetting, opt => opt.MapFrom(src => (Int32)src.BacklogSetting)) - .ForMember(dest => dest.NextAiring, opt => opt.ResolveUsing()) - .ForMember(dest => dest.QualityProfileName, opt => opt.MapFrom(src => src.QualityProfile.Name)); //Calendar Mapper.CreateMap() diff --git a/NzbDrone.Core.Test/DecisionEngineTests/AllowedDownloadSpecificationFixture.cs b/NzbDrone.Core.Test/DecisionEngineTests/AllowedDownloadSpecificationFixture.cs index ada780810..5b3e6fc71 100644 --- a/NzbDrone.Core.Test/DecisionEngineTests/AllowedDownloadSpecificationFixture.cs +++ b/NzbDrone.Core.Test/DecisionEngineTests/AllowedDownloadSpecificationFixture.cs @@ -37,12 +37,23 @@ public void Setup() _fail3 = new Mock(); _pass1.Setup(c => c.IsSatisfiedBy(It.IsAny())).Returns(true); + _pass1.Setup(c => c.RejectionReason).Returns("_pass1"); + _pass2.Setup(c => c.IsSatisfiedBy(It.IsAny())).Returns(true); + _pass2.Setup(c => c.RejectionReason).Returns("_pass2"); + _pass3.Setup(c => c.IsSatisfiedBy(It.IsAny())).Returns(true); + _pass3.Setup(c => c.RejectionReason).Returns("_pass3"); + _fail1.Setup(c => c.IsSatisfiedBy(It.IsAny())).Returns(false); + _fail1.Setup(c => c.RejectionReason).Returns("_fail1"); + _fail2.Setup(c => c.IsSatisfiedBy(It.IsAny())).Returns(false); + _fail2.Setup(c => c.RejectionReason).Returns("_fail2"); + _fail3.Setup(c => c.IsSatisfiedBy(It.IsAny())).Returns(false); + _fail3.Setup(c => c.RejectionReason).Returns("_fail3"); _reports = new List { new ReportInfo { Title = "The.Office.S03E115.DVDRip.XviD-OSiTV" } }; _remoteEpisode = new RemoteEpisode { Series = new Series() }; @@ -72,6 +83,17 @@ public void should_call_all_specifications() _pass3.Verify(c => c.IsSatisfiedBy(_remoteEpisode), Times.Once()); } + + [Test] + public void should_return_rejected_if_single_specs_fail() + { + GivenSpecifications(_fail1); + + var result = Subject.GetRssDecision(_reports); + + result.Single().Approved.Should().BeFalse(); + } + [Test] public void should_return_rejected_if_one_of_specs_fail() { diff --git a/NzbDrone.Core.Test/DecisionEngineTests/QualityAllowedByProfileSpecificationFixture.cs b/NzbDrone.Core.Test/DecisionEngineTests/QualityAllowedByProfileSpecificationFixture.cs index db4aa6360..a53568678 100644 --- a/NzbDrone.Core.Test/DecisionEngineTests/QualityAllowedByProfileSpecificationFixture.cs +++ b/NzbDrone.Core.Test/DecisionEngineTests/QualityAllowedByProfileSpecificationFixture.cs @@ -1,6 +1,8 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using FizzWare.NBuilder; using FluentAssertions; +using Marr.Data; using NUnit.Framework; using NzbDrone.Core.DecisionEngine.Specifications; using NzbDrone.Core.Parser.Model; @@ -34,7 +36,7 @@ public class QualityAllowedByProfileSpecificationFixture : CoreTest.CreateNew() - .With(c => c.QualityProfile = new QualityProfile { Cutoff = Quality.Bluray1080p }) + .With(c => c.QualityProfile = (LazyLoaded)new QualityProfile { Cutoff = Quality.Bluray1080p }) .Build(); remoteEpisode = new RemoteEpisode @@ -48,7 +50,7 @@ public void Setup() public void should_allow_if_quality_is_defined_in_profile(Quality qualityType) { remoteEpisode.ParsedEpisodeInfo.Quality.Quality = qualityType; - remoteEpisode.Series.QualityProfile.Allowed = new List { Quality.DVD, Quality.HDTV720p, Quality.Bluray1080p }; + remoteEpisode.Series.QualityProfile.Value.Allowed = new List { Quality.DVD, Quality.HDTV720p, Quality.Bluray1080p }; Subject.IsSatisfiedBy(remoteEpisode).Should().BeTrue(); } @@ -57,7 +59,7 @@ public void should_allow_if_quality_is_defined_in_profile(Quality qualityType) public void should_not_allow_if_quality_is_not_defined_in_profile(Quality qualityType) { remoteEpisode.ParsedEpisodeInfo.Quality.Quality = qualityType; - remoteEpisode.Series.QualityProfile.Allowed = new List { Quality.DVD, Quality.HDTV720p, Quality.Bluray1080p }; + remoteEpisode.Series.QualityProfile.Value.Allowed = new List { Quality.DVD, Quality.HDTV720p, Quality.Bluray1080p }; Subject.IsSatisfiedBy(remoteEpisode).Should().BeFalse(); } diff --git a/NzbDrone.Core.Test/JobTests/JobControllerFixture.cs b/NzbDrone.Core.Test/JobTests/JobControllerFixture.cs index 5ad9f3999..578ddb3ab 100644 --- a/NzbDrone.Core.Test/JobTests/JobControllerFixture.cs +++ b/NzbDrone.Core.Test/JobTests/JobControllerFixture.cs @@ -1,4 +1,5 @@ -using System.Linq; +/* +using System.Linq; using System; using System.Collections.Generic; using System.Threading; @@ -14,7 +15,7 @@ namespace NzbDrone.Core.Test.JobTests { - [TestFixture] + /* [TestFixture] [ExclusivelyUses("JOB_PROVIDER")] public class JobControllerFixture : CoreTest { @@ -225,6 +226,7 @@ public void scheduled_job_should_have_scheduler_as_source() Subject.Queue.Should().OnlyContain(c => c.Source == JobQueueItem.JobSourceType.Scheduler); WaitForQueue(); - } + }#1# } } +*/ diff --git a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj index ac4bb6bab..313744e89 100644 --- a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj +++ b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj @@ -142,6 +142,7 @@ + @@ -173,6 +174,7 @@ + @@ -346,7 +348,6 @@ - diff --git a/NzbDrone.Core.Test/Qualities/QualityProfileRepositoryFixture.cs b/NzbDrone.Core.Test/Qualities/QualityProfileRepositoryFixture.cs new file mode 100644 index 000000000..f82879953 --- /dev/null +++ b/NzbDrone.Core.Test/Qualities/QualityProfileRepositoryFixture.cs @@ -0,0 +1,39 @@ +using System.Collections.Generic; +using FluentAssertions; +using NUnit.Framework; +using NzbDrone.Core.Qualities; +using NzbDrone.Core.Test.Framework; + +namespace NzbDrone.Core.Test.Qualities +{ + [TestFixture] + + public class QualityProfileRepositoryFixture : DbTest + { + [Test] + public void should_be_able_to_read_and_write() + { + var profile = new QualityProfile + { + Allowed = new List + { + Quality.Bluray1080p, + Quality.DVD, + Quality.HDTV720p + }, + + Cutoff = Quality.Bluray1080p, + Name = "TestProfile" + }; + + Subject.Insert(profile); + + StoredModel.Name.Should().Be(profile.Name); + StoredModel.Cutoff.Should().Be(profile.Cutoff); + + StoredModel.Allowed.Should().BeEquivalentTo(profile.Allowed); + + + } + } +} \ No newline at end of file diff --git a/NzbDrone.Core.Test/TvTests/SeriesRepositoryTests/QualityProfileRepositoryFixture.cs b/NzbDrone.Core.Test/TvTests/SeriesRepositoryTests/QualityProfileRepositoryFixture.cs new file mode 100644 index 000000000..83eac638f --- /dev/null +++ b/NzbDrone.Core.Test/TvTests/SeriesRepositoryTests/QualityProfileRepositoryFixture.cs @@ -0,0 +1,46 @@ +using System.Collections.Generic; +using FizzWare.NBuilder; +using FluentAssertions; +using NUnit.Framework; +using NzbDrone.Core.Qualities; +using NzbDrone.Core.Test.Framework; +using NzbDrone.Core.Tv; +using NzbDrone.Test.Common; + +namespace NzbDrone.Core.Test.TvTests.SeriesRepositoryTests +{ + [TestFixture] + + public class SeriesRepositoryFixture : DbTest + { + [Test] + public void should_lazyload_quality_profile() + { + var profile = new QualityProfile + { + Allowed = new List + { + Quality.Bluray1080p, + Quality.DVD, + Quality.HDTV720p + }, + + Cutoff = Quality.Bluray1080p, + Name = "TestProfile" + }; + + + Mocker.Resolve().Insert(profile); + + var series = Builder.CreateNew().BuildNew(); + series.QualityProfileId = profile.Id; + + Subject.Insert(series); + + + StoredModel.QualityProfile.Should().NotBeNull(); + + + } + } +} \ No newline at end of file diff --git a/NzbDrone.Core/Datastore/MappingExtensions.cs b/NzbDrone.Core/Datastore/MappingExtensions.cs index ccc940d5e..702169798 100644 --- a/NzbDrone.Core/Datastore/MappingExtensions.cs +++ b/NzbDrone.Core/Datastore/MappingExtensions.cs @@ -20,9 +20,6 @@ public static class MappingExtensions public static ColumnMapBuilder RegisterModel(this FluentMappings.MappingsFluentEntity mapBuilder, string tableName = null) where T : ModelBase, new() { - - - return mapBuilder.Table.MapTable(tableName) .Columns .AutoMapPropertiesWhere(IsMappableProperty) diff --git a/NzbDrone.Core/Datastore/RelationshipExtensions.cs b/NzbDrone.Core/Datastore/RelationshipExtensions.cs index 3de895cc6..7c8767966 100644 --- a/NzbDrone.Core/Datastore/RelationshipExtensions.cs +++ b/NzbDrone.Core/Datastore/RelationshipExtensions.cs @@ -8,24 +8,29 @@ namespace NzbDrone.Core.Datastore { public static class RelationshipExtensions { - public static RelationshipBuilder HasOne(this ColumnMapBuilder columnMapBuilder, Expression>> portalExpression, Func childIdSelector) + public static RelationshipBuilder HasOne(this RelationshipBuilder relationshipBuilder, Expression>> portalExpression, Func childIdSelector) where TParent : ModelBase where TChild : ModelBase { - return columnMapBuilder.Relationships.AutoMapComplexTypeProperties() - .For(portalExpression.GetMemberName()) - .LazyLoad((db, parent) => db.Query().Single(c => c.Id == childIdSelector(parent))); - + return relationshipBuilder.For(portalExpression.GetMemberName()) + .LazyLoad((db, parent) => db.Query() + .Single(c => c.Id == childIdSelector(parent))); } - public static RelationshipBuilder HasMany(this ColumnMapBuilder columnMapBuilder, Expression>> portalExpression, Func childIdSelector) + public static RelationshipBuilder Relationship(this ColumnMapBuilder mapBuilder) + { + return mapBuilder.Relationships.AutoMapComplexTypeProperties(); + } + + + + public static RelationshipBuilder HasMany(this RelationshipBuilder relationshipBuilder, Expression>> portalExpression, Func childIdSelector) where TParent : ModelBase where TChild : ModelBase { - return columnMapBuilder.Relationships.AutoMapComplexTypeProperties() - .For(portalExpression.GetMemberName()) - .LazyLoad((db, parent) => db.Query().Where(c => c.Id == childIdSelector(parent)).ToList()); + return relationshipBuilder.For(portalExpression.GetMemberName()) + .LazyLoad((db, parent) => db.Query().Where(c => c.Id == childIdSelector(parent)).ToList()); } diff --git a/NzbDrone.Core/Datastore/TableMapping.cs b/NzbDrone.Core/Datastore/TableMapping.cs index 2215f385f..cc8e27e91 100644 --- a/NzbDrone.Core/Datastore/TableMapping.cs +++ b/NzbDrone.Core/Datastore/TableMapping.cs @@ -41,19 +41,20 @@ public static void Map() Mapper.Entity().RegisterModel("SceneMappings"); Mapper.Entity().RegisterModel("History") + .Relationship() .HasOne(h => h.Episode, h => h.EpisodeId); Mapper.Entity().RegisterModel("Series") .Ignore(s => s.Path) - .HasOne(s => s.RootFolder, s => s.RootFolderId); + .Relationship() + .HasOne(s => s.RootFolder, s => s.RootFolderId) + .HasOne(s => s.QualityProfile, s => s.QualityProfileId); Mapper.Entity().RegisterModel("Seasons"); Mapper.Entity().RegisterModel("Episodes"); Mapper.Entity().RegisterModel("EpisodeFiles"); - Mapper.Entity().RegisterModel("QualityProfiles") - .For(q => q.DbAllowed).SetColumnName("Allowed") - .Ignore(q => q.Allowed); + Mapper.Entity().RegisterModel("QualityProfiles"); Mapper.Entity().RegisterModel("QualitySizes"); @@ -65,6 +66,9 @@ public static void Map() } + + + private static void RegisterMappers() { RegisterEmbeddedConverter(); diff --git a/NzbDrone.Core/DecisionEngine/DownloadDecisionMaker.cs b/NzbDrone.Core/DecisionEngine/DownloadDecisionMaker.cs index 8a86ed28c..6300c6925 100644 --- a/NzbDrone.Core/DecisionEngine/DownloadDecisionMaker.cs +++ b/NzbDrone.Core/DecisionEngine/DownloadDecisionMaker.cs @@ -73,6 +73,11 @@ private string EvaluateSpec(IRejectWithReason spec, RemoteEpisode remoteEpisode, { try { + if (string.IsNullOrWhiteSpace(spec.RejectionReason)) + { + throw new InvalidOperationException("[Need Rejection Text]"); + } + var searchSpecification = spec as IDecisionEngineSearchSpecification; if (searchSpecification != null && searchDefinitionBase != null) { diff --git a/NzbDrone.Core/DecisionEngine/Specifications/QualityAllowedByProfileSpecification.cs b/NzbDrone.Core/DecisionEngine/Specifications/QualityAllowedByProfileSpecification.cs index 03a025281..99f6b247f 100644 --- a/NzbDrone.Core/DecisionEngine/Specifications/QualityAllowedByProfileSpecification.cs +++ b/NzbDrone.Core/DecisionEngine/Specifications/QualityAllowedByProfileSpecification.cs @@ -25,7 +25,7 @@ public string RejectionReason public virtual bool IsSatisfiedBy(RemoteEpisode subject) { _logger.Trace("Checking if report meets quality requirements. {0}", subject.ParsedEpisodeInfo.Quality); - if (!subject.Series.QualityProfile.Allowed.Contains(subject.ParsedEpisodeInfo.Quality.Quality)) + if (!subject.Series.QualityProfile.Value.Allowed.Contains(subject.ParsedEpisodeInfo.Quality.Quality)) { _logger.Trace("Quality {0} rejected by Series' quality profile", subject.ParsedEpisodeInfo.Quality); return false; diff --git a/NzbDrone.Core/Qualities/Quality.cs b/NzbDrone.Core/Qualities/Quality.cs index f327ff892..bdd6f11b1 100644 --- a/NzbDrone.Core/Qualities/Quality.cs +++ b/NzbDrone.Core/Qualities/Quality.cs @@ -5,7 +5,7 @@ namespace NzbDrone.Core.Qualities { - public class Quality : IComparable + public class Quality : IComparable, IEmbeddedDocument { public int Id { get; set; } public string Name { get; set; } @@ -173,7 +173,7 @@ public static Quality FindById(int id) if (quality == null) throw new ArgumentException("ID does not match a known quality", "id"); - return quality; + return quality; } public static explicit operator Quality(int id) diff --git a/NzbDrone.Core/Qualities/QualityProfile.cs b/NzbDrone.Core/Qualities/QualityProfile.cs index e419e13fe..892983ecd 100644 --- a/NzbDrone.Core/Qualities/QualityProfile.cs +++ b/NzbDrone.Core/Qualities/QualityProfile.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; +using System.Collections.Generic; using NzbDrone.Core.Datastore; namespace NzbDrone.Core.Qualities @@ -10,32 +7,6 @@ public class QualityProfile : ModelBase { public string Name { get; set; } public List Allowed { get; set; } - - [EditorBrowsable(EditorBrowsableState.Never)] - public string DbAllowed - { - get - { - string result = String.Empty; - if (Allowed == null) return result; - - foreach (var q in Allowed) - { - result += q.Id + "|"; - } - return result.Trim('|'); - } - private set - { - var qualities = value.Split('|'); - Allowed = new List(qualities.Length); - foreach (var quality in qualities.Where(q => !String.IsNullOrWhiteSpace(q))) - { - Allowed.Add(Quality.FindById(Convert.ToInt32(quality))); - } - } - } - public Quality Cutoff { get; set; } } } \ No newline at end of file diff --git a/NzbDrone.Core/Qualities/QualityProfileRepository.cs b/NzbDrone.Core/Qualities/QualityProfileRepository.cs index c36b8f6c4..e63807019 100644 --- a/NzbDrone.Core/Qualities/QualityProfileRepository.cs +++ b/NzbDrone.Core/Qualities/QualityProfileRepository.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Data; -using System.Linq; -using System.Text; -using NzbDrone.Core.Datastore; +using NzbDrone.Core.Datastore; namespace NzbDrone.Core.Qualities { diff --git a/NzbDrone.Core/Tv/Series.cs b/NzbDrone.Core/Tv/Series.cs index 56780427c..000243606 100644 --- a/NzbDrone.Core/Tv/Series.cs +++ b/NzbDrone.Core/Tv/Series.cs @@ -40,7 +40,7 @@ public Series() public int RootFolderId { get; set; } public string FolderName { get; set; } public LazyLoaded RootFolder { get; set; } - + //Todo: Use this to auto link RootFolder and Folder (using the proper path separator) public string Path { @@ -59,7 +59,7 @@ public string Path public int UtcOffset { get; set; } public DateTime? FirstAired { get; set; } - public QualityProfile QualityProfile { get; set; } + public LazyLoaded QualityProfile { get; set; } public DateTime? NextAiring { get; set; } } } \ No newline at end of file