From 1239da656ec6e624cbb26c1d2be232df581001c2 Mon Sep 17 00:00:00 2001 From: "kay.one" Date: Sat, 28 May 2011 12:23:35 -0700 Subject: [PATCH] Rewrite of InventoryProvider --- NzbDrone.Core.Test/DownloadProviderTest.cs | 23 +- NzbDrone.Core.Test/EpisodeProviderTest.cs | Bin 5812 -> 3194 bytes NzbDrone.Core.Test/EpisodeSearchJobTest.cs | 122 +++-- NzbDrone.Core.Test/HistoryProviderTest.cs | 110 ++--- NzbDrone.Core.Test/IndexerProviderTest.cs | 2 +- NzbDrone.Core.Test/IndexerTests.cs | 7 +- NzbDrone.Core.Test/InventoryProviderTest.cs | 430 ------------------ .../InventoryProvider_IsMonitoredTest.cs | 207 +++++++++ .../InventoryProvider_QualityNeededTest.cs | 234 ++++++++++ NzbDrone.Core.Test/NzbDrone.Core.Test.csproj | 4 +- NzbDrone.Core.Test/ParserTest.cs | 10 +- NzbDrone.Core.Test/QualityTest.cs | 130 ++++++ NzbDrone.Core.Test/RepoTest.cs | 30 ++ NzbDrone.Core.Test/SabProviderTest.cs | 14 +- NzbDrone.Core.Test/SeriesProviderTest.cs | Bin 7707 -> 6335 bytes NzbDrone.Core/Model/EpisodeParseResult.cs | 14 +- NzbDrone.Core/Model/Quality.cs | 92 ++++ NzbDrone.Core/Model/SeasonParseResult.cs | 2 +- NzbDrone.Core/NzbDrone.Core.csproj | 1 + NzbDrone.Core/Parser.cs | 53 ++- NzbDrone.Core/Providers/DownloadProvider.cs | 4 +- NzbDrone.Core/Providers/EpisodeProvider.cs | Bin 11924 -> 10048 bytes NzbDrone.Core/Providers/HistoryProvider.cs | 14 +- NzbDrone.Core/Providers/Indexer/Newzbin.cs | 4 +- NzbDrone.Core/Providers/InventoryProvider.cs | 89 +++- .../Providers/Jobs/EpisodeSearchJob.cs | 28 +- NzbDrone.Core/Providers/Jobs/RssSyncJob.cs | 6 +- NzbDrone.Core/Providers/MediaFileProvider.cs | 4 +- NzbDrone.Core/Providers/SabProvider.cs | 4 +- NzbDrone.Core/Providers/SeriesProvider.cs | 7 - NzbDrone.Core/Repository/Episode.cs | 21 +- 31 files changed, 999 insertions(+), 667 deletions(-) delete mode 100644 NzbDrone.Core.Test/InventoryProviderTest.cs create mode 100644 NzbDrone.Core.Test/InventoryProvider_IsMonitoredTest.cs create mode 100644 NzbDrone.Core.Test/InventoryProvider_QualityNeededTest.cs create mode 100644 NzbDrone.Core.Test/QualityTest.cs create mode 100644 NzbDrone.Core/Model/Quality.cs diff --git a/NzbDrone.Core.Test/DownloadProviderTest.cs b/NzbDrone.Core.Test/DownloadProviderTest.cs index db2c8758f..ee63d5f69 100644 --- a/NzbDrone.Core.Test/DownloadProviderTest.cs +++ b/NzbDrone.Core.Test/DownloadProviderTest.cs @@ -10,8 +10,10 @@ using Moq; using NzbDrone.Core.Model; using NzbDrone.Core.Providers; using NzbDrone.Core.Repository; +using NzbDrone.Core.Repository.Quality; // ReSharper disable InconsistentNaming + namespace NzbDrone.Core.Test { [TestFixture] @@ -23,10 +25,11 @@ namespace NzbDrone.Core.Test var mocker = new AutoMoqer(MockBehavior.Strict); var parseResult = Builder.CreateNew() .With(e => e.Episodes = Builder.CreateListOfSize(2) - .WhereTheFirst(1).Has(s => s.EpisodeId = 12) - .AndTheNext(1).Has(s => s.EpisodeId = 99) - .Build()) - .Build(); + .WhereTheFirst(1).Has(s => s.EpisodeId = 12) + .AndTheNext(1).Has(s => s.EpisodeId = 99) + .Build()) + .With(c => c.Quality = new Quality(QualityTypes.DVD, false)) + .Build(); const string sabTitle = "My fake sab title"; mocker.GetMock() @@ -38,18 +41,18 @@ namespace NzbDrone.Core.Test .Returns(true); mocker.GetMock() - .Setup(s => s.GetSabTitle(parseResult)) - .Returns(sabTitle); + .Setup(s => s.GetSabTitle(parseResult)) + .Returns(sabTitle); mocker.GetMock() - .Setup(s => s.Add(It.Is(h=>h.EpisodeId == 12))); + .Setup(s => s.Add(It.Is(h => h.EpisodeId == 12))); mocker.GetMock() - .Setup(s => s.Add(It.Is(h => h.EpisodeId == 99))); + .Setup(s => s.Add(It.Is(h => h.EpisodeId == 99))); mocker.Resolve().DownloadReport(parseResult); - + mocker.VerifyAllMocks(); } } -} +} \ No newline at end of file diff --git a/NzbDrone.Core.Test/EpisodeProviderTest.cs b/NzbDrone.Core.Test/EpisodeProviderTest.cs index b856d1818b607c87f3721486ec0d890b170eee10..b4d2c2836f7424ca77c49debbb9037d46446893e 100644 GIT binary patch delta 25 bcmdm@`%7Yj5C?|>6igQ25ZRm|S`3VLSarP6Tsv;P>Liu6l!?NBBO@yb+%?;wR-L`{;B;5VsMT12Y3MTp_i z*DMF62x7IrUubzIYiY;g{{D*R5S||tB8eeiQJzgdq(X-!=)THL1kGME`Z?eV^M?dlxhvULC_P)OxfC(x;0)t_ zYY|V_I8g& zVGYzKDb-71!A{ZhCBCKJ3tXYqqLoU-zs$zs9s+Re>4$3sxUTU3U)@3u`$^*Z-ltgm z6u#$k2oka}2~RON1-}7w7FkoKs$B|p2CN6^O%H!~ukQqTEwsN8mYxW@IIZg==jSM5C>3H;@PY7O^1=$Dj`>*|28@XUI!+_zv{ZU8a|HsiKbS0FapY zFvO#2RX%%NUMEpS7Fd&z%_Lk<*)?D~FQCgA*fX%mQx&+`+Ydit!p;Qs{SNbnLu+8A z-$`u^sz=IL)Dg^hk!XwICmNP#gdN8X8po7O+W(%&P+ie)_KZI@~PD3&L>Ln%V2b#hH_>-7|tHL(2YKdM#R5>GX=y}R=h zS-Lr@(a%`af#*7IV;!v${|czJ>^rOa-B8zuyB)rkKi#qBL`}{CVu&Y~^T}u)PmuqD zFYOP8Wr7rkIN#1@UO};$NWgk$z@}0rOsHdA!#0ScyI*81$2m0DO>%18xvm&W4EP#l zIG|%6sEheq{g)aimOY&~{vvhJjOPllDPz~S2W8cn>kXgF?Zfr|hP-;C`ELwd$@ILq zo0doOv%x0l1Y-3voHVelCMui__t-b~oIPv|X1$6izLz&u#`quEg>nP33Ht+{4n7^l z0W!)1KLoVmQ#PI19HCqLwBYFKqm zw{O4#szn^HP1ZcQn!k~Y(^Mx?pAS643O VI^}^1q$(18c=+M}&wuBEzX5=D>7xJu diff --git a/NzbDrone.Core.Test/EpisodeSearchJobTest.cs b/NzbDrone.Core.Test/EpisodeSearchJobTest.cs index 49d67b8b5..e1b38caf5 100644 --- a/NzbDrone.Core.Test/EpisodeSearchJobTest.cs +++ b/NzbDrone.Core.Test/EpisodeSearchJobTest.cs @@ -21,7 +21,7 @@ namespace NzbDrone.Core.Test public class EpisodeSearchJobTest : TestBase { [Test] - public void ParseResult_should_return_after_match() + public void processResults_ParseResult_should_return_after_match() { var parseResults = Builder.CreateListOfSize(5) .Build(); @@ -31,29 +31,31 @@ namespace NzbDrone.Core.Test var mocker = new AutoMoqer(MockBehavior.Strict); mocker.GetMock() - .Setup(c => c.IsNeeded(It.IsAny())).Returns(true); + .Setup(c => c.IsQualityNeeded(It.IsAny())).Returns(true); mocker.GetMock() .Setup(c => c.DownloadReport(It.IsAny())).Returns(true); - + //Act mocker.Resolve().ProcessResults(new ProgressNotification("Test"), episode, parseResults); //Assert mocker.VerifyAllMocks(); - mocker.GetMock().Verify(c => c.IsNeeded(It.IsAny()), Times.Once()); - mocker.GetMock().Verify(c => c.DownloadReport(It.IsAny()), Times.Once()); + mocker.GetMock().Verify(c => c.IsQualityNeeded(It.IsAny()), + Times.Once()); + mocker.GetMock().Verify(c => c.DownloadReport(It.IsAny()), + Times.Once()); } [Test] - public void higher_quality_should_be_called_first() + public void processResults_higher_quality_should_be_called_first() { - var parseResults = Builder.CreateListOfSize(2) - .WhereTheFirst(1).Has(c => c.Quality = QualityTypes.Bluray1080p) - .AndTheNext(1).Has(c => c.Quality = QualityTypes.DVD) + var parseResults = Builder.CreateListOfSize(10) + .WhereAll().Have(c => c.Quality = new Quality(QualityTypes.DVD, true)) + .WhereRandom(1).Has(c => c.Quality = new Quality(QualityTypes.Bluray1080p, true)) .Build(); var episode = Builder.CreateNew().Build(); @@ -61,41 +63,48 @@ namespace NzbDrone.Core.Test var mocker = new AutoMoqer(MockBehavior.Strict); mocker.GetMock() - .Setup(c => c.IsNeeded(parseResults[0])).Returns(true); + .Setup( + c => + c.IsQualityNeeded(It.Is(d => d.Quality.QualityType == QualityTypes.Bluray1080p))) + .Returns(true); mocker.GetMock() - .Setup(c => c.DownloadReport(parseResults[0])).Returns(true); + .Setup( + c => + c.DownloadReport(It.Is(d => d.Quality.QualityType == QualityTypes.Bluray1080p))) + .Returns(true); //Act mocker.Resolve().ProcessResults(new ProgressNotification("Test"), episode, parseResults); //Assert mocker.VerifyAllMocks(); - mocker.GetMock().Verify(c => c.IsNeeded(parseResults[0]), Times.Once()); - mocker.GetMock().Verify(c => c.DownloadReport(parseResults[0]), Times.Once()); + mocker.GetMock().Verify(c => c.IsQualityNeeded(It.IsAny()), + Times.Once()); + mocker.GetMock().Verify(c => c.DownloadReport(It.IsAny()), + Times.Once()); } [Test] - public void when_same_quality_proper_should_be_called_first() + public void processResults_when_same_quality_proper_should_be_called_first() { var parseResults = Builder.CreateListOfSize(20) - .WhereAll().Have(c => c.Quality = QualityTypes.DVD) - .And(c => c.Proper = false) - .WhereRandom(1).Has(c => c.Proper = true) + .WhereAll().Have(c => c.Quality = new Quality(QualityTypes.DVD, false)) + .WhereRandom(1).Has(c => c.Quality = new Quality(QualityTypes.DVD, true)) .Build(); - Assert.Count(1, parseResults.Where(c => c.Proper)); + Assert.Count(1, parseResults.Where(c => c.Quality.Proper)); var episode = Builder.CreateNew().Build(); var mocker = new AutoMoqer(MockBehavior.Strict); mocker.GetMock() - .Setup(c => c.IsNeeded(It.Is(p => p.Proper))).Returns(true); + .Setup(c => c.IsQualityNeeded(It.Is(p => p.Quality.Proper))).Returns(true); mocker.GetMock() - .Setup(c => c.DownloadReport(It.Is(p => p.Proper))).Returns(true); + .Setup(c => c.DownloadReport(It.Is(p => p.Quality.Proper))).Returns(true); //Act @@ -103,13 +112,15 @@ namespace NzbDrone.Core.Test //Assert mocker.VerifyAllMocks(); - mocker.GetMock().Verify(c => c.IsNeeded(It.Is(p => p.Proper)), Times.Once()); - mocker.GetMock().Verify(c => c.DownloadReport(It.Is(p => p.Proper)), Times.Once()); + mocker.GetMock().Verify(c => c.IsQualityNeeded(It.IsAny()), + Times.Once()); + mocker.GetMock().Verify(c => c.DownloadReport(It.IsAny()), + Times.Once()); } [Test] - public void when_not_needed_should_check_the_rest() + public void processResults_when_not_needed_should_check_the_rest() { var parseResults = Builder.CreateListOfSize(4) .Build(); @@ -119,20 +130,21 @@ namespace NzbDrone.Core.Test var mocker = new AutoMoqer(MockBehavior.Strict); mocker.GetMock() - .Setup(c => c.IsNeeded(It.IsAny())).Returns(false); + .Setup(c => c.IsQualityNeeded(It.IsAny())).Returns(false); //Act mocker.Resolve().ProcessResults(new ProgressNotification("Test"), episode, parseResults); //Assert mocker.VerifyAllMocks(); - mocker.GetMock().Verify(c => c.IsNeeded(It.IsAny()), Times.Exactly(4)); + mocker.GetMock().Verify(c => c.IsQualityNeeded(It.IsAny()), + Times.Exactly(4)); ExceptionVerification.ExcpectedWarns(1); } [Test] - public void failed_IsNeeded_should_check_the_rest() + public void processResults_failed_IsNeeded_should_check_the_rest() { var parseResults = Builder.CreateListOfSize(4) .Build(); @@ -142,34 +154,64 @@ namespace NzbDrone.Core.Test var mocker = new AutoMoqer(MockBehavior.Strict); mocker.GetMock() - .Setup(c => c.IsNeeded(It.IsAny())).Throws(new Exception()); + .Setup(c => c.IsQualityNeeded(It.IsAny())).Throws(new Exception()); //Act mocker.Resolve().ProcessResults(new ProgressNotification("Test"), episode, parseResults); //Assert mocker.VerifyAllMocks(); - mocker.GetMock().Verify(c => c.IsNeeded(It.IsAny()), Times.Exactly(4)); + mocker.GetMock().Verify(c => c.IsQualityNeeded(It.IsAny()), + Times.Exactly(4)); ExceptionVerification.ExcpectedErrors(4); ExceptionVerification.ExcpectedWarns(1); } + [Test] + public void processResults_failed_download_should_not_check_the_rest() + { + var parseResults = Builder.CreateListOfSize(4) + .Build(); + + var episode = Builder.CreateNew().Build(); + + var mocker = new AutoMoqer(MockBehavior.Strict); + + mocker.GetMock() + .Setup(c => c.IsQualityNeeded(It.IsAny())).Returns(true); + + mocker.GetMock() + .Setup(c => c.DownloadReport(It.IsAny())).Throws(new Exception()); + + //Act + mocker.Resolve().ProcessResults(new ProgressNotification("Test"), episode, parseResults); + + //Assert + mocker.VerifyAllMocks(); + mocker.GetMock().Verify(c => c.IsQualityNeeded(It.IsAny()), + Times.Exactly(1)); + + mocker.GetMock().Verify(c => c.DownloadReport(It.IsAny()), + Times.Exactly(1)); + + ExceptionVerification.ExcpectedErrors(1); + } + [Test] [Row(0)] [Row(-1)] [Row(-100)] [ExpectedException(typeof(ArgumentOutOfRangeException))] - public void target_id_less_than_0_throws_exception(int target) + public void start_target_id_less_than_0_throws_exception(int target) { var mocker = new AutoMoqer(MockBehavior.Strict); mocker.Resolve().Start(new ProgressNotification("Test"), target); } - [Test] - public void should_search_all_providers() + public void start_should_search_all_providers() { var parseResults = Builder.CreateListOfSize(4) .Build(); @@ -201,7 +243,7 @@ namespace NzbDrone.Core.Test .Returns(indexers); mocker.GetMock() - .Setup(c => c.IsNeeded(It.IsAny())).Returns(false); + .Setup(c => c.IsQualityNeeded(It.Is(d => d.Series != null && d.Episodes.Count != 0))).Returns(false); //Act mocker.Resolve().Start(new ProgressNotification("Test"), episode.EpisodeId); @@ -209,7 +251,8 @@ namespace NzbDrone.Core.Test //Assert mocker.VerifyAllMocks(); - mocker.GetMock().Verify(c => c.IsNeeded(It.IsAny()), Times.Exactly(8)); + mocker.GetMock().Verify(c => c.IsQualityNeeded(It.IsAny()), + Times.Exactly(8)); ExceptionVerification.ExcpectedWarns(1); indexer1.VerifyAll(); indexer2.VerifyAll(); @@ -217,7 +260,7 @@ namespace NzbDrone.Core.Test [Test] - public void failed_indexer_should_not_break_job() + public void start_failed_indexer_should_not_break_job() { var parseResults = Builder.CreateListOfSize(4) .Build(); @@ -254,7 +297,7 @@ namespace NzbDrone.Core.Test .Returns(indexers); mocker.GetMock() - .Setup(c => c.IsNeeded(It.IsAny())).Returns(false); + .Setup(c => c.IsQualityNeeded(It.Is(d => d.Series != null && d.Episodes.Count != 0))).Returns(false); //Act mocker.Resolve().Start(new ProgressNotification("Test"), episode.EpisodeId); @@ -262,7 +305,8 @@ namespace NzbDrone.Core.Test //Assert mocker.VerifyAllMocks(); - mocker.GetMock().Verify(c => c.IsNeeded(It.IsAny()), Times.Exactly(8)); + mocker.GetMock().Verify(c => c.IsQualityNeeded(It.IsAny()), + Times.Exactly(8)); ExceptionVerification.ExcpectedWarns(1); ExceptionVerification.ExcpectedErrors(1); @@ -272,9 +316,8 @@ namespace NzbDrone.Core.Test } - [Test] - public void no_episode_found_should_return_with_error_logged() + public void start_no_episode_found_should_return_with_error_logged() { var mocker = new AutoMoqer(MockBehavior.Strict); @@ -290,6 +333,5 @@ namespace NzbDrone.Core.Test mocker.VerifyAllMocks(); ExceptionVerification.ExcpectedErrors(1); } - } -} +} \ No newline at end of file diff --git a/NzbDrone.Core.Test/HistoryProviderTest.cs b/NzbDrone.Core.Test/HistoryProviderTest.cs index 8bb535d9d..a7fba7c57 100644 --- a/NzbDrone.Core.Test/HistoryProviderTest.cs +++ b/NzbDrone.Core.Test/HistoryProviderTest.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Linq; using AutoMoq; +using FizzWare.NBuilder; using MbUnit.Framework; using Moq; using NzbDrone.Core.Providers; @@ -59,6 +60,38 @@ namespace NzbDrone.Core.Test } + [Test] + public void GetBestQualityInHistory_no_result() + { + var mocker = new AutoMoqer(MockBehavior.Strict); + + mocker.SetConstant(MockLib.GetEmptyRepository()); + + //Act + var result = mocker.Resolve().GetBestQualityInHistory(12); + + //Assert + Assert.IsNull(result); + } + + [Test] + public void GetBestQualityInHistory_single_result() + { + var mocker = new AutoMoqer(MockBehavior.Strict); + + + var repo = MockLib.GetEmptyRepository(); + var history = Builder.CreateNew().Build(); + repo.Add(history); + mocker.SetConstant(repo); + + //Act + var result = mocker.Resolve().GetBestQualityInHistory(history.EpisodeId); + + //Assert + Assert.IsNotNull(result); + } + [Test] public void add_item() { @@ -95,83 +128,6 @@ namespace NzbDrone.Core.Test Assert.AreEqual(history.Indexer, newHistiory.Indexer); } - [Test] - [Ignore] - public void Exists_True() - { - //Todo: This test fails... Moq Setup doesn't return the expected value - //Setup - var season = new Season { SeasonId = 4321, SeasonNumber = 1, SeriesId = 5656, Monitored = true }; - var episode = new Episode - { - AirDate = DateTime.Today.AddDays(-1), - EpisodeId = 1234, - EpisodeNumber = 5, - Overview = "This is an Overview", - SeasonNumber = 1, - SeasonId = 4321, - Season = season, - SeriesId = 5656 - }; - - var proper = false; - var repo = new Mock(); - repo.Setup(r => r.Exists(h => h.EpisodeId == episode.EpisodeId && h.IsProper == proper)).Returns( - true); - - var target = new HistoryProvider(repo.Object); - - //Act - var result = target.Exists(episode.EpisodeId, QualityTypes.SDTV, false); - - //Assert - Assert.AreEqual(result, true); - } - - [Test] - [Ignore] - public void Exists_False() - { - //Todo: This test fails... Moq Setup doesn't return the expected value - - //Setup - var season = new Season { SeasonId = 4321, SeasonNumber = 1, SeriesId = 5656, Monitored = true }; - var episode = new Episode - { - AirDate = DateTime.Today.AddDays(-1), - EpisodeId = 1234, - EpisodeNumber = 5, - Overview = "This is an Overview", - SeasonNumber = 1, - SeasonId = 4321, - Season = season, - SeriesId = 5656 - }; - - var list = new List - { - new History - { - HistoryId = new int(), - Date = DateTime.Now, - IsProper = false, - Quality = QualityTypes.SDTV, - EpisodeId = episode.EpisodeId - } - }; - - var repo = new Mock(); - repo.Setup(r => r.Exists(h => h.Episode == episode && h.IsProper == list[0].IsProper)).Returns( - false); - - var target = new HistoryProvider(repo.Object); - - //Act - var result = target.Exists(episode.EpisodeId, QualityTypes.SDTV, true); - - //Assert - Assert.AreEqual(result, false); - } } } \ No newline at end of file diff --git a/NzbDrone.Core.Test/IndexerProviderTest.cs b/NzbDrone.Core.Test/IndexerProviderTest.cs index d45e14e88..f84a0a8c3 100644 --- a/NzbDrone.Core.Test/IndexerProviderTest.cs +++ b/NzbDrone.Core.Test/IndexerProviderTest.cs @@ -156,7 +156,7 @@ namespace NzbDrone.Core.Test protected override Model.EpisodeParseResult CustomParser(SyndicationItem item, Model.EpisodeParseResult currentResult) { if (currentResult == null) currentResult = new EpisodeParseResult(); - currentResult.EpisodeTitle = item.Summary.Text; + currentResult.Language = LanguageType.Finnish; return currentResult; } } diff --git a/NzbDrone.Core.Test/IndexerTests.cs b/NzbDrone.Core.Test/IndexerTests.cs index 8e7e662e2..88760a6fc 100644 --- a/NzbDrone.Core.Test/IndexerTests.cs +++ b/NzbDrone.Core.Test/IndexerTests.cs @@ -10,6 +10,7 @@ using Gallio.Framework; using MbUnit.Framework; using MbUnit.Framework.ContractVerifiers; using Moq; +using NzbDrone.Core.Model; using NzbDrone.Core.Providers; using NzbDrone.Core.Providers.Core; using NzbDrone.Core.Providers.Indexer; @@ -114,10 +115,10 @@ namespace NzbDrone.Core.Test var result = mocker.Resolve().ParseFeed(fakeRssItem); Assert.IsNotNull(result); - Assert.AreEqual(summary, result.EpisodeTitle); + Assert.AreEqual(LanguageType.Finnish, result.Language); Assert.AreEqual(season, result.SeasonNumber); Assert.AreEqual(episode, result.EpisodeNumbers[0]); - Assert.AreEqual(quality, result.Quality); + Assert.AreEqual(quality, result.Quality.QualityType); } @@ -142,7 +143,7 @@ namespace NzbDrone.Core.Test var result = mocker.Resolve().ParseFeed(fakeRssItem); Assert.IsNotNull(result); - Assert.AreEqual(summary, result.EpisodeTitle); + Assert.AreEqual(LanguageType.Finnish, result.Language); ExceptionVerification.ExcpectedWarns(1); } diff --git a/NzbDrone.Core.Test/InventoryProviderTest.cs b/NzbDrone.Core.Test/InventoryProviderTest.cs deleted file mode 100644 index c01dfd46a..000000000 --- a/NzbDrone.Core.Test/InventoryProviderTest.cs +++ /dev/null @@ -1,430 +0,0 @@ -// ReSharper disable RedundantUsingDirective -using System; -using System.Collections.Generic; -using System.IO; -using System.Net; -using System.ServiceModel.Syndication; -using AutoMoq; -using FizzWare.NBuilder; -using MbUnit.Framework; -using Moq; -using NzbDrone.Core.Model; -using NzbDrone.Core.Providers; -using NzbDrone.Core.Providers.Core; -using NzbDrone.Core.Providers.ExternalNotification; -using NzbDrone.Core.Providers.Indexer; -using NzbDrone.Core.Repository; -using NzbDrone.Core.Repository.Quality; -using NzbDrone.Core.Test.Framework; - -namespace NzbDrone.Core.Test -{ - [TestFixture] - // ReSharper disable InconsistentNaming - public class InventoryProviderTest : TestBase - { - private EpisodeParseResult parseResultMulti; - private Series series; - private Episode episode; - private Episode episode2; - private EpisodeParseResult parseResultSingle; - - [SetUp] - public new void Setup() - { - parseResultMulti = new EpisodeParseResult() - { - CleanTitle = "Title", - EpisodeTitle = "EpisodeTitle", - Language = LanguageType.English, - Proper = true, - Quality = QualityTypes.Bluray720p, - EpisodeNumbers = new List { 3, 4 }, - SeasonNumber = 12, - AirDate = DateTime.Now.AddDays(-12).Date - }; - - parseResultSingle = new EpisodeParseResult() - { - CleanTitle = "Title", - EpisodeTitle = "EpisodeTitle", - Language = LanguageType.English, - Proper = true, - Quality = QualityTypes.Bluray720p, - EpisodeNumbers = new List { 3 }, - SeasonNumber = 12, - AirDate = DateTime.Now.AddDays(-12).Date - }; - - series = Builder.CreateNew() - .With(c => c.Monitored = true) - .With(d => d.CleanTitle = parseResultMulti.CleanTitle) - .Build(); - - episode = Builder.CreateNew() - .With(c => c.EpisodeNumber = parseResultMulti.EpisodeNumbers[0]) - .With(c => c.SeasonNumber = parseResultMulti.SeasonNumber) - .With(c => c.AirDate = parseResultMulti.AirDate) - .Build(); - - episode2 = Builder.CreateNew() - .With(c => c.EpisodeNumber = parseResultMulti.EpisodeNumbers[1]) - .With(c => c.SeasonNumber = parseResultMulti.SeasonNumber) - .With(c => c.AirDate = parseResultMulti.AirDate) - .Build(); - - base.Setup(); - - } - - - [Test] - public void not_monitored_series_should_be_skipped() - { - series.Monitored = false; - - var mocker = new AutoMoqer(MockBehavior.Strict); - - mocker.GetMock() - .Setup(p => p.FindSeries(It.IsAny())) - .Returns(series); - - //Act - var result = mocker.Resolve().IsNeeded(parseResultMulti); - - //Assert - Assert.IsFalse(result); - mocker.VerifyAllMocks(); - } - - - [Test] - public void no_db_series_should_be_skipped() - { - - var mocker = new AutoMoqer(MockBehavior.Strict); - - mocker.GetMock() - .Setup(p => p.FindSeries(It.IsAny())) - .Returns(null); - - //Act - var result = mocker.Resolve().IsNeeded(parseResultMulti); - - //Assert - Assert.IsFalse(result); - mocker.VerifyAllMocks(); - } - - [Test] - public void unwannted_quality_should_be_skipped() - { - - var mocker = new AutoMoqer(MockBehavior.Strict); - mocker.GetMock() - .Setup(p => p.FindSeries(It.IsAny())) - .Returns(series); - - mocker.GetMock() - .Setup(p => p.QualityWanted(series.SeriesId, parseResultMulti.Quality)) - .Returns(false); - - - //Act - var result = mocker.Resolve().IsNeeded(parseResultMulti); - - //Assert - Assert.IsFalse(result); - mocker.VerifyAllMocks(); - } - - - [Test] - public void ignored_season_should_be_skipped() - { - - var mocker = new AutoMoqer(MockBehavior.Strict); - - mocker.GetMock() - .Setup(p => p.FindSeries(It.IsAny())) - .Returns(series); - - mocker.GetMock() - .Setup(p => p.QualityWanted(series.SeriesId, parseResultMulti.Quality)) - .Returns(true); - - mocker.GetMock() - .Setup(p => p.IsIgnored(series.SeriesId, parseResultMulti.SeasonNumber)) - .Returns(true); - - //Act - var result = mocker.Resolve().IsNeeded(parseResultMulti); - - //Assert - Assert.IsFalse(result); - mocker.VerifyAllMocks(); - } - - - - - - [Test] - public void unwannted_file_should_be_skipped() - { - var mocker = new AutoMoqer(MockBehavior.Strict); - - mocker.GetMock() - .Setup(p => p.FindSeries(It.IsAny())) - .Returns(series); - - mocker.GetMock() - .Setup(p => p.GetEpisode(episode.SeriesId, episode.SeasonNumber, episode.EpisodeNumber)) - .Returns(episode); - - mocker.GetMock() - .Setup(p => p.GetEpisode(episode2.SeriesId, episode2.SeasonNumber, episode2.EpisodeNumber)) - .Returns(episode2); - - - mocker.GetMock() - .Setup(p => p.QualityWanted(series.SeriesId, parseResultMulti.Quality)) - .Returns(true); - - mocker.GetMock() - .Setup(p => p.IsIgnored(series.SeriesId, parseResultMulti.SeasonNumber)) - .Returns(false); - - mocker.GetMock() - .Setup(p => p.IsNeeded(parseResultMulti, episode)) - .Returns(false); - - mocker.GetMock() - .Setup(p => p.IsNeeded(parseResultMulti, episode2)) - .Returns(false); - - //Act - var result = mocker.Resolve().IsNeeded(parseResultMulti); - - //Assert - Assert.IsFalse(result); - mocker.VerifyAllMocks(); - } - - - [Test] - public void file_in_history_should_be_skipped() - { - var mocker = new AutoMoqer(MockBehavior.Strict); - - mocker.GetMock() - .Setup(p => p.FindSeries(It.IsAny())) - .Returns(series); - - mocker.GetMock() - .Setup(p => p.GetEpisode(episode.SeriesId, episode.SeasonNumber, episode.EpisodeNumber)) - .Returns(episode); - - mocker.GetMock() - .Setup(p => p.QualityWanted(series.SeriesId, parseResultSingle.Quality)) - .Returns(true); - - mocker.GetMock() - .Setup(p => p.IsIgnored(series.SeriesId, parseResultSingle.SeasonNumber)) - .Returns(false); - - mocker.GetMock() - .Setup(p => p.IsNeeded(parseResultSingle, episode)) - .Returns(true); - - mocker.GetMock() - .Setup(p => p.Exists(episode.EpisodeId, parseResultSingle.Quality, parseResultSingle.Proper)) - .Returns(true); - - //Act - var result = mocker.Resolve().IsNeeded(parseResultSingle); - - //Assert - Assert.IsFalse(result); - mocker.VerifyAllMocks(); - } - - [Test] - public void dailyshow_should_do_daily_lookup() - { - var mocker = new AutoMoqer(MockBehavior.Strict); - - mocker.GetMock() - .Setup(p => p.FindSeries(It.IsAny())) - .Returns(series); - - mocker.GetMock() - .Setup(p => p.GetEpisode(episode.SeriesId, episode.SeasonNumber, episode.EpisodeNumber)) - .Returns(null); - - mocker.GetMock() - .Setup(p => p.GetEpisode(episode.SeriesId, episode.AirDate)) - .Returns(episode); - - - mocker.GetMock() - .Setup(p => p.QualityWanted(series.SeriesId, parseResultSingle.Quality)) - .Returns(true); - - mocker.GetMock() - .Setup(p => p.IsIgnored(series.SeriesId, parseResultSingle.SeasonNumber)) - .Returns(false); - - mocker.GetMock() - .Setup(p => p.IsNeeded(parseResultSingle, episode)) - .Returns(false); - - //Act - var result = mocker.Resolve().IsNeeded(parseResultSingle); - - //Assert - Assert.IsFalse(result); - mocker.VerifyAllMocks(); - } - - - [Test] - public void none_db_episode_should_be_added() - { - var mocker = new AutoMoqer(MockBehavior.Strict); - - mocker.GetMock() - .Setup(p => p.FindSeries(It.IsAny())) - .Returns(series); - - mocker.GetMock() - .Setup(p => p.QualityWanted(series.SeriesId, parseResultSingle.Quality)) - .Returns(true); - - mocker.GetMock() - .Setup(p => p.IsIgnored(series.SeriesId, parseResultSingle.SeasonNumber)) - .Returns(false); - - mocker.GetMock() - .Setup(p => p.GetEpisode(episode.SeriesId, episode.SeasonNumber, episode.EpisodeNumber)) - .Returns(null); - - mocker.GetMock() - .Setup(p => p.GetEpisode(episode.SeriesId, episode.AirDate)) - .Returns(null); - - mocker.GetMock() - .Setup(p => p.AddEpisode(It.IsAny())) - .Returns(12); - - mocker.GetMock() - .Setup(p => p.IsNeeded(parseResultSingle, It.IsAny())) - .Returns(false); - - //Act - var result = mocker.Resolve().IsNeeded(parseResultSingle); - - //Assert - Assert.IsFalse(result); - mocker.VerifyAllMocks(); - } - - - [Test] - public void first_file_needed_should_return_true() - { - var mocker = new AutoMoqer(MockBehavior.Strict); - - mocker.GetMock() - .Setup(p => p.FindSeries(It.IsAny())) - .Returns(series); - - mocker.GetMock() - .Setup(p => p.GetEpisode(episode.SeriesId, episode.SeasonNumber, episode.EpisodeNumber)) - .Returns(episode); - - mocker.GetMock() - .Setup(p => p.GetEpisode(episode2.SeriesId, episode2.SeasonNumber, episode2.EpisodeNumber)) - .Returns(episode2); - - mocker.GetMock() - .Setup(p => p.QualityWanted(series.SeriesId, parseResultMulti.Quality)) - .Returns(true); - - mocker.GetMock() - .Setup(p => p.IsIgnored(series.SeriesId, parseResultMulti.SeasonNumber)) - .Returns(false); - - mocker.GetMock() - .Setup(p => p.IsNeeded(parseResultMulti, episode)) - .Returns(true); - - mocker.GetMock() - .Setup(p => p.Exists(episode.EpisodeId, parseResultMulti.Quality, parseResultMulti.Proper)) - .Returns(false); - - //Act - var result = mocker.Resolve().IsNeeded(parseResultMulti); - - //Assert - Assert.IsTrue(result); - Assert.Contains(parseResultMulti.Episodes, episode); - Assert.Contains(parseResultMulti.Episodes, episode2); - Assert.AreEqual(series, parseResultMulti.Series); - mocker.VerifyAllMocks(); - } - - [Test] - public void second_file_needed_should_return_true() - { - var mocker = new AutoMoqer(MockBehavior.Strict); - - mocker.GetMock() - .Setup(p => p.FindSeries(It.IsAny())) - .Returns(series); - - mocker.GetMock() - .Setup(p => p.GetEpisode(episode.SeriesId, episode.SeasonNumber, episode.EpisodeNumber)) - .Returns(episode); - - mocker.GetMock() - .Setup(p => p.GetEpisode(episode2.SeriesId, episode2.SeasonNumber, episode2.EpisodeNumber)) - .Returns(episode2); - - - mocker.GetMock() - .Setup(p => p.QualityWanted(series.SeriesId, parseResultMulti.Quality)) - .Returns(true); - - mocker.GetMock() - .Setup(p => p.IsIgnored(series.SeriesId, parseResultMulti.SeasonNumber)) - .Returns(false); - - mocker.GetMock() - .Setup(p => p.IsNeeded(parseResultMulti, episode)) - .Returns(false); - - mocker.GetMock() - .Setup(p => p.IsNeeded(parseResultMulti, episode2)) - .Returns(true); - - mocker.GetMock() - .Setup(p => p.Exists(episode2.EpisodeId, parseResultMulti.Quality, parseResultMulti.Proper)) - .Returns(false); - - //Act - var result = mocker.Resolve().IsNeeded(parseResultMulti); - - //Assert - Assert.IsTrue(result); - Assert.Contains(parseResultMulti.Episodes, episode); - Assert.Contains(parseResultMulti.Episodes, episode2); - Assert.AreEqual(series, parseResultMulti.Series); - mocker.VerifyAllMocks(); - } - } - - - - -} \ No newline at end of file diff --git a/NzbDrone.Core.Test/InventoryProvider_IsMonitoredTest.cs b/NzbDrone.Core.Test/InventoryProvider_IsMonitoredTest.cs new file mode 100644 index 000000000..387502cd0 --- /dev/null +++ b/NzbDrone.Core.Test/InventoryProvider_IsMonitoredTest.cs @@ -0,0 +1,207 @@ +// ReSharper disable RedundantUsingDirective +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.ServiceModel.Syndication; +using AutoMoq; +using FizzWare.NBuilder; +using MbUnit.Framework; +using Moq; +using NzbDrone.Core.Model; +using NzbDrone.Core.Providers; +using NzbDrone.Core.Providers.Core; +using NzbDrone.Core.Providers.ExternalNotification; +using NzbDrone.Core.Providers.Indexer; +using NzbDrone.Core.Repository; +using NzbDrone.Core.Repository.Quality; +using NzbDrone.Core.Test.Framework; + +namespace NzbDrone.Core.Test +{ + [TestFixture] + // ReSharper disable InconsistentNaming + public class InventoryProvider_IsMonitoredTest : TestBase + { + private EpisodeParseResult parseResultMulti; + private Series series; + private Episode episode; + private Episode episode2; + private EpisodeParseResult parseResultSingle; + + [SetUp] + public new void Setup() + { + parseResultMulti = new EpisodeParseResult() + { + CleanTitle = "Title", + Language = LanguageType.English, + Quality = new Quality(QualityTypes.Bluray720p, true), + EpisodeNumbers = new List { 3, 4 }, + SeasonNumber = 12, + AirDate = DateTime.Now.AddDays(-12).Date, + }; + + parseResultSingle = new EpisodeParseResult() + { + CleanTitle = "Title", + Language = LanguageType.English, + Quality = new Quality(QualityTypes.Bluray720p, true), + EpisodeNumbers = new List { 3 }, + SeasonNumber = 12, + AirDate = DateTime.Now.AddDays(-12).Date, + }; + + + episode = Builder.CreateNew() + .With(c => c.EpisodeNumber = parseResultMulti.EpisodeNumbers[0]) + .With(c => c.SeasonNumber = parseResultMulti.SeasonNumber) + .With(c => c.AirDate = parseResultMulti.AirDate) + .With(c => c.Title = "EpisodeTitle1") + .Build(); + + episode2 = Builder.CreateNew() + .With(c => c.EpisodeNumber = parseResultMulti.EpisodeNumbers[1]) + .With(c => c.SeasonNumber = parseResultMulti.SeasonNumber) + .With(c => c.AirDate = parseResultMulti.AirDate) + .With(c => c.Title = "EpisodeTitle2") + .Build(); + + + series = Builder.CreateNew() + .With(c => c.Monitored = true) + .With(d => d.CleanTitle = parseResultMulti.CleanTitle) + .Build(); + + base.Setup(); + } + + + [Test] + public void not_monitored_series_should_be_skipped() + { + series.Monitored = false; + + var mocker = new AutoMoqer(MockBehavior.Strict); + + mocker.GetMock() + .Setup(p => p.FindSeries(It.IsAny())) + .Returns(series); + + //Act + var result = mocker.Resolve().IsMonitored(parseResultMulti); + + //Assert + Assert.IsFalse(result); + Assert.AreSame(series, parseResultMulti.Series); + mocker.VerifyAllMocks(); + } + + + [Test] + public void not_in_db_should_be_skipped() + { + var mocker = new AutoMoqer(MockBehavior.Strict); + + mocker.GetMock() + .Setup(p => p.FindSeries(It.IsAny())) + .Returns(null); + + //Act + var result = mocker.Resolve().IsMonitored(parseResultMulti); + + //Assert + Assert.IsFalse(result); + mocker.VerifyAllMocks(); + } + + [Test] + public void ignored_season_should_be_skipped() + { + var mocker = new AutoMoqer(MockBehavior.Strict); + + mocker.GetMock() + .Setup(p => p.FindSeries(It.IsAny())) + .Returns(series); + + mocker.GetMock() + .Setup(p => p.IsIgnored(series.SeriesId, parseResultMulti.SeasonNumber)) + .Returns(true); + + //Act + var result = mocker.Resolve().IsMonitored(parseResultMulti); + + //Assert + Assert.IsFalse(result); + Assert.AreSame(series, parseResultMulti.Series); + mocker.VerifyAllMocks(); + } + + [Test] + public void IsMonitored_dailyshow_should_do_daily_lookup() + { + var mocker = new AutoMoqer(MockBehavior.Strict); + + mocker.GetMock() + .Setup(p => p.FindSeries(It.IsAny())) + .Returns(series); + + mocker.GetMock() + .Setup(p => p.GetEpisode(episode.SeriesId, episode.SeasonNumber, episode.EpisodeNumber)) + .Returns(null); + + mocker.GetMock() + .Setup(p => p.GetEpisode(episode.SeriesId, episode.AirDate)) + .Returns(episode); + + + mocker.GetMock() + .Setup(p => p.IsIgnored(series.SeriesId, parseResultSingle.SeasonNumber)) + .Returns(false); + + + var result = mocker.Resolve().IsMonitored(parseResultSingle); + + //Assert + Assert.IsTrue(result); + Assert.AreSame(series, parseResultSingle.Series); + mocker.VerifyAllMocks(); + } + + [Test] + public void none_db_episode_should_be_added() + { + var mocker = new AutoMoqer(MockBehavior.Strict); + + mocker.GetMock() + .Setup(p => p.FindSeries(It.IsAny())) + .Returns(series); + + mocker.GetMock() + .Setup(p => p.IsIgnored(series.SeriesId, parseResultSingle.SeasonNumber)) + .Returns(false); + + mocker.GetMock() + .Setup(p => p.GetEpisode(episode.SeriesId, episode.SeasonNumber, episode.EpisodeNumber)) + .Returns(null); + + mocker.GetMock() + .Setup(p => p.GetEpisode(episode.SeriesId, episode.AirDate)) + .Returns(null); + + mocker.GetMock() + .Setup(p => p.AddEpisode(It.IsAny())) + .Returns(12); + + //Act + var result = mocker.Resolve().IsMonitored(parseResultSingle); + + //Assert + Assert.IsTrue(result); + Assert.AreSame(series, parseResultSingle.Series); + Assert.Count(1, parseResultSingle.Episodes); + Assert.AreEqual("TBD", parseResultSingle.Episodes[0].Title); + mocker.VerifyAllMocks(); + } + } +} \ No newline at end of file diff --git a/NzbDrone.Core.Test/InventoryProvider_QualityNeededTest.cs b/NzbDrone.Core.Test/InventoryProvider_QualityNeededTest.cs new file mode 100644 index 000000000..34a1c5a26 --- /dev/null +++ b/NzbDrone.Core.Test/InventoryProvider_QualityNeededTest.cs @@ -0,0 +1,234 @@ +// ReSharper disable RedundantUsingDirective +using System; +using System.Collections.Generic; +using AutoMoq; +using FizzWare.NBuilder; +using MbUnit.Framework; +using Moq; +using NzbDrone.Core.Model; +using NzbDrone.Core.Providers; +using NzbDrone.Core.Repository; +using NzbDrone.Core.Repository.Quality; +using NzbDrone.Core.Test.Framework; + +namespace NzbDrone.Core.Test +{ + [TestFixture] + // ReSharper disable InconsistentNaming + public class InventoryProvider_QualityNeededTest : TestBase + { + private Episode episode; + private Episode episode2; + private EpisodeFile episodeFile; + private QualityProfile hdProfile; + private EpisodeParseResult parseResultMulti; + private EpisodeParseResult parseResultSingle; + private QualityProfile sdProfile; + private Series series; + + [SetUp] + public new void Setup() + { + parseResultMulti = new EpisodeParseResult + { + CleanTitle = "Title", + Language = LanguageType.English, + Quality = new Quality(QualityTypes.Bluray720p, true), + EpisodeNumbers = new List { 3, 4 }, + SeasonNumber = 12, + AirDate = DateTime.Now.AddDays(-12).Date, + Episodes = new List() + }; + + parseResultSingle = new EpisodeParseResult + { + CleanTitle = "Title", + Language = LanguageType.English, + Quality = new Quality(QualityTypes.Bluray720p, true), + EpisodeNumbers = new List { 3 }, + SeasonNumber = 12, + AirDate = DateTime.Now.AddDays(-12).Date, + Episodes = new List() + }; + + episodeFile = Builder.CreateNew().With(c => c.Quality = QualityTypes.DVD).Build(); + + episode = Builder.CreateNew() + .With(c => c.EpisodeNumber = parseResultMulti.EpisodeNumbers[0]) + .With(c => c.SeasonNumber = parseResultMulti.SeasonNumber) + .With(c => c.AirDate = parseResultMulti.AirDate) + .With(c => c.Title = "EpisodeTitle1") + .With(c => c.EpisodeFile = episodeFile) + .Build(); + + episode2 = Builder.CreateNew() + .With(c => c.EpisodeNumber = parseResultMulti.EpisodeNumbers[1]) + .With(c => c.SeasonNumber = parseResultMulti.SeasonNumber) + .With(c => c.AirDate = parseResultMulti.AirDate) + .With(c => c.Title = "EpisodeTitle2") + .With(c => c.EpisodeFile = episodeFile) + .Build(); + + sdProfile = new QualityProfile + { + Name = "SD", + Allowed = new List { QualityTypes.SDTV, QualityTypes.DVD }, + Cutoff = QualityTypes.DVD + }; + + hdProfile = new QualityProfile + { + Name = "HD", + Allowed = + new List + { + QualityTypes.HDTV, + QualityTypes.WEBDL, + QualityTypes.Bluray720p, + QualityTypes.Bluray1080p + }, + Cutoff = QualityTypes.Bluray720p + }; + + series = Builder.CreateNew() + .With(c => c.Monitored = true) + .With(d => d.CleanTitle = parseResultMulti.CleanTitle) + .With(c => c.QualityProfile = sdProfile) + .Build(); + + parseResultMulti.Series = series; + parseResultSingle.Series = series; + + parseResultSingle.Episodes.Add(episode); + parseResultMulti.Episodes.Add(episode); + parseResultMulti.Episodes.Add(episode2); + + + base.Setup(); + } + + [Test] + public void IsQualityNeeded_report_not_in_quality_profile_should_be_skipped() + { + var mocker = new AutoMoqer(MockBehavior.Strict); + + parseResultMulti.Series.QualityProfile = sdProfile; + parseResultMulti.Quality = new Quality(QualityTypes.HDTV, true); + + //Act + bool result = mocker.Resolve().IsQualityNeeded(parseResultMulti); + + //Assert + Assert.IsFalse(result); + mocker.VerifyAllMocks(); + } + + [Test] + public void IsQualityNeeded_file_already_at_cut_off_should_be_skipped() + { + var mocker = new AutoMoqer(MockBehavior.Strict); + + parseResultMulti.Series.QualityProfile = hdProfile; + parseResultMulti.Episodes[0].EpisodeFile.Quality = QualityTypes.Bluray720p; + parseResultMulti.Quality = new Quality(QualityTypes.HDTV, true); + + //Act + bool result = mocker.Resolve().IsQualityNeeded(parseResultMulti); + + //Assert + Assert.IsFalse(result); + mocker.VerifyAllMocks(); + } + + + [Test] + public void IsQualityNeeded_file_in_history_should_be_skipped() + { + var mocker = new AutoMoqer(MockBehavior.Strict); + + parseResultSingle.Series.QualityProfile = sdProfile; + parseResultSingle.Episodes[0].EpisodeFile.Quality = QualityTypes.SDTV; + parseResultSingle.Quality.QualityType = QualityTypes.DVD; + + mocker.GetMock() + .Setup(p => p.GetBestQualityInHistory(episode.EpisodeId)) + .Returns(new Quality(QualityTypes.DVD, true)); + + //Act + bool result = mocker.Resolve().IsQualityNeeded(parseResultSingle); + + //Assert + Assert.IsFalse(result); + mocker.VerifyAllMocks(); + } + + [Test] + public void IsQualityNeeded_lesser_file_in_history_should_be_downloaded() + { + var mocker = new AutoMoqer(MockBehavior.Strict); + + parseResultSingle.Series.QualityProfile = sdProfile; + parseResultSingle.Episodes[0].EpisodeFile.Quality = QualityTypes.SDTV; + parseResultSingle.Quality.QualityType = QualityTypes.DVD; + + mocker.GetMock() + .Setup(p => p.GetBestQualityInHistory(episode.EpisodeId)) + .Returns(new Quality(QualityTypes.SDTV, true)); + + //Act + bool result = mocker.Resolve().IsQualityNeeded(parseResultSingle); + + //Assert + Assert.IsTrue(result); + mocker.VerifyAllMocks(); + } + + [Test] + public void IsQualityNeeded_file_not_in_history_should_be_downloaded() + { + var mocker = new AutoMoqer(MockBehavior.Strict); + + parseResultSingle.Series.QualityProfile = sdProfile; + parseResultSingle.Episodes[0].EpisodeFile.Quality = QualityTypes.SDTV; + parseResultSingle.Quality.QualityType = QualityTypes.DVD; + + mocker.GetMock() + .Setup(p => p.GetBestQualityInHistory(episode.EpisodeId)) + .Returns(null); + + //Act + bool result = mocker.Resolve().IsQualityNeeded(parseResultSingle); + + //Assert + Assert.IsTrue(result); + mocker.VerifyAllMocks(); + } + + //Should Download + [Test] + [Row(QualityTypes.SDTV, true, QualityTypes.HDTV, false, true)] + [Row(QualityTypes.DVD, true, QualityTypes.Bluray720p, true, true)] + [Row(QualityTypes.HDTV, false, QualityTypes.HDTV, true, true)] + [Row(QualityTypes.HDTV, false, QualityTypes.HDTV, false, false)] + [Row(QualityTypes.Bluray720p, true, QualityTypes.Bluray1080p, false, false)] + [Row(QualityTypes.HDTV, true, QualityTypes.Bluray720p, true, true)] + [Row(QualityTypes.Bluray1080p, true, QualityTypes.Bluray720p, true, false)] + [Row(QualityTypes.Bluray1080p, true, QualityTypes.Bluray720p, false, false)] + [Row(QualityTypes.Bluray1080p, false, QualityTypes.Bluray720p, true, false)] + [Row(QualityTypes.HDTV, false, QualityTypes.Bluray720p, true, true)] + [Row(QualityTypes.HDTV, true, QualityTypes.HDTV, false, false)] + public void Is_upgrade(QualityTypes fileQuality, bool isFileProper, QualityTypes reportQuality, + bool isReportProper, bool excpected) + { + //Setup + + var currentQuality = new Quality(fileQuality, isFileProper); + var newQuality = new Quality(reportQuality, isReportProper); + + bool result = InventoryProvider.IsUpgrade(currentQuality, newQuality, QualityTypes.Bluray720p); + + + Assert.AreEqual(excpected, result); + } + } +} \ No newline at end of file diff --git a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj index 1f5e05cf4..068d76fb8 100644 --- a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj +++ b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj @@ -85,13 +85,14 @@ + - + @@ -103,6 +104,7 @@ + diff --git a/NzbDrone.Core.Test/ParserTest.cs b/NzbDrone.Core.Test/ParserTest.cs index b36512ab4..785b22d7c 100644 --- a/NzbDrone.Core.Test/ParserTest.cs +++ b/NzbDrone.Core.Test/ParserTest.cs @@ -100,14 +100,14 @@ namespace NzbDrone.Core.Test public void quality_parse(string postTitle, object quality) { var result = Parser.ParseQuality(postTitle); - Assert.AreEqual(quality, result); + Assert.AreEqual(quality, result.QualityType); } [Test] public void parsing_our_own_quality_enum() { var qualityEnums = Enum.GetValues(typeof(QualityTypes)); - + foreach (var qualityEnum in qualityEnums) { @@ -115,14 +115,14 @@ namespace NzbDrone.Core.Test var extention = "mkv"; - if (qualityEnum.ToString() ==QualityTypes.SDTV.ToString() || qualityEnum.ToString() ==QualityTypes.DVD.ToString()) + if (qualityEnum.ToString() == QualityTypes.SDTV.ToString() || qualityEnum.ToString() == QualityTypes.DVD.ToString()) { extention = "avi"; } - var fileName = String.Format("My series S01E01 [{0}].{1}", qualityEnum,extention); + var fileName = String.Format("My series S01E01 [{0}].{1}", qualityEnum, extention); var result = Parser.ParseQuality(fileName); - Assert.AreEqual(qualityEnum, result); + Assert.AreEqual(qualityEnum, result.QualityType); } } diff --git a/NzbDrone.Core.Test/QualityTest.cs b/NzbDrone.Core.Test/QualityTest.cs new file mode 100644 index 000000000..682ae5378 --- /dev/null +++ b/NzbDrone.Core.Test/QualityTest.cs @@ -0,0 +1,130 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Gallio.Framework; +using MbUnit.Framework; +using MbUnit.Framework.ContractVerifiers; +using NzbDrone.Core.Model; +using NzbDrone.Core.Repository.Quality; + +namespace NzbDrone.Core.Test +{ + [TestFixture] + // ReSharper disable InconsistentNaming + public class QualityTest + { + [Test] + public void Icomparer_greater_test() + { + var first = new Quality(QualityTypes.DVD, true); + var second = new Quality(QualityTypes.Bluray1080p, true); + + Assert.GreaterThan(second, first); + } + + [Test] + public void Icomparer_greater_proper() + { + var first = new Quality(QualityTypes.Bluray1080p, false); + var second = new Quality(QualityTypes.Bluray1080p, true); + + Assert.GreaterThan(second, first); + } + + [Test] + public void Icomparer_lesser() + { + var first = new Quality(QualityTypes.DVD, true); + var second = new Quality(QualityTypes.Bluray1080p, true); + + Assert.LessThan(first, second); + } + + [Test] + public void Icomparer_lesser_proper() + { + var first = new Quality(QualityTypes.DVD, false); + var second = new Quality(QualityTypes.DVD, true); + + Assert.LessThan(first, second); + } + + [Test] + public void equal_operand() + { + var first = new Quality(QualityTypes.Bluray1080p, true); + var second = new Quality(QualityTypes.Bluray1080p, true); + + Assert.IsTrue(first == second); + Assert.IsTrue(first >= second); + Assert.IsTrue(first <= second); + } + + [Test] + public void equal_operand_false() + { + var first = new Quality(QualityTypes.Bluray1080p, true); + var second = new Quality(QualityTypes.Unknown, true); + + Assert.IsFalse(first == second); + } + + [Test] + public void equal_operand_false_proper() + { + var first = new Quality(QualityTypes.Bluray1080p, true); + var second = new Quality(QualityTypes.Bluray1080p, false); + + Assert.IsFalse(first == second); + } + + + [Test] + public void not_equal_operand() + { + var first = new Quality(QualityTypes.Bluray1080p, true); + var second = new Quality(QualityTypes.Bluray1080p, true); + + Assert.IsFalse(first != second); + } + + [Test] + public void not_equal_operand_false() + { + var first = new Quality(QualityTypes.Bluray1080p, true); + var second = new Quality(QualityTypes.Unknown, true); + + Assert.IsTrue(first != second); + } + + [Test] + public void not_equal_operand_false_proper() + { + var first = new Quality(QualityTypes.Bluray1080p, true); + var second = new Quality(QualityTypes.Bluray1080p, false); + + Assert.IsTrue(first != second); + } + + [Test] + public void greater_operand() + { + var first = new Quality(QualityTypes.DVD, true); + var second = new Quality(QualityTypes.Bluray1080p, true); + + Assert.IsTrue(first < second); + Assert.IsTrue(first <= second); + } + + [Test] + public void lesser_operand() + { + var first = new Quality(QualityTypes.DVD, true); + var second = new Quality(QualityTypes.Bluray1080p, true); + + Assert.IsTrue(second > first); + Assert.IsTrue(second >= first); + } + + } +} diff --git a/NzbDrone.Core.Test/RepoTest.cs b/NzbDrone.Core.Test/RepoTest.cs index afc1b665b..2ea42611c 100644 --- a/NzbDrone.Core.Test/RepoTest.cs +++ b/NzbDrone.Core.Test/RepoTest.cs @@ -39,6 +39,36 @@ namespace NzbDrone.Core.Test Assert.AreEqual(fetchedSeries.Episodes[0].Title, fakeEpisode.Title); } + [Test] + public void ToString_test_over_castle_proxy() + { + //Arrange + var fakeSeries = Builder.CreateNew().With(s => s.SeriesId = 69).Build(); + var fakeEpisode = Builder.CreateNew().With(c => c.SeriesId = 69).Build(); + + //Act + var repo = MockLib.GetEmptyRepository(true); + repo.Add(fakeSeries); + repo.Add(fakeEpisode); + Console.WriteLine("Getting single"); + var fetchedEpisode = repo.Single(fakeEpisode.EpisodeId); + + //Assert + Console.WriteLine("Doing assert"); + Assert.AreEqual(fakeEpisode.EpisodeId, fetchedEpisode.EpisodeId); + Console.WriteLine("Doing assert"); + Assert.AreEqual(fakeEpisode.Title, fetchedEpisode.Title); + + Console.WriteLine("======================="); + var ttt= fetchedEpisode.Series; + Console.WriteLine("======================="); + var tttd= fetchedEpisode.Series; + Console.WriteLine("======================="); + + //Assert.Contains(fetchedEpisode.ToString(), fakeSeries.Title); + } + + [Test] [Description( "This test confirms that the tvdb id stored in the db is preserved rather than being replaced by an auto incrementing value" diff --git a/NzbDrone.Core.Test/SabProviderTest.cs b/NzbDrone.Core.Test/SabProviderTest.cs index d5323f6a9..c0df3589e 100644 --- a/NzbDrone.Core.Test/SabProviderTest.cs +++ b/NzbDrone.Core.Test/SabProviderTest.cs @@ -1,5 +1,6 @@ // ReSharper disable RedundantUsingDirective using System; +using System.Collections.Generic; using System.IO; using System.Linq; using AutoMoq; @@ -226,17 +227,20 @@ namespace NzbDrone.Core.Test .With(c => c.Path = @"d:\tv shows\My Series Name") .Build(); + var episode = Builder.CreateNew() + .With(e => e.Title = title) + .Build(); + var parsResult = new EpisodeParseResult() { AirDate = DateTime.Now, EpisodeNumbers = episodes.ToList(), - Proper = proper, - Quality = quality, + Quality = new Quality(quality,proper), SeasonNumber = seasons, - EpisodeTitle = title, - Series = series + Series = series, + Episodes = new List() { episode } }; - + //Act var actual = mocker.Resolve().GetSabTitle(parsResult); diff --git a/NzbDrone.Core.Test/SeriesProviderTest.cs b/NzbDrone.Core.Test/SeriesProviderTest.cs index e54f61e8c0dbf74a0dd7650f93f5845f7b74e5c0..5f877a7452d1ee1f8f61084d6f022eb6c912d5db 100644 GIT binary patch delta 27 hcmbPjv)^z7hbR{>mjV#f@^aN~E|glu%*?>R003ni1~mWx delta 793 zcma))OE1Jw7=}ZcF-Dn7D@4MV*l1FXu|R@Jj3FcvjN8H`8ap4>m^~Q>|nMMh5o6{7KdRyLnA8JouIW z1)r&A{zs6tsa$^UQv@tTg<*gEHI>;!3zY$-PtC}XGYm>p1}3o_YU4&rcL2aR1mAPgv5jKUwfw4dApxJ$Q5@k!+>S>$m%+PazZ;0h;}m$O6wW*AMJv^&R>D_! z$+f?`9kiU|Lp*^m4Q+`JY+rX9$l_DIh|m}r+VN)IQKogK_5JKQt4WelAhu&ND?so* zE}*~*cou8-&X_NiMll&n;}$PO7$F+b@RaZE4MO_c%M8jv{A!`nDBp~Ats*9(v98+Q TWVd=x?p+1X`{=q!yy4yer9cFl diff --git a/NzbDrone.Core/Model/EpisodeParseResult.cs b/NzbDrone.Core/Model/EpisodeParseResult.cs index 4452d8fa9..280cb7f0b 100644 --- a/NzbDrone.Core/Model/EpisodeParseResult.cs +++ b/NzbDrone.Core/Model/EpisodeParseResult.cs @@ -13,13 +13,9 @@ namespace NzbDrone.Core.Model internal List EpisodeNumbers { get; set; } - internal string EpisodeTitle { get; set; } - internal DateTime AirDate { get; set; } - - public bool Proper { get; set; } - - public QualityTypes Quality { get; set; } + + public Quality Quality { get; set; } public LanguageType Language { get; set; } @@ -36,10 +32,10 @@ namespace NzbDrone.Core.Model public override string ToString() { if (EpisodeNumbers == null) - return string.Format("{0} - {1}", CleanTitle, AirDate.Date); + return string.Format("{0} - {1} {2}", CleanTitle, AirDate.ToShortDateString(), Quality); - return string.Format("{0} - S{1:00}E{2}", CleanTitle, SeasonNumber, - String.Join("-", EpisodeNumbers)); + return string.Format("{0} - S{1:00}E{2} {3}", CleanTitle, SeasonNumber, + String.Join("-", EpisodeNumbers),Quality); } } diff --git a/NzbDrone.Core/Model/Quality.cs b/NzbDrone.Core/Model/Quality.cs new file mode 100644 index 000000000..35922bc37 --- /dev/null +++ b/NzbDrone.Core/Model/Quality.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NzbDrone.Core.Repository.Quality; + +namespace NzbDrone.Core.Model +{ + public class Quality : IComparable + { + public QualityTypes QualityType { get; set; } + + public Boolean Proper { get; set; } + + public Quality() { } + + public Quality(QualityTypes quality, Boolean proper) + { + QualityType = quality; + Proper = proper; + } + + public int CompareTo(Quality other) + { + if (other.QualityType > this.QualityType) + return -1; + + if (other.QualityType < this.QualityType) + return 1; + + if (other.QualityType == this.QualityType && other.Proper == this.Proper) + return 0; + + if (this.Proper && !other.Proper) + return 1; + + if (!this.Proper && other.Proper) + return -1; + + return 0; + } + + public static bool operator !=(Quality x, Quality y) + { + return !(x == y); + } + + public static bool operator ==(Quality x, Quality y) + { + var xObj = (Object)x; + var yObj = (object)y; + + if (xObj == null || yObj == null) + { + return xObj == yObj; + } + + return x.CompareTo(y) == 0; + } + + public static bool operator >(Quality x, Quality y) + { + return x.CompareTo(y) > 0; + } + + public static bool operator <(Quality x, Quality y) + { + return x.CompareTo(y) < 1; + } + + public static bool operator <=(Quality x, Quality y) + { + return x.CompareTo(y) <= 0; + } + + public static bool operator >=(Quality x, Quality y) + { + return x.CompareTo(y) >= 0; + } + + public override string ToString() + { + string result = QualityType.ToString(); + if (Proper) + { + result += " [proper]"; + } + + return result; + } + } +} diff --git a/NzbDrone.Core/Model/SeasonParseResult.cs b/NzbDrone.Core/Model/SeasonParseResult.cs index 059850bff..3abc899c0 100644 --- a/NzbDrone.Core/Model/SeasonParseResult.cs +++ b/NzbDrone.Core/Model/SeasonParseResult.cs @@ -8,7 +8,7 @@ namespace NzbDrone.Core.Model internal int SeasonNumber { get; set; } internal int Year { get; set; } - public QualityTypes Quality { get; set; } + public Quality Quality { get; set; } public override string ToString() { diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index ca76530f6..d8d137655 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -169,6 +169,7 @@ + diff --git a/NzbDrone.Core/Parser.cs b/NzbDrone.Core/Parser.cs index 043e73c5e..8f1d15cfa 100644 --- a/NzbDrone.Core/Parser.cs +++ b/NzbDrone.Core/Parser.cs @@ -65,7 +65,6 @@ namespace NzbDrone.Core parsedEpisode = new EpisodeParseResult { - Proper = title.ToLower().Contains("proper"), CleanTitle = seriesName, SeasonNumber = season, EpisodeNumbers = new List() @@ -99,7 +98,6 @@ namespace NzbDrone.Core parsedEpisode = new EpisodeParseResult { - Proper = title.ToLower().Contains("proper"), CleanTitle = seriesName, AirDate = new DateTime(airyear, airmonth, airday), Language = ParseLanguage(simpleTitle) @@ -200,49 +198,65 @@ namespace NzbDrone.Core return title.ToLower().Contains("proper"); } - internal static QualityTypes ParseQuality(string name) + internal static Quality ParseQuality(string name) { Logger.Trace("Trying to parse quality for {0}", name); name = name.Trim(); var normilizedName = NormalizeTitle(name); - var result = QualityTypes.Unknown; + var result = new Quality { QualityType = QualityTypes.Unknown }; + result.Proper = normilizedName.Contains("proper"); if (normilizedName.Contains("dvd") || normilizedName.Contains("bdrip") || normilizedName.Contains("brrip")) { - return QualityTypes.DVD; + result.QualityType = QualityTypes.DVD; + return result; } if (normilizedName.Contains("xvid") || normilizedName.Contains("divx")) { if (normilizedName.Contains("bluray")) { - return QualityTypes.DVD; + result.QualityType = QualityTypes.DVD; + return result; } - return QualityTypes.SDTV; + result.QualityType = QualityTypes.SDTV; + return result; } if (normilizedName.Contains("bluray")) { if (normilizedName.Contains("720p")) - return QualityTypes.Bluray720p; + { + result.QualityType = QualityTypes.Bluray720p; + return result; + } if (normilizedName.Contains("1080p")) - return QualityTypes.Bluray1080p; + { + result.QualityType = QualityTypes.Bluray1080p; + return result; + } - return QualityTypes.Bluray720p; + result.QualityType = QualityTypes.Bluray720p; + return result; } if (normilizedName.Contains("webdl")) - return QualityTypes.WEBDL; + { + result.QualityType = QualityTypes.WEBDL; + return result; + } if (normilizedName.Contains("x264") || normilizedName.Contains("h264") || normilizedName.Contains("720p")) - return QualityTypes.HDTV; - + { + result.QualityType = QualityTypes.HDTV; + return result; + } //Based on extension - if (result == QualityTypes.Unknown) + if (result.QualityType == QualityTypes.Unknown) { try { @@ -253,12 +267,12 @@ namespace NzbDrone.Core case ".wmv": case ".mp4": { - result = QualityTypes.SDTV; + result.QualityType = QualityTypes.SDTV; break; } case ".mkv": { - result = QualityTypes.HDTV; + result.QualityType = QualityTypes.HDTV; break; } } @@ -270,15 +284,18 @@ namespace NzbDrone.Core } } - if (normilizedName.Contains("sdtv") || (result == QualityTypes.Unknown && normilizedName.Contains("hdtv"))) + if (normilizedName.Contains("sdtv") || (result.QualityType == QualityTypes.Unknown && normilizedName.Contains("hdtv"))) { - return QualityTypes.SDTV; + result.QualityType = QualityTypes.SDTV; + return result; } Logger.Trace("Quality Parsed:{0} Title:", result, name); return result; } + + internal static LanguageType ParseLanguage(string title) { if (title.ToLower().Contains("english")) diff --git a/NzbDrone.Core/Providers/DownloadProvider.cs b/NzbDrone.Core/Providers/DownloadProvider.cs index 1070eaded..5c238a983 100644 --- a/NzbDrone.Core/Providers/DownloadProvider.cs +++ b/NzbDrone.Core/Providers/DownloadProvider.cs @@ -47,8 +47,8 @@ namespace NzbDrone.Core.Providers var history = new History(); history.Date = DateTime.Now; history.Indexer = parseResult.Indexer; - history.IsProper = parseResult.Proper; - history.Quality = parseResult.Quality; + history.IsProper = parseResult.Quality.Proper; + history.Quality = parseResult.Quality.QualityType; history.NzbTitle = parseResult.NzbTitle; history.EpisodeId = episode.EpisodeId; diff --git a/NzbDrone.Core/Providers/EpisodeProvider.cs b/NzbDrone.Core/Providers/EpisodeProvider.cs index bcb2a8968ccc3d654f4a09abc946ac56601c8713..e7b6724dc1f0ce19878193b0764a08bdd6c12385 100644 GIT binary patch delta 16 YcmbOdd%$nQWX{P4<>WTA3iita06pFYQ2+n{ delta 1407 zcma)6%Wl&^6kW8a>LaOCl~9lnmk6RnDt2K>ov2V+DH5vs0Cp@U@pU}Z@tB!$LsV7$ zi0Nmr0I{ax6X*}H;X~k#W4B3FA+m7hdGERBoI5{u&fb49v!~#?E_f>K_n92FN^_9^ z>@vWn=qD0Gj1@mZ=!V!m1QEj^L>;08At4qTbjTH8!jbh@85rhGcA|mRD)FGA_Xil_}UNNbJ1zh+z3Sz~IP!Xpg zv#Juu1B8%~)-3kzc)(%}Tsw{fHYWW$(6)ldhhzEzI3wE>Wfmx*H9={y+%V@04XV9d z%{U2}BCuK$<{X#<>X0W1u~9W_d1Y~=A_Oc_mRs|C`7u@84l?^$J}p*jJL?XGXT8^q$in=DwCCUHOU_h3HcBh(H?6~O-;;M zhBj0EL<9l6V^NC#rXXX$8zW#|>Pd-Tm*=0^ws8(na#Y18m2ZW2D3?v;H7BgyFc%9I z^K;>jS-Ulzxn%Fkt_f2bx;e&z5GQkqJzkn{N)~9NvS_@@BXeFU*NTp|t#$cOQD=?! zePi8xox1&2%M{n?btIFKw|Yp=oF#~EC4y5^*aoqDT{_slghM*kL25RMAF!*fA8qTg SZWj~VM}|$+zI~oOyZ;wa(h => h.EpisodeId == episodeId && h.Quality == quality && h.IsProper == proper)) - { - Logger.Debug("Episode in History. ID:{0} Q:{1} Proper:{2}", episodeId, quality, proper); - return true; - } - Logger.Debug("Episode not in History. ID:{0} Q:{1} Proper:{2}", episodeId, quality, proper); - return false; + var history = AllItems().Where(c => c.EpisodeId == episodeId).Select(d => new Quality() { QualityType = d.Quality, Proper = d.IsProper }).ToList(); + history.Sort(); + return history.FirstOrDefault(); } public virtual void Delete(int historyId) diff --git a/NzbDrone.Core/Providers/Indexer/Newzbin.cs b/NzbDrone.Core/Providers/Indexer/Newzbin.cs index 4c96228ca..e2df61f1a 100644 --- a/NzbDrone.Core/Providers/Indexer/Newzbin.cs +++ b/NzbDrone.Core/Providers/Indexer/Newzbin.cs @@ -53,10 +53,8 @@ namespace NzbDrone.Core.Providers.Indexer if (currentResult != null) { var quality = Parser.ParseQuality(item.Summary.Text); - var proper = Parser.ParseProper(item.Summary.Text); - currentResult.Quality = quality; - currentResult.Proper = proper; + currentResult.Quality = quality; } return currentResult; } diff --git a/NzbDrone.Core/Providers/InventoryProvider.cs b/NzbDrone.Core/Providers/InventoryProvider.cs index 804e1a84f..893027350 100644 --- a/NzbDrone.Core/Providers/InventoryProvider.cs +++ b/NzbDrone.Core/Providers/InventoryProvider.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using NLog; using NzbDrone.Core.Model; using NzbDrone.Core.Repository; +using NzbDrone.Core.Repository.Quality; namespace NzbDrone.Core.Providers { @@ -25,10 +26,11 @@ namespace NzbDrone.Core.Providers public InventoryProvider() { - + } - public virtual bool IsNeeded(EpisodeParseResult parseResult) + + public virtual bool IsMonitored(EpisodeParseResult parseResult) { var series = _seriesProvider.FindSeries(parseResult.CleanTitle); @@ -47,12 +49,6 @@ namespace NzbDrone.Core.Providers return false; } - if (!_seriesProvider.QualityWanted(series.SeriesId, parseResult.Quality)) - { - Logger.Debug("Post doesn't meet the quality requirements [{0}]. skipping.", parseResult.Quality); - return false; - } - if (_seasonProvider.IsIgnored(series.SeriesId, parseResult.SeasonNumber)) { Logger.Debug("Season {0} is currently set to ignore. skipping.", parseResult.SeasonNumber); @@ -76,7 +72,7 @@ namespace NzbDrone.Core.Providers AirDate = DateTime.Now.Date, EpisodeNumber = episodeNumber, SeasonNumber = parseResult.SeasonNumber, - Title = parseResult.EpisodeTitle, + Title = "TBD", Overview = String.Empty, }; @@ -86,34 +82,79 @@ namespace NzbDrone.Core.Providers parseResult.Episodes.Add(episodeInfo); } - foreach (var episode in parseResult.Episodes) - { - //Todo: How to handle full season files? Currently the episode list is completely empty for these releases - //Todo: Should we assume that the release contains all the episodes that belong to this season and add them from the DB? - //Todo: Fix this so it properly handles multi-epsiode releases (Currently as long as the first episode is needed we download it) - //Todo: for small releases this is less of an issue, but for Full Season Releases this could be an issue if we only need the first episode (or first few) + return true; + } + /// + /// Comprehensive check on whether or not this episode is needed. + /// + /// Episode that needs to be checked + /// Whether or not the file quality meets the requirements + /// for multi episode files, all episodes need to meet the requirement + /// before the report is downloaded + public virtual bool IsQualityNeeded(EpisodeParseResult parsedReport) + { + Logger.Trace("Checking if report meets quality requirements. {0}", parsedReport.Quality); + if (!parsedReport.Series.QualityProfile.Allowed.Contains(parsedReport.Quality.QualityType)) + { + Logger.Trace("Quality {0} rejected by Series' quality profile", parsedReport.Quality); + return false; + } + var cutoff = parsedReport.Series.QualityProfile.Cutoff; - if (!_episodeProvider.IsNeeded(parseResult, episode)) + foreach (var episode in parsedReport.Episodes) + { + //Checking File + var file = episode.EpisodeFile; + if (file != null) { - Logger.Debug("Episode {0} is not needed. skipping.", parseResult); - continue; + Logger.Trace("Comparing file quality with report. Existing file is {0} proper:{1}", file.Quality, file.Proper); + if (!IsUpgrade(new Quality { QualityType = file.Quality, Proper = file.Proper }, parsedReport.Quality, cutoff)) + return false; } - if (_historyProvider.Exists(episode.EpisodeId, parseResult.Quality, parseResult.Proper)) + //Checking History + var bestQualityInHistory = _historyProvider.GetBestQualityInHistory(episode.EpisodeId); + if (bestQualityInHistory != null) { - Logger.Debug("Episode {0} is in history. skipping.", parseResult); - continue; + Logger.Trace("Comparing history quality with report. History is {0}", bestQualityInHistory); + if (!IsUpgrade(bestQualityInHistory, parsedReport.Quality, cutoff)) + return false; } - //Congragulations younge feed item! you have made it this far. you are truly special!!! - Logger.Debug("Episode {0} is needed", parseResult); + } + Logger.Debug("Episode {0} is needed", parsedReport); + return true; //If we get to this point and the file has not yet been rejected then accept it + } + + + public static bool IsUpgrade(Quality currentQuality, Quality newQuality, QualityTypes cutOff) + { + if (currentQuality.QualityType >= cutOff) + { + Logger.Trace("Existing file meets cut-off. skipping."); + return false; + } + + if (newQuality > currentQuality) return true; + + if (currentQuality > newQuality) + { + Logger.Trace("existing item has better quality. skipping"); + return false; + } + + if (currentQuality == newQuality && !newQuality.Proper) + { + Logger.Trace("same quality. not proper skipping"); + return false; } - return false; + Logger.Debug("New item has better quality than existing item"); + return true; } } } \ No newline at end of file diff --git a/NzbDrone.Core/Providers/Jobs/EpisodeSearchJob.cs b/NzbDrone.Core/Providers/Jobs/EpisodeSearchJob.cs index c26cb4efd..cb80525aa 100644 --- a/NzbDrone.Core/Providers/Jobs/EpisodeSearchJob.cs +++ b/NzbDrone.Core/Providers/Jobs/EpisodeSearchJob.cs @@ -45,7 +45,7 @@ namespace NzbDrone.Core.Providers.Jobs var episode = _episodeProvider.GetEpisode(targetId); if (episode == null) { - Logger.Error("Unbale to find an episode {0} in database", targetId); + Logger.Error("Unable to find an episode {0} in database", targetId); return; } @@ -80,19 +80,36 @@ namespace NzbDrone.Core.Providers.Jobs Logger.Debug("Finished searching all indexers. Total {0}", reports.Count); notification.CurrentMessage = "Processing search results"; + reports.ForEach(c => + { + c.Series = episode.Series; + c.Episodes = new List { episode }; + }); + ProcessResults(notification, episode, reports); } public void ProcessResults(ProgressNotification notification, Episode episode, IEnumerable reports) { - foreach (var episodeParseResult in reports.OrderByDescending(c => c.Quality).ThenByDescending(c => c.Proper)) + foreach (var episodeParseResult in reports.OrderByDescending(c => c.Quality)) { try { - if (_inventoryProvider.IsNeeded(episodeParseResult)) + Logger.Trace("Analysing report " + episodeParseResult); + if (_inventoryProvider.IsQualityNeeded(episodeParseResult)) { - _downloadProvider.DownloadReport(episodeParseResult); - notification.CurrentMessage = String.Format("{0} {1} Added to download queue", episode, episodeParseResult.Quality); + Logger.Debug("Found '{0}'. Adding to download queue.", episodeParseResult); + try + { + _downloadProvider.DownloadReport(episodeParseResult); + notification.CurrentMessage = String.Format("{0} {1} Added to download queue", episode, episodeParseResult.Quality); + } + catch (Exception e) + { + Logger.ErrorException("Unable to add report to download queue." + episodeParseResult, e); + notification.CurrentMessage = String.Format("Unable to add report to download queue. {0}", episodeParseResult); + } + return; } } @@ -103,6 +120,7 @@ namespace NzbDrone.Core.Providers.Jobs } Logger.Warn("Unable to find {0} in any of indexers.", episode); + notification.CurrentMessage = String.Format("Unable to find {0} in any of indexers.", episode); } } } \ No newline at end of file diff --git a/NzbDrone.Core/Providers/Jobs/RssSyncJob.cs b/NzbDrone.Core/Providers/Jobs/RssSyncJob.cs index 5ad822003..375a3f35c 100644 --- a/NzbDrone.Core/Providers/Jobs/RssSyncJob.cs +++ b/NzbDrone.Core/Providers/Jobs/RssSyncJob.cs @@ -49,18 +49,18 @@ namespace NzbDrone.Core.Providers.Jobs } catch (Exception e) { - Logger.ErrorException("An error has occured while fetching items from " + indexer.Name, e); + Logger.ErrorException("An error has occurred while fetching items from " + indexer.Name, e); } } Logger.Debug("Finished fetching reports from all indexers. Total {0}", reports.Count); - notification.CurrentMessage = "Proccessing downloaded RSS"; + notification.CurrentMessage = "Processing downloaded RSS"; foreach (var episodeParseResult in reports) { try { - if (_inventoryProvider.IsNeeded(episodeParseResult)) + if (_inventoryProvider.IsMonitored(episodeParseResult) && _inventoryProvider.IsQualityNeeded(episodeParseResult)) { _downloadProvider.DownloadReport(episodeParseResult); } diff --git a/NzbDrone.Core/Providers/MediaFileProvider.cs b/NzbDrone.Core/Providers/MediaFileProvider.cs index 0879692e7..9405ba8b5 100644 --- a/NzbDrone.Core/Providers/MediaFileProvider.cs +++ b/NzbDrone.Core/Providers/MediaFileProvider.cs @@ -123,8 +123,8 @@ namespace NzbDrone.Core.Providers episodeFile.SeriesId = series.SeriesId; episodeFile.Path = Parser.NormalizePath(filePath); episodeFile.Size = size; - episodeFile.Quality = parseResult.Quality; - episodeFile.Proper = Parser.ParseProper(filePath); + episodeFile.Quality = parseResult.Quality.QualityType; + episodeFile.Proper = parseResult.Quality.Proper; var fileId = (int)_repository.Add(episodeFile); //This is for logging + updating the episodes that are linked to this EpisodeFile diff --git a/NzbDrone.Core/Providers/SabProvider.cs b/NzbDrone.Core/Providers/SabProvider.cs index 8417eef9b..4d13c7611 100644 --- a/NzbDrone.Core/Providers/SabProvider.cs +++ b/NzbDrone.Core/Providers/SabProvider.cs @@ -105,9 +105,9 @@ namespace NzbDrone.Core.Providers var epNumberString = String.Join("-", episodeString); - var result = String.Format("{0} - {1} - {2} [{3}]", new DirectoryInfo(parseResult.Series.Path).Name, epNumberString, parseResult.EpisodeTitle, parseResult.Quality); + var result = String.Format("{0} - {1} - {2} [{3}]", new DirectoryInfo(parseResult.Series.Path).Name, epNumberString, parseResult.Episodes.FirstOrDefault().Title, parseResult.Quality.QualityType); - if (parseResult.Proper) + if (parseResult.Quality.Proper) { result += " [Proper]"; } diff --git a/NzbDrone.Core/Providers/SeriesProvider.cs b/NzbDrone.Core/Providers/SeriesProvider.cs index 641475851..248947b45 100644 --- a/NzbDrone.Core/Providers/SeriesProvider.cs +++ b/NzbDrone.Core/Providers/SeriesProvider.cs @@ -54,13 +54,6 @@ namespace NzbDrone.Core.Providers return _repository.Exists(c => c.SeriesId == id && c.Monitored); } - public virtual bool QualityWanted(int seriesId, QualityTypes quality) - { - var series = _repository.Single(seriesId); - Logger.Trace("Series {0} is using quality profile {1}", seriesId, series.QualityProfile.Name); - return series.QualityProfile.Allowed.Contains(quality); - } - public virtual TvdbSeries MapPathToSeries(string path) { var seriesPath = new DirectoryInfo(path); diff --git a/NzbDrone.Core/Repository/Episode.cs b/NzbDrone.Core/Repository/Episode.cs index 8318eb9fa..06a04f2b4 100644 --- a/NzbDrone.Core/Repository/Episode.cs +++ b/NzbDrone.Core/Repository/Episode.cs @@ -1,29 +1,30 @@ using System; using System.Collections.Generic; +using Castle.DynamicProxy; using NzbDrone.Core.Model; using SubSonic.SqlGeneration.Schema; namespace NzbDrone.Core.Repository { - public class Episode + public class Episode { [SubSonicPrimaryKey] public virtual int EpisodeId { get; set; } - public int? TvDbEpisodeId { get; set; } + public virtual int? TvDbEpisodeId { get; set; } public virtual int SeriesId { get; set; } public virtual int EpisodeFileId { get; set; } public virtual int SeasonId { get; set; } - public int SeasonNumber { get; set; } - public int EpisodeNumber { get; set; } - public string Title { get; set; } - public DateTime AirDate { get; set; } + public virtual int SeasonNumber { get; set; } + public virtual int EpisodeNumber { get; set; } + public virtual string Title { get; set; } + public virtual DateTime AirDate { get; set; } [SubSonicLongString] - public string Overview { get; set; } + public virtual string Overview { get; set; } - public Boolean Ignored { get; set; } + public virtual Boolean Ignored { get; set; } [SubSonicIgnore] public Boolean IsDailyEpisode @@ -41,7 +42,7 @@ namespace NzbDrone.Core.Repository /// Used to specify when the episode was grapped. /// this filed is used by status as an expirable "Grabbed" status. /// - public DateTime? GrabDate { get; set; } + public virtual DateTime? GrabDate { get; set; } [SubSonicIgnore] public EpisodeStatusType Status @@ -85,7 +86,7 @@ namespace NzbDrone.Core.Repository if (IsDailyEpisode) return string.Format("{0} - {1}", seriesTitle, AirDate.Date); - return string.Format("{0} - S{1:00}E{2}", seriesTitle, SeasonNumber, EpisodeNumber); + return string.Format("{0} - S{1:00}E{2:00}", seriesTitle, SeasonNumber, EpisodeNumber); } }