quality Series.QualityProfile is lazyloaded.

This commit is contained in:
kay.one 2013-04-28 18:47:06 -07:00
parent d6d524e624
commit 016e360d1a
16 changed files with 154 additions and 72 deletions

View File

@ -36,13 +36,6 @@ namespace NzbDrone.Api
Mapper.CreateMap<QualitySizeResource, QualitySize>()
.ForMember(dest => dest.QualityId, opt => opt.MapFrom(src => src.Id));
//Series
Mapper.CreateMap<Core.Tv.Series, SeriesResource>()
.ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.Id))
.ForMember(dest => dest.CustomStartDate, opt => opt.ResolveUsing<NullableDatetimeToString>().FromMember(src => src.CustomStartDate))
.ForMember(dest => dest.BacklogSetting, opt => opt.MapFrom(src => (Int32)src.BacklogSetting))
.ForMember(dest => dest.NextAiring, opt => opt.ResolveUsing<NextAiringResolver>())
.ForMember(dest => dest.QualityProfileName, opt => opt.MapFrom(src => src.QualityProfile.Name));
//Calendar
Mapper.CreateMap<Episode, CalendarResource>()

View File

@ -37,12 +37,23 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
_fail3 = new Mock<IDecisionEngineSpecification>();
_pass1.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>())).Returns(true);
_pass1.Setup(c => c.RejectionReason).Returns("_pass1");
_pass2.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>())).Returns(true);
_pass2.Setup(c => c.RejectionReason).Returns("_pass2");
_pass3.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>())).Returns(true);
_pass3.Setup(c => c.RejectionReason).Returns("_pass3");
_fail1.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>())).Returns(false);
_fail1.Setup(c => c.RejectionReason).Returns("_fail1");
_fail2.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>())).Returns(false);
_fail2.Setup(c => c.RejectionReason).Returns("_fail2");
_fail3.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>())).Returns(false);
_fail3.Setup(c => c.RejectionReason).Returns("_fail3");
_reports = new List<ReportInfo> { new ReportInfo { Title = "The.Office.S03E115.DVDRip.XviD-OSiTV" } };
_remoteEpisode = new RemoteEpisode { Series = new Series() };
@ -72,6 +83,17 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
_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()
{

View File

@ -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 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
public void Setup()
{
var fakeSeries = Builder<Series>.CreateNew()
.With(c => c.QualityProfile = new QualityProfile { Cutoff = Quality.Bluray1080p })
.With(c => c.QualityProfile = (LazyLoaded<QualityProfile>)new QualityProfile { Cutoff = Quality.Bluray1080p })
.Build();
remoteEpisode = new RemoteEpisode
@ -48,7 +50,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
public void should_allow_if_quality_is_defined_in_profile(Quality qualityType)
{
remoteEpisode.ParsedEpisodeInfo.Quality.Quality = qualityType;
remoteEpisode.Series.QualityProfile.Allowed = new List<Quality> { Quality.DVD, Quality.HDTV720p, Quality.Bluray1080p };
remoteEpisode.Series.QualityProfile.Value.Allowed = new List<Quality> { Quality.DVD, Quality.HDTV720p, Quality.Bluray1080p };
Subject.IsSatisfiedBy(remoteEpisode).Should().BeTrue();
}
@ -57,7 +59,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
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> { Quality.DVD, Quality.HDTV720p, Quality.Bluray1080p };
remoteEpisode.Series.QualityProfile.Value.Allowed = new List<Quality> { Quality.DVD, Quality.HDTV720p, Quality.Bluray1080p };
Subject.IsSatisfiedBy(remoteEpisode).Should().BeFalse();
}

View File

@ -1,4 +1,5 @@
using System.Linq;
/*
using System.Linq;
using System;
using System.Collections.Generic;
using System.Threading;
@ -14,7 +15,7 @@ using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.JobTests
{
[TestFixture]
/* [TestFixture]
[ExclusivelyUses("JOB_PROVIDER")]
public class JobControllerFixture : CoreTest<JobController>
{
@ -225,6 +226,7 @@ namespace NzbDrone.Core.Test.JobTests
Subject.Queue.Should().OnlyContain(c => c.Source == JobQueueItem.JobSourceType.Scheduler);
WaitForQueue();
}
}#1#
}
}
*/

View File

@ -142,6 +142,7 @@
<Compile Include="MediaFileTests\MediaFileRepositoryFixture.cs" />
<Compile Include="MediaFileTests\EpisodeFileMoverFixture.cs" />
<Compile Include="MetadataSourceTests\TracktProxyFixture.cs" />
<Compile Include="Qualities\QualityProfileRepositoryFixture.cs" />
<Compile Include="RootFolderTests\FreeSpaceOnDrivesFixture.cs" />
<Compile Include="Qualities\QualityFixture.cs" />
<Compile Include="EpisodeParseResultTest.cs" />
@ -173,6 +174,7 @@
<Compile Include="ProviderTests\PostDownloadProviderTests\DropFolderImportServiceFixture.cs" />
<Compile Include="JobTests\TestJobs.cs" />
<Compile Include="SeriesStatsTests\SeriesStatisticsFixture.cs" />
<Compile Include="TvTests\SeriesRepositoryTests\QualityProfileRepositoryFixture.cs" />
<Compile Include="UpdateTests\UpdateServiceFixture.cs" />
<Compile Include="ProviderTests\XemCommunicationProviderTests\GetSceneTvdbMappingsFixture.cs" />
<Compile Include="ProviderTests\XemCommunicationProviderTests\GetXemSeriesIdsFixture.cs" />
@ -346,7 +348,6 @@
</ItemGroup>
<ItemGroup>
<Folder Include="ProviderTests\UpdateProviderTests\" />
<Folder Include="TvTests\SeriesRepositoryTests\" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>

View File

@ -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<QualityProfileRepository, QualityProfile>
{
[Test]
public void should_be_able_to_read_and_write()
{
var profile = new QualityProfile
{
Allowed = new List<Quality>
{
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);
}
}
}

View File

@ -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<SeriesRepository, Series>
{
[Test]
public void should_lazyload_quality_profile()
{
var profile = new QualityProfile
{
Allowed = new List<Quality>
{
Quality.Bluray1080p,
Quality.DVD,
Quality.HDTV720p
},
Cutoff = Quality.Bluray1080p,
Name = "TestProfile"
};
Mocker.Resolve<QualityProfileRepository>().Insert(profile);
var series = Builder<Series>.CreateNew().BuildNew();
series.QualityProfileId = profile.Id;
Subject.Insert(series);
StoredModel.QualityProfile.Should().NotBeNull();
}
}
}

View File

@ -20,9 +20,6 @@ namespace NzbDrone.Core.Datastore
public static ColumnMapBuilder<T> RegisterModel<T>(this FluentMappings.MappingsFluentEntity<T> mapBuilder, string tableName = null) where T : ModelBase, new()
{
return mapBuilder.Table.MapTable(tableName)
.Columns
.AutoMapPropertiesWhere(IsMappableProperty)

View File

@ -8,24 +8,29 @@ namespace NzbDrone.Core.Datastore
{
public static class RelationshipExtensions
{
public static RelationshipBuilder<TParent> HasOne<TParent, TChild>(this ColumnMapBuilder<TParent> columnMapBuilder, Expression<Func<TParent, LazyLoaded<TChild>>> portalExpression, Func<TParent, int> childIdSelector)
public static RelationshipBuilder<TParent> HasOne<TParent, TChild>(this RelationshipBuilder<TParent> relationshipBuilder, Expression<Func<TParent, LazyLoaded<TChild>>> portalExpression, Func<TParent, int> childIdSelector)
where TParent : ModelBase
where TChild : ModelBase
{
return columnMapBuilder.Relationships.AutoMapComplexTypeProperties<ILazyLoaded>()
.For(portalExpression.GetMemberName())
.LazyLoad((db, parent) => db.Query<TChild>().Single(c => c.Id == childIdSelector(parent)));
return relationshipBuilder.For(portalExpression.GetMemberName())
.LazyLoad((db, parent) => db.Query<TChild>()
.Single(c => c.Id == childIdSelector(parent)));
}
public static RelationshipBuilder<TParent> HasMany<TParent, TChild>(this ColumnMapBuilder<TParent> columnMapBuilder, Expression<Func<TParent, LazyList<TChild>>> portalExpression, Func<TParent, int> childIdSelector)
public static RelationshipBuilder<TParent> Relationship<TParent>(this ColumnMapBuilder<TParent> mapBuilder)
{
return mapBuilder.Relationships.AutoMapComplexTypeProperties<ILazyLoaded>();
}
public static RelationshipBuilder<TParent> HasMany<TParent, TChild>(this RelationshipBuilder<TParent> relationshipBuilder, Expression<Func<TParent, LazyList<TChild>>> portalExpression, Func<TParent, int> childIdSelector)
where TParent : ModelBase
where TChild : ModelBase
{
return columnMapBuilder.Relationships.AutoMapComplexTypeProperties<ILazyLoaded>()
.For(portalExpression.GetMemberName())
.LazyLoad((db, parent) => db.Query<TChild>().Where(c => c.Id == childIdSelector(parent)).ToList());
return relationshipBuilder.For(portalExpression.GetMemberName())
.LazyLoad((db, parent) => db.Query<TChild>().Where(c => c.Id == childIdSelector(parent)).ToList());
}

View File

@ -41,19 +41,20 @@ namespace NzbDrone.Core.Datastore
Mapper.Entity<SceneMapping>().RegisterModel("SceneMappings");
Mapper.Entity<History.History>().RegisterModel("History")
.Relationship()
.HasOne(h => h.Episode, h => h.EpisodeId);
Mapper.Entity<Series>().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<Season>().RegisterModel("Seasons");
Mapper.Entity<Episode>().RegisterModel("Episodes");
Mapper.Entity<EpisodeFile>().RegisterModel("EpisodeFiles");
Mapper.Entity<QualityProfile>().RegisterModel("QualityProfiles")
.For(q => q.DbAllowed).SetColumnName("Allowed")
.Ignore(q => q.Allowed);
Mapper.Entity<QualityProfile>().RegisterModel("QualityProfiles");
Mapper.Entity<QualitySize>().RegisterModel("QualitySizes");
@ -65,6 +66,9 @@ namespace NzbDrone.Core.Datastore
}
private static void RegisterMappers()
{
RegisterEmbeddedConverter();

View File

@ -73,6 +73,11 @@ namespace NzbDrone.Core.DecisionEngine
{
try
{
if (string.IsNullOrWhiteSpace(spec.RejectionReason))
{
throw new InvalidOperationException("[Need Rejection Text]");
}
var searchSpecification = spec as IDecisionEngineSearchSpecification;
if (searchSpecification != null && searchDefinitionBase != null)
{

View File

@ -25,7 +25,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
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;

View File

@ -5,7 +5,7 @@ using NzbDrone.Core.Datastore;
namespace NzbDrone.Core.Qualities
{
public class Quality : IComparable<Quality>
public class Quality : IComparable<Quality>, IEmbeddedDocument
{
public int Id { get; set; }
public string Name { get; set; }
@ -173,7 +173,7 @@ namespace NzbDrone.Core.Qualities
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)

View File

@ -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 @@ namespace NzbDrone.Core.Qualities
{
public string Name { get; set; }
public List<Quality> 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<Quality>(qualities.Length);
foreach (var quality in qualities.Where(q => !String.IsNullOrWhiteSpace(q)))
{
Allowed.Add(Quality.FindById(Convert.ToInt32(quality)));
}
}
}
public Quality Cutoff { get; set; }
}
}

View File

@ -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
{

View File

@ -40,7 +40,7 @@ namespace NzbDrone.Core.Tv
public int RootFolderId { get; set; }
public string FolderName { get; set; }
public LazyLoaded<RootFolder> RootFolder { get; set; }
//Todo: Use this to auto link RootFolder and Folder (using the proper path separator)
public string Path
{
@ -59,7 +59,7 @@ namespace NzbDrone.Core.Tv
public int UtcOffset { get; set; }
public DateTime? FirstAired { get; set; }
public QualityProfile QualityProfile { get; set; }
public LazyLoaded<QualityProfile> QualityProfile { get; set; }
public DateTime? NextAiring { get; set; }
}
}