From 5717b7f596668df715015db4e3a3325831d2b08b Mon Sep 17 00:00:00 2001 From: "kay.one" Date: Mon, 6 Feb 2012 21:08:07 -0800 Subject: [PATCH] New: Rewrite of download decision engine. --- NzbDrone.App.Test/RouterTest.cs | 25 -- NzbDrone.Common/LogConfiguration.cs | 6 +- .../ServiceIntegerationFixture.cs | 20 +- NzbDrone.Core.Test/NzbDrone.Core.Test.csproj | 20 +- .../AcceptableSizeSpecificationFixture.cs} | 38 +-- .../AllowedDownloadSpecificationFixture.cs | 121 +++++++ .../MonitoredEpisodeSpecificationFixture.cs | 138 ++++++++ ...ityAllowedByProfileSpecificationFixtrue.cs | 69 ++++ .../QualityUpgradeSpecificationFixture.cs | 30 ++ .../UpgradeDiskSpecificationFixtrue.cs | 118 +++++++ .../UpgradeHistorySpecificationFixtrue.cs | 118 +++++++ .../UpgradePossibleSpecificationFixture.cs} | 19 +- .../DiskScanProviderTest_ImportFile.cs | 20 +- .../BlackholeProviderFixture.cs | 72 ++++ .../SabProviderTests/QueueFixture.cs | 5 +- .../SabProviderTests/SabProviderFixture.cs | 165 ++++++++++ .../ProviderTests/DownloadProviderFixture.cs | 249 ++++++++++++++ .../ProviderTests/DownloadProviderTest.cs | 125 ------- ...deProviderTest_GetEpisodesByParseResult.cs | 14 +- .../ProviderTests/HistoryProviderTest.cs | 140 +++++--- .../IsMonitoredFixture.cs | 272 --------------- .../IsUpgradeFixture.cs | 140 -------- .../QualityNeededFixture.cs | 311 ------------------ .../ProcessDownloadProviderFixture.cs | 53 ++- .../SabProviderTests/SabProviderTest.cs | 281 ---------------- .../ProcessDailySearchResultsFixture.cs | 17 +- .../ProcessSearchResultsFixture.cs | 23 +- .../SearchProviderTests/SearchFixture.cs | 3 +- NzbDrone.Core/Datastore/CustomeMapper.cs | 4 +- NzbDrone.Core/Jobs/RssSyncJob.cs | 16 +- NzbDrone.Core/NzbDrone.Core.csproj | 16 +- NzbDrone.Core/Providers/BackupProvider.cs | 3 - NzbDrone.Core/Providers/BlackholeProvider.cs | 61 ---- .../AcceptableSizeSpecification.cs | 66 ++++ .../AllowedDownloadSpecification.cs | 42 +++ .../AlreadyInQueueSpecification.cs | 32 ++ .../MonitoredEpisodeSpecification.cs | 56 ++++ .../QualityAllowedByProfileSpecification.cs | 35 ++ .../QualityUpgradeSpecification.cs | 23 ++ .../UpgradeDiskSpecification.cs | 37 +++ .../UpgradeHistorySpecification.cs | 44 +++ .../UpgradePossibleSpecification.cs | 40 +++ NzbDrone.Core/Providers/DiskScanProvider.cs | 12 +- .../DownloadClients/BlackholeProvider.cs | 70 ++++ .../DownloadClients/IDownloadClient.cs | 11 + .../{ => DownloadClients}/SabProvider.cs | 120 ++----- NzbDrone.Core/Providers/DownloadProvider.cs | 93 ++++-- NzbDrone.Core/Providers/EpisodeProvider.cs | 4 +- NzbDrone.Core/Providers/HistoryProvider.cs | 23 +- NzbDrone.Core/Providers/Indexer/Newzbin.cs | 13 +- NzbDrone.Core/Providers/InventoryProvider.cs | 209 ------------ NzbDrone.Core/Providers/SearchProvider.cs | 25 +- .../Repository/Quality/QualityType.cs | 6 +- .../NzbDrone.Services.Service/Global.asax.cs | 7 +- .../JsonModelBinder.cs | 37 ++- .../Migrations/Migration20120206.cs | 21 ++ .../NzbDrone.Services.Service.csproj | 1 + NzbDrone.Web/Controllers/CommandController.cs | 1 + NzbDrone.Web/Controllers/SystemController.cs | 1 + NzbDrone/Router.cs | 11 +- 60 files changed, 2010 insertions(+), 1742 deletions(-) rename NzbDrone.Core.Test/ProviderTests/{InventoryProviderTests/IsAcceptableSizeTestFixture.cs => DecisionEngineTests/AcceptableSizeSpecificationFixture.cs} (87%) create mode 100644 NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/AllowedDownloadSpecificationFixture.cs create mode 100644 NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/MonitoredEpisodeSpecificationFixture.cs create mode 100644 NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/QualityAllowedByProfileSpecificationFixtrue.cs create mode 100644 NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/QualityUpgradeSpecificationFixture.cs create mode 100644 NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/UpgradeDiskSpecificationFixtrue.cs create mode 100644 NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/UpgradeHistorySpecificationFixtrue.cs rename NzbDrone.Core.Test/ProviderTests/{InventoryProviderTests/IsUpgradePossibleFixture.cs => DecisionEngineTests/UpgradePossibleSpecificationFixture.cs} (81%) create mode 100644 NzbDrone.Core.Test/ProviderTests/DownloadClientTests/BlackholeProviderFixture.cs rename NzbDrone.Core.Test/ProviderTests/{ => DownloadClientTests}/SabProviderTests/QueueFixture.cs (98%) create mode 100644 NzbDrone.Core.Test/ProviderTests/DownloadClientTests/SabProviderTests/SabProviderFixture.cs create mode 100644 NzbDrone.Core.Test/ProviderTests/DownloadProviderFixture.cs delete mode 100644 NzbDrone.Core.Test/ProviderTests/DownloadProviderTest.cs delete mode 100644 NzbDrone.Core.Test/ProviderTests/InventoryProviderTests/IsMonitoredFixture.cs delete mode 100644 NzbDrone.Core.Test/ProviderTests/InventoryProviderTests/IsUpgradeFixture.cs delete mode 100644 NzbDrone.Core.Test/ProviderTests/InventoryProviderTests/QualityNeededFixture.cs delete mode 100644 NzbDrone.Core.Test/ProviderTests/SabProviderTests/SabProviderTest.cs delete mode 100644 NzbDrone.Core/Providers/BlackholeProvider.cs create mode 100644 NzbDrone.Core/Providers/DecisionEngine/AcceptableSizeSpecification.cs create mode 100644 NzbDrone.Core/Providers/DecisionEngine/AllowedDownloadSpecification.cs create mode 100644 NzbDrone.Core/Providers/DecisionEngine/AlreadyInQueueSpecification.cs create mode 100644 NzbDrone.Core/Providers/DecisionEngine/MonitoredEpisodeSpecification.cs create mode 100644 NzbDrone.Core/Providers/DecisionEngine/QualityAllowedByProfileSpecification.cs create mode 100644 NzbDrone.Core/Providers/DecisionEngine/QualityUpgradeSpecification.cs create mode 100644 NzbDrone.Core/Providers/DecisionEngine/UpgradeDiskSpecification.cs create mode 100644 NzbDrone.Core/Providers/DecisionEngine/UpgradeHistorySpecification.cs create mode 100644 NzbDrone.Core/Providers/DecisionEngine/UpgradePossibleSpecification.cs create mode 100644 NzbDrone.Core/Providers/DownloadClients/BlackholeProvider.cs create mode 100644 NzbDrone.Core/Providers/DownloadClients/IDownloadClient.cs rename NzbDrone.Core/Providers/{ => DownloadClients}/SabProvider.cs (72%) delete mode 100644 NzbDrone.Core/Providers/InventoryProvider.cs create mode 100644 NzbDrone.Services/NzbDrone.Services.Service/Migrations/Migration20120206.cs diff --git a/NzbDrone.App.Test/RouterTest.cs b/NzbDrone.App.Test/RouterTest.cs index 6235192c3..604db48db 100644 --- a/NzbDrone.App.Test/RouterTest.cs +++ b/NzbDrone.App.Test/RouterTest.cs @@ -135,30 +135,5 @@ namespace NzbDrone.App.Test Mocker.VerifyAllMocks(); } - - [Test] - public void should_delete_service_bat_files_if_they_exist() - { - WithTempAsAppPath(); - - var bat1 = @"c:\nzbdrone\ServiceInstall.bat"; - var bat2 = @"c:\nzbdrone\ServiceUninstall.bat"; - var bat3 = @"c:\nzbdrone\Someother.bat"; - var file1 = @"c:\nzbdrone\ServiceInstall.exe"; - var file2 = @"c:\nzbdrone\ServiceInstall.dat"; - - var files = new string[] {bat1, bat2, bat3, file1, file2}; - - Mocker.GetMock() - .Setup(c => c.GetFiles(VirtualPath, SearchOption.TopDirectoryOnly)).Returns(files); - - Mocker.Resolve().Route(ApplicationMode.Console); - - Mocker.GetMock().Verify(c=>c.DeleteFile(bat1)); - Mocker.GetMock().Verify(c=>c.DeleteFile(bat2)); - Mocker.GetMock().Verify(c=>c.DeleteFile(bat3),Times.Never()); - Mocker.GetMock().Verify(c=>c.DeleteFile(file1),Times.Never()); - Mocker.GetMock().Verify(c=>c.DeleteFile(file2),Times.Never()); - } } } diff --git a/NzbDrone.Common/LogConfiguration.cs b/NzbDrone.Common/LogConfiguration.cs index 6722caade..1b695dc97 100644 --- a/NzbDrone.Common/LogConfiguration.cs +++ b/NzbDrone.Common/LogConfiguration.cs @@ -119,9 +119,9 @@ namespace NzbDrone.Common { try { - var exTarget = new ExceptioneerTarget(); - LogManager.Configuration.AddTarget("Exceptioneer", exTarget); - LogManager.Configuration.LoggingRules.Add(new LoggingRule("*", LogLevel.Trace, exTarget)); + var exceptioneerTarget = new ExceptioneerTarget(); + LogManager.Configuration.AddTarget("Exceptioneer", exceptioneerTarget); + LogManager.Configuration.LoggingRules.Add(new LoggingRule("*", LogLevel.Trace, exceptioneerTarget)); } catch (Exception e) { diff --git a/NzbDrone.Core.Test/Integeration/ServiceIntegerationFixture.cs b/NzbDrone.Core.Test/Integeration/ServiceIntegerationFixture.cs index f1d9ace6d..55e269f79 100644 --- a/NzbDrone.Core.Test/Integeration/ServiceIntegerationFixture.cs +++ b/NzbDrone.Core.Test/Integeration/ServiceIntegerationFixture.cs @@ -1,7 +1,11 @@ -using System.Linq; +using System; +using System.Data; +using System.Linq; using FluentAssertions; +using NLog; using NUnit.Framework; using Ninject; +using NzbDrone.Common; using NzbDrone.Core.Providers; using NzbDrone.Core.Providers.Core; using NzbDrone.Core.Repository; @@ -51,6 +55,20 @@ namespace NzbDrone.Core.Test.Integeration } + [Test] + public void should_be_able_to_submit_exceptions() + { + ReportingService.RestProvider = new RestProvider(new EnviromentProvider()); + + var log = new LogEventInfo(); + log.LoggerName = "LoggerName.LoggerName.LoggerName.LoggerName"; + log.Exception = new ArgumentOutOfRangeException(); + log.Message = "New message string. New message string. New message string. New message string. New message string. New message string."; + + ReportingService.ReportException(log); + } + + } } \ 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 75290390c..96e742818 100644 --- a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj +++ b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj @@ -113,12 +113,16 @@ - - + + + + + + - + @@ -138,7 +142,7 @@ - + @@ -155,13 +159,13 @@ - - + + - + @@ -174,7 +178,7 @@ - + diff --git a/NzbDrone.Core.Test/ProviderTests/InventoryProviderTests/IsAcceptableSizeTestFixture.cs b/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/AcceptableSizeSpecificationFixture.cs similarity index 87% rename from NzbDrone.Core.Test/ProviderTests/InventoryProviderTests/IsAcceptableSizeTestFixture.cs rename to NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/AcceptableSizeSpecificationFixture.cs index acb954dab..300082d67 100644 --- a/NzbDrone.Core.Test/ProviderTests/InventoryProviderTests/IsAcceptableSizeTestFixture.cs +++ b/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/AcceptableSizeSpecificationFixture.cs @@ -1,24 +1,24 @@ // ReSharper disable RedundantUsingDirective +using System.Linq; using System; using System.Collections.Generic; - using FizzWare.NBuilder; using FluentAssertions; using Moq; using NUnit.Framework; using NzbDrone.Core.Model; using NzbDrone.Core.Providers; +using NzbDrone.Core.Providers.DecisionEngine; using NzbDrone.Core.Repository; using NzbDrone.Core.Repository.Quality; using NzbDrone.Core.Test.Framework; -using NzbDrone.Test.Common.AutoMoq; -namespace NzbDrone.Core.Test.ProviderTests.InventoryProviderTests +namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests { [TestFixture] // ReSharper disable InconsistentNaming - public class IsAcceptableSizeTestFixture : CoreTest + public class AcceptableSizeSpecificationFixture : CoreTest { private EpisodeParseResult parseResultMulti; private EpisodeParseResult parseResultSingle; @@ -84,7 +84,7 @@ namespace NzbDrone.Core.Test.ProviderTests.InventoryProviderTests .Returns(false); //Act - bool result = Mocker.Resolve().IsAcceptableSize(parseResultSingle); + bool result = Mocker.Resolve().IsSatisfiedBy(parseResultSingle); //Assert result.Should().BeTrue(); @@ -105,7 +105,7 @@ namespace NzbDrone.Core.Test.ProviderTests.InventoryProviderTests .Returns(false); //Act - bool result = Mocker.Resolve().IsAcceptableSize(parseResultSingle); + bool result = Mocker.Resolve().IsSatisfiedBy(parseResultSingle); //Assert result.Should().BeTrue(); @@ -126,7 +126,7 @@ namespace NzbDrone.Core.Test.ProviderTests.InventoryProviderTests .Returns(false); //Act - bool result = Mocker.Resolve().IsAcceptableSize(parseResultSingle); + bool result = Mocker.Resolve().IsSatisfiedBy(parseResultSingle); //Assert result.Should().BeFalse(); @@ -147,7 +147,7 @@ namespace NzbDrone.Core.Test.ProviderTests.InventoryProviderTests .Returns(false); //Act - bool result = Mocker.Resolve().IsAcceptableSize(parseResultSingle); + bool result = Mocker.Resolve().IsSatisfiedBy(parseResultSingle); //Assert result.Should().BeFalse(); @@ -168,7 +168,7 @@ namespace NzbDrone.Core.Test.ProviderTests.InventoryProviderTests .Returns(false); //Act - bool result = Mocker.Resolve().IsAcceptableSize(parseResultMulti); + bool result = Mocker.Resolve().IsSatisfiedBy(parseResultMulti); //Assert result.Should().BeTrue(); @@ -189,7 +189,7 @@ namespace NzbDrone.Core.Test.ProviderTests.InventoryProviderTests .Returns(false); //Act - bool result = Mocker.Resolve().IsAcceptableSize(parseResultMulti); + bool result = Mocker.Resolve().IsSatisfiedBy(parseResultMulti); //Assert result.Should().BeTrue(); @@ -210,7 +210,7 @@ namespace NzbDrone.Core.Test.ProviderTests.InventoryProviderTests .Returns(false); //Act - bool result = Mocker.Resolve().IsAcceptableSize(parseResultMulti); + bool result = Mocker.Resolve().IsSatisfiedBy(parseResultMulti); //Assert result.Should().BeFalse(); @@ -231,7 +231,7 @@ namespace NzbDrone.Core.Test.ProviderTests.InventoryProviderTests .Returns(false); //Act - bool result = Mocker.Resolve().IsAcceptableSize(parseResultMulti); + bool result = Mocker.Resolve().IsSatisfiedBy(parseResultMulti); //Assert result.Should().BeFalse(); @@ -252,7 +252,7 @@ namespace NzbDrone.Core.Test.ProviderTests.InventoryProviderTests .Returns(true); //Act - bool result = Mocker.Resolve().IsAcceptableSize(parseResultSingle); + bool result = Mocker.Resolve().IsSatisfiedBy(parseResultSingle); //Assert result.Should().BeTrue(); @@ -273,7 +273,7 @@ namespace NzbDrone.Core.Test.ProviderTests.InventoryProviderTests .Returns(true); //Act - bool result = Mocker.Resolve().IsAcceptableSize(parseResultSingle); + bool result = Mocker.Resolve().IsSatisfiedBy(parseResultSingle); //Assert result.Should().BeTrue(); @@ -294,7 +294,7 @@ namespace NzbDrone.Core.Test.ProviderTests.InventoryProviderTests .Returns(true); //Act - bool result = Mocker.Resolve().IsAcceptableSize(parseResultSingle); + bool result = Mocker.Resolve().IsSatisfiedBy(parseResultSingle); //Assert result.Should().BeFalse(); @@ -315,7 +315,7 @@ namespace NzbDrone.Core.Test.ProviderTests.InventoryProviderTests .Returns(true); //Act - bool result = Mocker.Resolve().IsAcceptableSize(parseResultSingle); + bool result = Mocker.Resolve().IsSatisfiedBy(parseResultSingle); //Assert result.Should().BeFalse(); @@ -337,7 +337,7 @@ namespace NzbDrone.Core.Test.ProviderTests.InventoryProviderTests .Returns(true); //Act - bool result = Mocker.Resolve().IsAcceptableSize(parseResultSingle); + bool result = Mocker.Resolve().IsSatisfiedBy(parseResultSingle); //Assert result.Should().BeTrue(); @@ -359,7 +359,7 @@ namespace NzbDrone.Core.Test.ProviderTests.InventoryProviderTests .Returns(true); //Act - bool result = Mocker.Resolve().IsAcceptableSize(parseResultSingle); + bool result = Mocker.Resolve().IsSatisfiedBy(parseResultSingle); //Assert result.Should().BeTrue(); @@ -382,7 +382,7 @@ namespace NzbDrone.Core.Test.ProviderTests.InventoryProviderTests .Returns(true); //Act - bool result = Mocker.Resolve().IsAcceptableSize(parseResultSingle); + bool result = Mocker.Resolve().IsSatisfiedBy(parseResultSingle); //Assert result.Should().BeTrue(); diff --git a/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/AllowedDownloadSpecificationFixture.cs b/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/AllowedDownloadSpecificationFixture.cs new file mode 100644 index 000000000..4b95725d9 --- /dev/null +++ b/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/AllowedDownloadSpecificationFixture.cs @@ -0,0 +1,121 @@ +// ReSharper disable RedundantUsingDirective + +using System.Linq; +using System; +using System.Collections.Generic; +using FizzWare.NBuilder; +using FluentAssertions; +using Moq; +using NUnit.Framework; +using NzbDrone.Core.Model; +using NzbDrone.Core.Providers; +using NzbDrone.Core.Providers.DecisionEngine; +using NzbDrone.Core.Repository; +using NzbDrone.Core.Repository.Quality; +using NzbDrone.Core.Test.Framework; + +namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests +{ + [TestFixture] + // ReSharper disable InconsistentNaming + public class AllowedDownloadSpecificationFixture : CoreTest + { + private AllowedDownloadSpecification spec; + private EpisodeParseResult parseResult; + + [SetUp] + public void Setup() + { + spec = Mocker.Resolve(); + parseResult = new EpisodeParseResult(); + + Mocker.GetMock() + .Setup(c => c.IsSatisfiedBy(It.IsAny())) + .Returns(true); + + Mocker.GetMock() + .Setup(c => c.IsSatisfiedBy(It.IsAny())) + .Returns(true); + + Mocker.GetMock() + .Setup(c => c.IsSatisfiedBy(It.IsAny())) + .Returns(true); + + Mocker.GetMock() + .Setup(c => c.IsSatisfiedBy(It.IsAny())) + .Returns(false); + } + + private void WithProfileNotAllowed() + { + Mocker.GetMock() + .Setup(c => c.IsSatisfiedBy(It.IsAny())) + .Returns(false); + } + + private void WithNotAcceptableSize() + { + Mocker.GetMock() + .Setup(c => c.IsSatisfiedBy(It.IsAny())) + .Returns(false); + } + + private void WithNoDiskUpgrade() + { + Mocker.GetMock() + .Setup(c => c.IsSatisfiedBy(It.IsAny())) + .Returns(false); + } + + private void WithEpisodeAlreadyInQueue() + { + Mocker.GetMock() + .Setup(c => c.IsSatisfiedBy(It.IsAny())) + .Returns(true); + } + + [Test] + public void should_be_allowed_if_all_conditions_are_met() + { + spec.IsSatisfiedBy(parseResult).Should().BeTrue(); + } + + [Test] + public void should_not_be_allowed_if_profile_is_not_allowed() + { + WithProfileNotAllowed(); + spec.IsSatisfiedBy(parseResult).Should().BeFalse(); + } + + [Test] + public void should_not_be_allowed_if_size_is_not_allowed() + { + WithNotAcceptableSize(); + spec.IsSatisfiedBy(parseResult).Should().BeFalse(); + } + + [Test] + public void should_not_be_allowed_if_disk_is_not_upgrade() + { + WithNoDiskUpgrade(); + spec.IsSatisfiedBy(parseResult).Should().BeFalse(); + } + + [Test] + public void should_not_be_allowed_if_episode_is_already_in_queue() + { + WithEpisodeAlreadyInQueue(); + spec.IsSatisfiedBy(parseResult).Should().BeFalse(); + } + + [Test] + public void should_not_be_allowed_if_none_of_conditions_are_met() + { + WithNoDiskUpgrade(); + WithNotAcceptableSize(); + WithProfileNotAllowed(); + + spec.IsSatisfiedBy(parseResult).Should().BeFalse(); + } + } +} \ No newline at end of file diff --git a/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/MonitoredEpisodeSpecificationFixture.cs b/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/MonitoredEpisodeSpecificationFixture.cs new file mode 100644 index 000000000..7b6f624ab --- /dev/null +++ b/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/MonitoredEpisodeSpecificationFixture.cs @@ -0,0 +1,138 @@ +// ReSharper disable RedundantUsingDirective + +using System.Linq; +using System; +using System.Collections.Generic; +using FizzWare.NBuilder; +using FluentAssertions; +using Moq; +using NUnit.Framework; +using NzbDrone.Core.Model; +using NzbDrone.Core.Providers; +using NzbDrone.Core.Providers.DecisionEngine; +using NzbDrone.Core.Repository; +using NzbDrone.Core.Test.Framework; + +namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests +{ + [TestFixture] + // ReSharper disable InconsistentNaming + public class MonitoredEpisodeSpecificationFixture : CoreTest + { + private MonitoredEpisodeSpecification monitoredEpisodeSpecification; + + private EpisodeParseResult parseResultMulti; + private EpisodeParseResult parseResultSingle; + private Series fakeSeries; + private Episode firstEpisode; + private Episode secondEpisode; + + [SetUp] + public void Setup() + { + monitoredEpisodeSpecification = Mocker.Resolve(); + + fakeSeries = Builder.CreateNew() + .With(c => c.Monitored = true) + .Build(); + + parseResultMulti = new EpisodeParseResult + { + SeriesTitle = "Title", + Series = fakeSeries, + EpisodeNumbers = new List { 3, 4 }, + SeasonNumber = 12, + }; + + parseResultSingle = new EpisodeParseResult + { + SeriesTitle = "Title", + Series = fakeSeries, + EpisodeNumbers = new List { 3 }, + SeasonNumber = 12, + }; + + firstEpisode = new Episode { Ignored = false }; + secondEpisode = new Episode { Ignored = false }; + + var singleEpisodeList = new List { firstEpisode }; + var doubleEpisodeList = new List { firstEpisode, secondEpisode }; + + Mocker.GetMock().Setup(c => c.GetEpisodesByParseResult(parseResultSingle)).Returns(singleEpisodeList); + Mocker.GetMock().Setup(c => c.GetEpisodesByParseResult(parseResultMulti)).Returns(doubleEpisodeList); + + Mocker.GetMock().Setup(c => c.FindSeries(parseResultMulti.CleanTitle)).Returns(fakeSeries); + Mocker.GetMock().Setup(c => c.FindSeries(parseResultSingle.CleanTitle)).Returns(fakeSeries); + } + + private void WithFirstEpisodeIgnored() + { + firstEpisode.Ignored = true; + } + + private void WithSecondEpisodeIgnored() + { + secondEpisode.Ignored = true; + } + + [Test] + public void setup_should_return_monitored_episode_should_return_true() + { + monitoredEpisodeSpecification.IsSatisfiedBy(parseResultSingle).Should().BeTrue(); + monitoredEpisodeSpecification.IsSatisfiedBy(parseResultMulti).Should().BeTrue(); + } + + + [Test] + public void not_monitored_series_should_be_skipped() + { + fakeSeries.Monitored = false; + monitoredEpisodeSpecification.IsSatisfiedBy(parseResultMulti).Should().BeFalse(); + } + + + [Test] + public void not_in_db_should_be_skipped() + { + Mocker.GetMock() + .Setup(p => p.FindSeries(It.IsAny())) + .Returns(null); + + monitoredEpisodeSpecification.IsSatisfiedBy(parseResultMulti).Should().BeFalse(); + } + + + [Test] + public void only_episode_ignored_should_return_false() + { + WithFirstEpisodeIgnored(); + monitoredEpisodeSpecification.IsSatisfiedBy(parseResultSingle).Should().BeFalse(); + } + + + [Test] + public void both_episodes_ignored_should_return_false() + { + WithFirstEpisodeIgnored(); + WithSecondEpisodeIgnored(); + monitoredEpisodeSpecification.IsSatisfiedBy(parseResultMulti).Should().BeFalse(); + } + + + [Test] + public void only_first_episode_ignored_should_return_monitored() + { + WithFirstEpisodeIgnored(); + monitoredEpisodeSpecification.IsSatisfiedBy(parseResultMulti).Should().BeTrue(); + } + + + [Test] + public void only_second_episode_ignored_should_return_monitored() + { + WithSecondEpisodeIgnored(); + monitoredEpisodeSpecification.IsSatisfiedBy(parseResultMulti).Should().BeTrue(); + } + + } +} \ No newline at end of file diff --git a/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/QualityAllowedByProfileSpecificationFixtrue.cs b/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/QualityAllowedByProfileSpecificationFixtrue.cs new file mode 100644 index 000000000..86158b9c1 --- /dev/null +++ b/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/QualityAllowedByProfileSpecificationFixtrue.cs @@ -0,0 +1,69 @@ +// ReSharper disable RedundantUsingDirective + +using System.Collections.Generic; +using System.Linq; +using FizzWare.NBuilder; +using FluentAssertions; +using NUnit.Framework; +using NzbDrone.Core.Model; +using NzbDrone.Core.Providers.DecisionEngine; +using NzbDrone.Core.Repository; +using NzbDrone.Core.Repository.Quality; +using NzbDrone.Core.Test.Framework; + +namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests +{ + [TestFixture] + // ReSharper disable InconsistentNaming + public class QualityAllowedByProfileSpecificationFixtrue : CoreTest + { + private QualityAllowedByProfileSpecification _qualityAllowedByProfile; + + + private EpisodeParseResult parseResult; + + + [SetUp] + public void Setup() + { + _qualityAllowedByProfile = Mocker.Resolve(); + + var fakeSeries = Builder.CreateNew() + .With(c => c.QualityProfile = new QualityProfile { Cutoff = QualityTypes.Bluray1080p }) + .Build(); + + parseResult = new EpisodeParseResult + { + Series = fakeSeries, + Quality = new Quality(QualityTypes.DVD, true), + EpisodeNumbers = new List { 3 }, + SeasonNumber = 12, + }; + } + + + + [TestCase(QualityTypes.DVD)] + [TestCase(QualityTypes.HDTV)] + [TestCase(QualityTypes.Bluray1080p)] + public void should_allow_if_quality_is_defined_in_profile(QualityTypes qualityType) + { + parseResult.Quality.QualityType = qualityType; + parseResult.Series.QualityProfile.Allowed = new List { QualityTypes.DVD, QualityTypes.HDTV, QualityTypes.Bluray1080p }; + + _qualityAllowedByProfile.IsSatisfiedBy(parseResult).Should().BeTrue(); + } + + [TestCase(QualityTypes.SDTV)] + [TestCase(QualityTypes.WEBDL)] + [TestCase(QualityTypes.Bluray720p)] + public void should_not_allow_if_quality_is_not_defined_in_profile(QualityTypes qualityType) + { + parseResult.Quality.QualityType = qualityType; + parseResult.Series.QualityProfile.Allowed = new List { QualityTypes.DVD, QualityTypes.HDTV, QualityTypes.Bluray1080p }; + + _qualityAllowedByProfile.IsSatisfiedBy(parseResult).Should().BeFalse(); + } + + } +} \ No newline at end of file diff --git a/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/QualityUpgradeSpecificationFixture.cs b/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/QualityUpgradeSpecificationFixture.cs new file mode 100644 index 000000000..83f6c1ea0 --- /dev/null +++ b/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/QualityUpgradeSpecificationFixture.cs @@ -0,0 +1,30 @@ +// ReSharper disable RedundantUsingDirective + +using System.Linq; +using NUnit.Framework; +using NzbDrone.Core.Model; +using NzbDrone.Core.Providers.DecisionEngine; +using NzbDrone.Core.Repository.Quality; +using NzbDrone.Core.Test.Framework; + +namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests +{ + [TestFixture] + // ReSharper disable InconsistentNaming + public class QualityUpgradeSpecificationFixture : CoreTest + { + + [TestCase(QualityTypes.SDTV, false, QualityTypes.SDTV, true, QualityTypes.SDTV, Result = true)] + [TestCase(QualityTypes.WEBDL, false, QualityTypes.WEBDL, true, QualityTypes.WEBDL, Result = true)] + [TestCase(QualityTypes.SDTV, false, QualityTypes.SDTV, false, QualityTypes.SDTV, Result = false)] + [TestCase(QualityTypes.SDTV, false, QualityTypes.DVD, true, QualityTypes.SDTV, Result = false)] + [TestCase(QualityTypes.WEBDL, false, QualityTypes.HDTV, true, QualityTypes.Bluray720p, Result = false)] + [TestCase(QualityTypes.WEBDL, false, QualityTypes.HDTV, true, QualityTypes.WEBDL, Result = false)] + [TestCase(QualityTypes.WEBDL, false, QualityTypes.WEBDL, false, QualityTypes.WEBDL, Result = false)] + [TestCase(QualityTypes.SDTV, false, QualityTypes.SDTV, true, QualityTypes.SDTV, Result = true)] + public bool IsUpgradeTest(QualityTypes current, bool currentProper, QualityTypes newQuality, bool newProper, QualityTypes cutoff) + { + return new QualityUpgradeSpecification().IsSatisfiedBy(new Quality(current, currentProper), new Quality(newQuality, newProper), cutoff); + } + } +} \ No newline at end of file diff --git a/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/UpgradeDiskSpecificationFixtrue.cs b/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/UpgradeDiskSpecificationFixtrue.cs new file mode 100644 index 000000000..bd8a2a39f --- /dev/null +++ b/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/UpgradeDiskSpecificationFixtrue.cs @@ -0,0 +1,118 @@ +// ReSharper disable RedundantUsingDirective + +using System.Collections.Generic; +using System.Linq; +using FizzWare.NBuilder; +using FluentAssertions; +using NUnit.Framework; +using NzbDrone.Core.Model; +using NzbDrone.Core.Providers; +using NzbDrone.Core.Providers.DecisionEngine; +using NzbDrone.Core.Repository; +using NzbDrone.Core.Repository.Quality; +using NzbDrone.Core.Test.Framework; + +namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests +{ + [TestFixture] + // ReSharper disable InconsistentNaming + public class UpgradeDiskSpecificationFixtrue : CoreTest + { + private UpgradeDiskSpecification _upgradeDisk; + + private EpisodeParseResult parseResultMulti; + private EpisodeParseResult parseResultSingle; + private EpisodeFile firstFile; + private EpisodeFile secondFile; + + [SetUp] + public void Setup() + { + Mocker.Resolve(); + _upgradeDisk = Mocker.Resolve(); + + var fakeSeries = Builder.CreateNew() + .With(c => c.QualityProfile = new QualityProfile { Cutoff = QualityTypes.Bluray1080p }) + .Build(); + + parseResultMulti = new EpisodeParseResult + { + Series = fakeSeries, + Quality = new Quality(QualityTypes.DVD, true), + EpisodeNumbers = new List { 3, 4 }, + SeasonNumber = 12, + }; + + parseResultSingle = new EpisodeParseResult + { + Series = fakeSeries, + Quality = new Quality(QualityTypes.DVD, true), + EpisodeNumbers = new List { 3 }, + SeasonNumber = 12, + }; + + + firstFile = new EpisodeFile { Quality = QualityTypes.Bluray1080p, Proper = true }; + secondFile = new EpisodeFile { Quality = QualityTypes.Bluray1080p, Proper = true }; + + var singleEpisodeList = new List { new Episode { EpisodeFile = firstFile }, new Episode { EpisodeFile = null } }; + var doubleEpisodeList = new List { new Episode { EpisodeFile = firstFile }, new Episode { EpisodeFile = secondFile }, new Episode { EpisodeFile = null } }; + + Mocker.GetMock().Setup(c => c.GetEpisodesByParseResult(parseResultSingle)).Returns(singleEpisodeList); + Mocker.GetMock().Setup(c => c.GetEpisodesByParseResult(parseResultMulti)).Returns(doubleEpisodeList); + } + + private void WithFirstFileUpgradable() + { + firstFile.Quality = QualityTypes.SDTV; + } + + private void WithSecondFileUpgradable() + { + secondFile.Quality = QualityTypes.SDTV; + } + + [Test] + public void should_return_false_if_single_episode_doesnt_exist_on_disk() + { + Mocker.GetMock().Setup(c => c.GetEpisodesByParseResult(parseResultSingle)).Returns(new List()); + + _upgradeDisk.IsSatisfiedBy(parseResultSingle).Should().BeTrue(); + } + + [Test] + public void should_be_upgradable_if_only_episode_is_upgradable() + { + WithFirstFileUpgradable(); + _upgradeDisk.IsSatisfiedBy(parseResultSingle).Should().BeTrue(); + } + + [Test] + public void should_be_upgradable_if_both_episodes_are_upgradable() + { + WithFirstFileUpgradable(); + WithSecondFileUpgradable(); + _upgradeDisk.IsSatisfiedBy(parseResultMulti).Should().BeTrue(); + } + + [Test] + public void should_be_not_upgradable_if_both_episodes_are_not_upgradable() + { + _upgradeDisk.IsSatisfiedBy(parseResultMulti).Should().BeFalse(); + } + + [Test] + public void should_be_not_upgradable_if_only_first_episodes_is_upgradable() + { + WithFirstFileUpgradable(); + _upgradeDisk.IsSatisfiedBy(parseResultMulti).Should().BeFalse(); + } + + [Test] + public void should_be_not_upgradable_if_only_second_episodes_is_upgradable() + { + WithSecondFileUpgradable(); + _upgradeDisk.IsSatisfiedBy(parseResultMulti).Should().BeFalse(); + } + } +} \ No newline at end of file diff --git a/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/UpgradeHistorySpecificationFixtrue.cs b/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/UpgradeHistorySpecificationFixtrue.cs new file mode 100644 index 000000000..85e0ff0fe --- /dev/null +++ b/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/UpgradeHistorySpecificationFixtrue.cs @@ -0,0 +1,118 @@ +// ReSharper disable RedundantUsingDirective + +using System.Collections.Generic; +using System.Linq; +using FizzWare.NBuilder; +using FluentAssertions; +using NUnit.Framework; +using NzbDrone.Core.Model; +using NzbDrone.Core.Providers; +using NzbDrone.Core.Providers.DecisionEngine; +using NzbDrone.Core.Repository; +using NzbDrone.Core.Repository.Quality; +using NzbDrone.Core.Test.Framework; + +namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests +{ + [TestFixture] + // ReSharper disable InconsistentNaming + public class UpgradeHistorySpecificationFixtrue : CoreTest + { + private UpgradeHistorySpecification _upgradeHistory; + + private EpisodeParseResult parseResultMulti; + private EpisodeParseResult parseResultSingle; + private Quality firstQuality; + private Quality secondQuality; + + [SetUp] + public void Setup() + { + Mocker.Resolve(); + _upgradeHistory = Mocker.Resolve(); + + var fakeSeries = Builder.CreateNew() + .With(c => c.QualityProfile = new QualityProfile { Cutoff = QualityTypes.Bluray1080p }) + .Build(); + + parseResultMulti = new EpisodeParseResult + { + Series = fakeSeries, + Quality = new Quality(QualityTypes.DVD, true), + EpisodeNumbers = new List { 3, 4 }, + SeasonNumber = 12, + }; + + parseResultSingle = new EpisodeParseResult + { + Series = fakeSeries, + Quality = new Quality(QualityTypes.DVD, true), + EpisodeNumbers = new List { 3 }, + SeasonNumber = 12, + }; + + firstQuality = new Quality(QualityTypes.Bluray1080p, true); + secondQuality = new Quality(QualityTypes.Bluray1080p, true); + + var singleEpisodeList = new List { new Episode { SeasonNumber = 12, EpisodeNumber = 3 } }; + var doubleEpisodeList = new List { + new Episode { SeasonNumber = 12, EpisodeNumber = 3 }, + new Episode { SeasonNumber = 12, EpisodeNumber = 4 }, + new Episode { SeasonNumber = 12, EpisodeNumber = 5 } + }; + + Mocker.GetMock().Setup(c => c.GetEpisodesByParseResult(parseResultSingle)).Returns(singleEpisodeList); + Mocker.GetMock().Setup(c => c.GetEpisodesByParseResult(parseResultMulti)).Returns(doubleEpisodeList); + + Mocker.GetMock().Setup(c => c.GetBestQualityInHistory(fakeSeries.SeriesId, 12, 3)).Returns(firstQuality); + Mocker.GetMock().Setup(c => c.GetBestQualityInHistory(fakeSeries.SeriesId, 12, 4)).Returns(secondQuality); + Mocker.GetMock().Setup(c => c.GetBestQualityInHistory(fakeSeries.SeriesId, 12, 5)).Returns(null); + } + + private void WithFirstReportUpgradable() + { + firstQuality.QualityType = QualityTypes.SDTV; + } + + private void WithSecondReportUpgradable() + { + secondQuality.QualityType = QualityTypes.SDTV; + } + + + [Test] + public void should_be_upgradable_if_only_episode_is_upgradable() + { + WithFirstReportUpgradable(); + _upgradeHistory.IsSatisfiedBy(parseResultSingle).Should().BeTrue(); + } + + [Test] + public void should_be_upgradable_if_both_episodes_are_upgradable() + { + WithFirstReportUpgradable(); + WithSecondReportUpgradable(); + _upgradeHistory.IsSatisfiedBy(parseResultMulti).Should().BeTrue(); + } + + [Test] + public void should_not_be_upgradable_if_both_episodes_are_not_upgradable() + { + _upgradeHistory.IsSatisfiedBy(parseResultMulti).Should().BeFalse(); + } + + [Test] + public void should_be_not_upgradable_if_only_first_episodes_is_upgradable() + { + WithFirstReportUpgradable(); + _upgradeHistory.IsSatisfiedBy(parseResultMulti).Should().BeFalse(); + } + + [Test] + public void should_be_not_upgradable_if_only_second_episodes_is_upgradable() + { + WithSecondReportUpgradable(); + _upgradeHistory.IsSatisfiedBy(parseResultMulti).Should().BeFalse(); + } + } +} \ No newline at end of file diff --git a/NzbDrone.Core.Test/ProviderTests/InventoryProviderTests/IsUpgradePossibleFixture.cs b/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/UpgradePossibleSpecificationFixture.cs similarity index 81% rename from NzbDrone.Core.Test/ProviderTests/InventoryProviderTests/IsUpgradePossibleFixture.cs rename to NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/UpgradePossibleSpecificationFixture.cs index 61421fb0e..b6e758749 100644 --- a/NzbDrone.Core.Test/ProviderTests/InventoryProviderTests/IsUpgradePossibleFixture.cs +++ b/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/UpgradePossibleSpecificationFixture.cs @@ -1,24 +1,21 @@ // ReSharper disable RedundantUsingDirective -using System; -using System.Collections.Generic; - +using System.Linq; using FizzWare.NBuilder; using FluentAssertions; using Moq; using NUnit.Framework; -using NzbDrone.Core.Model; using NzbDrone.Core.Providers; +using NzbDrone.Core.Providers.DecisionEngine; using NzbDrone.Core.Repository; using NzbDrone.Core.Repository.Quality; using NzbDrone.Core.Test.Framework; -using NzbDrone.Test.Common.AutoMoq; -namespace NzbDrone.Core.Test.ProviderTests.InventoryProviderTests +namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests { [TestFixture] // ReSharper disable InconsistentNaming - public class IsUpgradePossibleFixture : CoreTest + public class UpgradePossibleSpecificationFixture : CoreTest { private void WithWebdlCutoff() { @@ -57,7 +54,7 @@ namespace NzbDrone.Core.Test.ProviderTests.InventoryProviderTests .Build(); //Act - bool result = Mocker.Resolve().IsUpgradePossible(episode); + bool result = Mocker.Resolve().IsSatisfiedBy(episode); //Assert result.Should().BeTrue(); @@ -69,7 +66,7 @@ namespace NzbDrone.Core.Test.ProviderTests.InventoryProviderTests WithWebdlCutoff(); //Act - bool result = Mocker.Resolve().IsUpgradePossible(_episode); + bool result = Mocker.Resolve().IsSatisfiedBy(_episode); //Assert result.Should().BeTrue(); @@ -83,7 +80,7 @@ namespace NzbDrone.Core.Test.ProviderTests.InventoryProviderTests _episodeFile.Quality = QualityTypes.WEBDL; //Act - bool result = Mocker.Resolve().IsUpgradePossible(_episode); + bool result = Mocker.Resolve().IsSatisfiedBy(_episode); //Assert result.Should().BeFalse(); @@ -97,7 +94,7 @@ namespace NzbDrone.Core.Test.ProviderTests.InventoryProviderTests _episodeFile.Quality = QualityTypes.Bluray720p; //Act - bool result = Mocker.Resolve().IsUpgradePossible(_episode); + bool result = Mocker.Resolve().IsSatisfiedBy(_episode); //Assert result.Should().BeFalse(); diff --git a/NzbDrone.Core.Test/ProviderTests/DiskScanProviderTest_ImportFile.cs b/NzbDrone.Core.Test/ProviderTests/DiskScanProviderTest_ImportFile.cs index c16b32051..5460adf7d 100644 --- a/NzbDrone.Core.Test/ProviderTests/DiskScanProviderTest_ImportFile.cs +++ b/NzbDrone.Core.Test/ProviderTests/DiskScanProviderTest_ImportFile.cs @@ -39,7 +39,7 @@ namespace NzbDrone.Core.Test.ProviderTests .Returns(false); Mocker.GetMock() - .Setup(e => e.GetEpisodesByParseResult(It.IsAny(), false)).Returns(new List { fakeEpisode }); + .Setup(e => e.GetEpisodesByParseResult(It.IsAny())).Returns(new List { fakeEpisode }); //Act var result = Mocker.Resolve().ImportFile(fakeSeries, newFile); @@ -73,7 +73,7 @@ namespace NzbDrone.Core.Test.ProviderTests Mocker.GetMock() - .Setup(e => e.GetEpisodesByParseResult(It.IsAny(), false)).Returns(new List { fakeEpisode }); + .Setup(e => e.GetEpisodesByParseResult(It.IsAny())).Returns(new List { fakeEpisode }); //Act var result = Mocker.Resolve().ImportFile(fakeSeries, newFile); @@ -106,7 +106,7 @@ namespace NzbDrone.Core.Test.ProviderTests .Returns(false); Mocker.GetMock() - .Setup(e => e.GetEpisodesByParseResult(It.IsAny(), false)).Returns(new List { fakeEpisode }); + .Setup(e => e.GetEpisodesByParseResult(It.IsAny())).Returns(new List { fakeEpisode }); //Act var result = Mocker.Resolve().ImportFile(fakeSeries, fileName); @@ -202,7 +202,7 @@ namespace NzbDrone.Core.Test.ProviderTests .Setup(e => e.GetSize(fileName)).Returns(90000000000); Mocker.GetMock() - .Setup(c => c.GetEpisodesByParseResult(It.IsAny(), false)) + .Setup(c => c.GetEpisodesByParseResult(It.IsAny())) .Returns(new List()); @@ -237,7 +237,7 @@ namespace NzbDrone.Core.Test.ProviderTests .Returns(false); Mocker.GetMock() - .Setup(e => e.GetEpisodesByParseResult(It.IsAny(), false)).Returns(new List { fakeEpisode }); + .Setup(e => e.GetEpisodesByParseResult(It.IsAny())).Returns(new List { fakeEpisode }); //Act var result = Mocker.Resolve().ImportFile(fakeSeries, fileName); @@ -273,7 +273,7 @@ namespace NzbDrone.Core.Test.ProviderTests .Returns(false); Mocker.GetMock() - .Setup(e => e.GetEpisodesByParseResult(It.IsAny(), false)).Returns(fakeEpisodes); + .Setup(e => e.GetEpisodesByParseResult(It.IsAny())).Returns(fakeEpisodes); //Act var result = Mocker.Resolve().ImportFile(fakeSeries, fileName); @@ -308,7 +308,7 @@ namespace NzbDrone.Core.Test.ProviderTests .Returns(false); Mocker.GetMock() - .Setup(e => e.GetEpisodesByParseResult(It.IsAny(), false)).Returns(fakeEpisodes); + .Setup(e => e.GetEpisodesByParseResult(It.IsAny())).Returns(fakeEpisodes); //Act var result = Mocker.Resolve().ImportFile(fakeSeries, fileName); @@ -349,7 +349,7 @@ namespace NzbDrone.Core.Test.ProviderTests .Returns(false); Mocker.GetMock() - .Setup(e => e.GetEpisodesByParseResult(It.IsAny(), false)).Returns(new List { fakeEpisode1, fakeEpisode2 }); + .Setup(e => e.GetEpisodesByParseResult(It.IsAny())).Returns(new List { fakeEpisode1, fakeEpisode2 }); //Act var result = Mocker.Resolve().ImportFile(fakeSeries, fileName); @@ -383,7 +383,7 @@ namespace NzbDrone.Core.Test.ProviderTests .Returns(false); Mocker.GetMock() - .Setup(e => e.GetEpisodesByParseResult(It.IsAny(), false)).Returns(new List { fakeEpisode}); + .Setup(e => e.GetEpisodesByParseResult(It.IsAny())).Returns(new List { fakeEpisode}); //Act var result = Mocker.Resolve().ImportFile(fakeSeries, fileName); @@ -403,7 +403,7 @@ namespace NzbDrone.Core.Test.ProviderTests Mocker.GetMock().Verify(p => p.Add(It.IsAny()), Times.Once()); //Get the count of episodes linked - var count = Mocker.GetMock().Object.GetEpisodesByParseResult(null, false).Count; + var count = Mocker.GetMock().Object.GetEpisodesByParseResult(null).Count; Mocker.GetMock().Verify(p => p.UpdateEpisode(It.Is(e => e.EpisodeFileId == result.EpisodeFileId)), Times.Exactly(count)); } diff --git a/NzbDrone.Core.Test/ProviderTests/DownloadClientTests/BlackholeProviderFixture.cs b/NzbDrone.Core.Test/ProviderTests/DownloadClientTests/BlackholeProviderFixture.cs new file mode 100644 index 000000000..0f8a5be95 --- /dev/null +++ b/NzbDrone.Core.Test/ProviderTests/DownloadClientTests/BlackholeProviderFixture.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Text; +using FluentAssertions; +using Moq; +using NUnit.Framework; +using NzbDrone.Common; +using NzbDrone.Core.Providers.Core; +using NzbDrone.Core.Providers.DownloadClients; +using NzbDrone.Core.Test.Framework; +using NzbDrone.Test.Common; + +namespace NzbDrone.Core.Test.ProviderTests.DownloadClientTests +{ + [TestFixture] + public class BlackholeProviderFixture : CoreTest + { + private const string nzbUrl = "http://www.nzbs.com/url"; + private const string title = "some_nzb_title"; + private const string blackHoleFolder = @"d:\nzb\blackhole\"; + private const string nzbPath = @"d:\nzb\blackhole\some_nzb_title.nzb"; + + [SetUp] + public void Setup() + { + Mocker.GetMock().SetupGet(c => c.BlackholeDirectory).Returns(blackHoleFolder); + } + + + private void WithExistingFile() + { + Mocker.GetMock().Setup(c => c.FileExists(nzbPath)).Returns(true); + } + + private void WithFailedDownload() + { + Mocker.GetMock().Setup(c => c.DownloadFile(It.IsAny(), It.IsAny())).Throws(new WebException()); + } + + [Test] + public void DownloadNzb_should_download_file_if_it_doesnt_exist() + { + Mocker.Resolve().DownloadNzb(nzbUrl, title).Should().BeTrue(); + + Mocker.GetMock().Verify(c => c.DownloadFile(nzbUrl, nzbPath),Times.Once()); + } + + [Test] + public void DownloadNzb_not_download_file_if_it_doesn_exist() + { + WithExistingFile(); + + Mocker.Resolve().DownloadNzb(nzbUrl, title).Should().BeTrue(); + + Mocker.GetMock().Verify(c => c.DownloadFile(It.IsAny(), It.IsAny()), Times.Never()); + } + + [Test] + public void should_return_false_on_failed_download() + { + WithFailedDownload(); + + Mocker.Resolve().DownloadNzb(nzbUrl, title).Should().BeFalse(); + + ExceptionVerification.ExpectedWarns(1); + } + + + } +} diff --git a/NzbDrone.Core.Test/ProviderTests/SabProviderTests/QueueFixture.cs b/NzbDrone.Core.Test/ProviderTests/DownloadClientTests/SabProviderTests/QueueFixture.cs similarity index 98% rename from NzbDrone.Core.Test/ProviderTests/SabProviderTests/QueueFixture.cs rename to NzbDrone.Core.Test/ProviderTests/DownloadClientTests/SabProviderTests/QueueFixture.cs index 1d238d99d..799622b0a 100644 --- a/NzbDrone.Core.Test/ProviderTests/SabProviderTests/QueueFixture.cs +++ b/NzbDrone.Core.Test/ProviderTests/DownloadClientTests/SabProviderTests/QueueFixture.cs @@ -4,19 +4,18 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; -using FizzWare.NBuilder; using FluentAssertions; using Moq; using NUnit.Framework; using NzbDrone.Core.Model; -using NzbDrone.Core.Providers; using NzbDrone.Core.Providers.Core; +using NzbDrone.Core.Providers.DownloadClients; using NzbDrone.Core.Repository; using NzbDrone.Core.Repository.Quality; using NzbDrone.Core.Test.Framework; using NzbDrone.Test.Common; -namespace NzbDrone.Core.Test.ProviderTests.SabProviderTests +namespace NzbDrone.Core.Test.ProviderTests.DownloadClientTests.SabProviderTests { [TestFixture] // ReSharper disable InconsistentNaming diff --git a/NzbDrone.Core.Test/ProviderTests/DownloadClientTests/SabProviderTests/SabProviderFixture.cs b/NzbDrone.Core.Test/ProviderTests/DownloadClientTests/SabProviderTests/SabProviderFixture.cs new file mode 100644 index 000000000..087c49711 --- /dev/null +++ b/NzbDrone.Core.Test/ProviderTests/DownloadClientTests/SabProviderTests/SabProviderFixture.cs @@ -0,0 +1,165 @@ +// ReSharper disable RedundantUsingDirective + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using FizzWare.NBuilder; +using FluentAssertions; +using Moq; +using NUnit.Framework; +using NzbDrone.Core.Model; +using NzbDrone.Core.Providers.Core; +using NzbDrone.Core.Providers.DownloadClients; +using NzbDrone.Core.Repository; +using NzbDrone.Core.Repository.Quality; +using NzbDrone.Core.Test.Framework; +using NzbDrone.Test.Common; + +namespace NzbDrone.Core.Test.ProviderTests.DownloadClientTests.SabProviderTests +{ + [TestFixture] + // ReSharper disable InconsistentNaming + public class SabProviderFixture : CoreTest + { + private const string url = "http://www.nzbclub.com/nzb_download.aspx?mid=1950232"; + private const string title = "My Series Name - 5x2-5x3 - My title [Bluray720p] [Proper]"; + + [SetUp] + public void Setup() + { + var fakeConfig = Mocker.GetMock(); + + fakeConfig.SetupGet(c => c.SabHost).Returns("192.168.5.55"); + fakeConfig.SetupGet(c => c.SabPort).Returns(2222); + fakeConfig.SetupGet(c => c.SabApiKey).Returns("5c770e3197e4fe763423ee7c392c25d1"); + fakeConfig.SetupGet(c => c.SabUsername).Returns("admin"); + fakeConfig.SetupGet(c => c.SabPassword).Returns("pass"); + fakeConfig.SetupGet(c => c.SabTvCategory).Returns("tv"); + } + + + private void WithFailResponse() + { + Mocker.GetMock() + .Setup(s => s.DownloadString(It.IsAny())).Returns("failed"); + } + + [Test] + public void add_url_should_format_request_properly() + { + Mocker.GetMock(MockBehavior.Strict) + .Setup(s => s.DownloadString("http://192.168.5.55:2222/api?mode=addurl&name=http://www.nzbclub.com/nzb_download.aspx?mid=1950232&priority=0&pp=3&cat=tv&nzbname=My+Series+Name+-+5x2-5x3+-+My+title+%5bBluray720p%5d+%5bProper%5d&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass")) + .Returns("ok"); + + //Act + Mocker.Resolve().DownloadNzb(url, title).Should().BeTrue(); + } + + + [Test] + public void newzbin_add_url_should_format_request_properly() + { + Mocker.GetMock(MockBehavior.Strict) + .Setup(s => s.DownloadString("http://192.168.5.55:2222/api?mode=addid&name=6107863&priority=0&pp=3&cat=tv&nzbname=My+Series+Name+-+5x2-5x3+-+My+title+%5bBluray720p%5d+%5bProper%5d&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass")) + .Returns("ok"); + + + //Act + bool result = Mocker.Resolve().DownloadNzb("http://www.newzbin.com/browse/post/6107863/nzb", title); + + //Assert + result.Should().BeTrue(); + } + + [Test] + public void add_by_url_should_detect_and_handle_sab_errors() + { + WithFailResponse(); + + //Act + Mocker.Resolve().DownloadNzb(url, title).Should().BeFalse(); + ExceptionVerification.ExpectedWarns(1); + } + + [Test] + public void should_be_able_to_get_categories_when_config_is_passed_in() + { + //Setup + const string host = "192.168.5.22"; + const int port = 1111; + const string apikey = "5c770e3197e4fe763423ee7c392c25d2"; + const string username = "admin2"; + const string password = "pass2"; + + + + Mocker.GetMock(MockBehavior.Strict) + .Setup(s => s.DownloadString("http://192.168.5.22:1111/api?mode=get_cats&output=json&apikey=5c770e3197e4fe763423ee7c392c25d2&ma_username=admin2&ma_password=pass2")) + .Returns(File.ReadAllText(@".\Files\Categories_json.txt")); + + //Act + var result = Mocker.Resolve().GetCategories(host, port, apikey, username, password); + + //Assert + result.Should().NotBeNull(); + result.categories.Should().NotBeEmpty(); + } + + [Test] + public void should_be_able_to_get_categories_using_config() + { + Mocker.GetMock(MockBehavior.Strict) + .Setup(s => s.DownloadString("http://192.168.5.55:2222/api?mode=get_cats&output=json&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass")) + .Returns(File.ReadAllText(@".\Files\Categories_json.txt")); + + //Act + var result = Mocker.Resolve().GetCategories(); + + //Assert + result.Should().NotBeNull(); + result.categories.Should().NotBeEmpty(); + } + + + [Test] + public void GetHistory_should_return_a_list_with_items_when_the_history_has_items() + { + Mocker.GetMock() + .Setup(s => s.DownloadString("http://192.168.5.55:2222/api?mode=history&output=json&start=0&limit=0&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass")) + .Returns(File.ReadAllText(@".\Files\History.txt")); + + //Act + var result = Mocker.Resolve().GetHistory(); + + //Assert + result.Should().HaveCount(1); + } + + [Test] + public void GetHistory_should_return_an_empty_list_when_the_queue_is_empty() + { + Mocker.GetMock() + .Setup(s => s.DownloadString("http://192.168.5.55:2222/api?mode=history&output=json&start=0&limit=0&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass")) + .Returns(File.ReadAllText(@".\Files\HistoryEmpty.txt")); + + //Act + var result = Mocker.Resolve().GetHistory(); + + //Assert + result.Should().BeEmpty(); + } + + [Test] + public void GetHistory_should_return_an_empty_list_when_there_is_an_error_getting_the_queue() + { + Mocker.GetMock() + .Setup(s => s.DownloadString("http://192.168.5.55:2222/api?mode=history&output=json&start=0&limit=0&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass")) + .Returns(File.ReadAllText(@".\Files\JsonError.txt")); + + //Act + Assert.Throws(() => Mocker.Resolve().GetHistory(), "API Key Incorrect"); + } + + } +} \ No newline at end of file diff --git a/NzbDrone.Core.Test/ProviderTests/DownloadProviderFixture.cs b/NzbDrone.Core.Test/ProviderTests/DownloadProviderFixture.cs new file mode 100644 index 000000000..922d683a1 --- /dev/null +++ b/NzbDrone.Core.Test/ProviderTests/DownloadProviderFixture.cs @@ -0,0 +1,249 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using FizzWare.NBuilder; +using FluentAssertions; +using Moq; +using NUnit.Framework; +using NzbDrone.Core.Model; +using NzbDrone.Core.Providers; +using NzbDrone.Core.Providers.Core; +using NzbDrone.Core.Providers.DownloadClients; +using NzbDrone.Core.Repository; +using NzbDrone.Core.Repository.Quality; +using NzbDrone.Core.Test.Framework; + +// ReSharper disable InconsistentNaming + +namespace NzbDrone.Core.Test.ProviderTests +{ + [TestFixture] + public class DownloadProviderFixture : CoreTest + { + + private void SetDownloadClient(DownloadClientType clientType) + { + Mocker.GetMock() + .Setup(c => c.DownloadClient) + .Returns(clientType); + } + + private EpisodeParseResult SetupParseResult() + { + var episodes = Builder.CreateListOfSize(2) + .TheFirst(1).With(s => s.EpisodeId = 12) + .TheNext(1).With(s => s.EpisodeId = 99) + .All().With(s => s.SeriesId = 5) + .Build().ToList(); + + Mocker.GetMock() + .Setup(c => c.GetEpisodesByParseResult(It.IsAny())).Returns(episodes); + + return Builder.CreateNew() + .With(c => c.Quality = new Quality(QualityTypes.DVD, false)) + .With(c => c.Series = Builder.CreateNew().Build()) + .With(c => c.EpisodeNumbers = new List{2}) + .Build(); + } + + private void WithSuccessfullAdd() + { + Mocker.GetMock() + .Setup(s => s.DownloadNzb(It.IsAny(), It.IsAny())) + .Returns(true); + + Mocker.GetMock() + .Setup(s => s.DownloadNzb(It.IsAny(), It.IsAny())) + .Returns(true); + } + + private void WithFailedAdd() + { + Mocker.GetMock() + .Setup(s => s.DownloadNzb(It.IsAny(), It.IsAny())) + .Returns(false); + + Mocker.GetMock() + .Setup(s => s.DownloadNzb(It.IsAny(), It.IsAny())) + .Returns(false); + } + + + [Test] + public void Download_report_should_send_to_sab_add_to_history_mark_as_grabbed() + { + WithSuccessfullAdd(); + SetDownloadClient(DownloadClientType.Sabnzbd); + + var parseResult = SetupParseResult(); + + //Act + Mocker.Resolve().DownloadReport(parseResult); + + + //Assert + Mocker.GetMock() + .Verify(s => s.DownloadNzb(It.IsAny(), It.IsAny()), Times.Once()); + + Mocker.GetMock() + .Verify(s => s.DownloadNzb(It.IsAny(), It.IsAny()), Times.Never()); + + Mocker.GetMock() + .Verify(s => s.Add(It.Is(h => h.EpisodeId == 12 && h.SeriesId == 5)), Times.Once()); + + Mocker.GetMock() + .Verify(s => s.Add(It.Is(h => h.EpisodeId == 99 && h.SeriesId == 5)), Times.Once()); + + Mocker.GetMock() + .Verify(c => c.MarkEpisodeAsFetched(12)); + + Mocker.GetMock() + .Verify(c => c.MarkEpisodeAsFetched(99)); + + Mocker.GetMock() + .Verify(c => c.OnGrab(It.IsAny())); + } + + [Test] + public void should_download_nzb_to_blackhole_add_to_history_mark_as_grabbed() + { + WithSuccessfullAdd(); + SetDownloadClient(DownloadClientType.Blackhole); + + var parseResult = SetupParseResult(); + + //Act + Mocker.Resolve().DownloadReport(parseResult); + + + //Assert + Mocker.GetMock() + .Verify(s => s.DownloadNzb(It.IsAny(), It.IsAny()), Times.Never()); + + Mocker.GetMock() + .Verify(s => s.DownloadNzb(It.IsAny(), It.IsAny()), Times.Once()); + + Mocker.GetMock() + .Verify(s => s.Add(It.Is(h => h.EpisodeId == 12 && h.SeriesId == 5)), Times.Once()); + + Mocker.GetMock() + .Verify(s => s.Add(It.Is(h => h.EpisodeId == 99 && h.SeriesId == 5)), Times.Once()); + + Mocker.GetMock() + .Verify(c => c.MarkEpisodeAsFetched(12)); + + Mocker.GetMock() + .Verify(c => c.MarkEpisodeAsFetched(99)); + + Mocker.GetMock() + .Verify(c => c.OnGrab(It.IsAny())); + } + + [TestCase(DownloadClientType.Sabnzbd)] + [TestCase(DownloadClientType.Blackhole)] + public void Download_report_should_not_add_to_history_mark_as_grabbed_if_add_fails(DownloadClientType clientType) + { + WithFailedAdd(); + SetDownloadClient(clientType); + + var parseResult = SetupParseResult(); + + //Act + Mocker.Resolve().DownloadReport(parseResult); + + Mocker.GetMock() + .Verify(s => s.Add(It.IsAny()), Times.Never()); + + + Mocker.GetMock() + .Verify(c => c.MarkEpisodeAsFetched(It.IsAny()), Times.Never()); + + Mocker.GetMock() + .Verify(c => c.OnGrab(It.IsAny()), Times.Never()); + } + + + + [Test] + public void should_return_sab_as_active_client() + { + SetDownloadClient(DownloadClientType.Sabnzbd); + Mocker.Resolve().GetActiveDownloadClient().Should().BeAssignableTo(); + } + + [Test] + public void should_return_blackhole_as_active_client() + { + SetDownloadClient(DownloadClientType.Blackhole); + Mocker.Resolve().GetActiveDownloadClient().Should().BeAssignableTo(); + } + + + [TestCase(1, new[] { 2 }, "My Episode Title", QualityTypes.DVD, false, Result = "My Series Name - 1x2 - My Episode Title [DVD]")] + [TestCase(1, new[] { 2 }, "My Episode Title", QualityTypes.DVD, true, Result = "My Series Name - 1x2 - My Episode Title [DVD] [Proper]")] + [TestCase(1, new[] { 2 }, "", QualityTypes.DVD, true, Result = "My Series Name - 1x2 - [DVD] [Proper]")] + [TestCase(1, new[] { 2, 4 }, "My Episode Title", QualityTypes.HDTV, false, Result = "My Series Name - 1x2-1x4 - My Episode Title [HDTV]")] + [TestCase(1, new[] { 2, 4 }, "My Episode Title", QualityTypes.HDTV, true, Result = "My Series Name - 1x2-1x4 - My Episode Title [HDTV] [Proper]")] + [TestCase(1, new[] { 2, 4 }, "", QualityTypes.HDTV, true, Result = "My Series Name - 1x2-1x4 - [HDTV] [Proper]")] + public string create_proper_sab_titles(int seasons, int[] episodes, string title, QualityTypes quality, bool proper) + { + var series = Builder.CreateNew() + .With(c => c.Title = "My Series Name") + .Build(); + + var parsResult = new EpisodeParseResult() + { + AirDate = DateTime.Now, + EpisodeNumbers = episodes.ToList(), + Quality = new Quality(quality, proper), + SeasonNumber = seasons, + Series = series, + EpisodeTitle = title + }; + + return Mocker.Resolve().GetDownloadTitle(parsResult); + } + + [TestCase(true, Result = "My Series Name - Season 1 [Bluray720p] [Proper]")] + [TestCase(false, Result = "My Series Name - Season 1 [Bluray720p]")] + public string create_proper_sab_season_title(bool proper) + { + var series = Builder.CreateNew() + .With(c => c.Title = "My Series Name") + .Build(); + + var parsResult = new EpisodeParseResult() + { + AirDate = DateTime.Now, + Quality = new Quality(QualityTypes.Bluray720p, proper), + SeasonNumber = 1, + Series = series, + EpisodeTitle = "My Episode Title", + FullSeason = true + }; + + return Mocker.Resolve().GetDownloadTitle(parsResult); + } + + [TestCase(true, Result = "My Series Name - 2011-12-01 - My Episode Title [Bluray720p] [Proper]")] + [TestCase(false, Result = "My Series Name - 2011-12-01 - My Episode Title [Bluray720p]")] + public string create_proper_sab_daily_titles(bool proper) + { + var series = Builder.CreateNew() + .With(c => c.IsDaily = true) + .With(c => c.Title = "My Series Name") + .Build(); + + var parsResult = new EpisodeParseResult + { + AirDate = new DateTime(2011, 12, 1), + Quality = new Quality(QualityTypes.Bluray720p, proper), + Series = series, + EpisodeTitle = "My Episode Title", + }; + + return Mocker.Resolve().GetDownloadTitle(parsResult); + } + + } +} \ No newline at end of file diff --git a/NzbDrone.Core.Test/ProviderTests/DownloadProviderTest.cs b/NzbDrone.Core.Test/ProviderTests/DownloadProviderTest.cs deleted file mode 100644 index 61e257470..000000000 --- a/NzbDrone.Core.Test/ProviderTests/DownloadProviderTest.cs +++ /dev/null @@ -1,125 +0,0 @@ -using System; - -using FizzWare.NBuilder; -using Moq; -using NUnit.Framework; -using NzbDrone.Core.Model; -using NzbDrone.Core.Providers; -using NzbDrone.Core.Providers.Core; -using NzbDrone.Core.Repository; -using NzbDrone.Core.Repository.Quality; -using NzbDrone.Core.Test.Framework; -using NzbDrone.Test.Common.AutoMoq; - -// ReSharper disable InconsistentNaming - -namespace NzbDrone.Core.Test.ProviderTests -{ - [TestFixture] - public class DownloadProviderTest : CoreTest - { - [Test] - public void Download_report_should_send_to_sab_add_to_history_mark_as_grabbed() - { - WithStrictMocker(); - var parseResult = Builder.CreateNew() - .With(c => c.Quality = new Quality(QualityTypes.DVD, false)) - .Build(); - - var episodes = Builder.CreateListOfSize(2) - .TheFirst(1).With(s => s.EpisodeId = 12) - .TheNext(1).With(s => s.EpisodeId = 99) - .All().With(s => s.SeriesId = 5) - .Build(); - - - const string sabTitle = "My fake sab title"; - Mocker.GetMock() - .Setup(s => s.IsInQueue(It.IsAny())) - .Returns(false); - - Mocker.GetMock() - .Setup(s => s.AddByUrl(parseResult.NzbUrl, sabTitle)) - .Returns(true); - - Mocker.GetMock() - .Setup(s => s.GetSabTitle(parseResult)) - .Returns(sabTitle); - - Mocker.GetMock() - .Setup(s => s.Add(It.Is(h => h.EpisodeId == 12 && h.SeriesId == 5))); - Mocker.GetMock() - .Setup(s => s.Add(It.Is(h => h.EpisodeId == 99 && h.SeriesId == 5))); - - Mocker.GetMock() - .Setup(c => c.GetEpisodesByParseResult(It.IsAny(), false)).Returns(episodes); - - Mocker.GetMock() - .Setup(c => c.MarkEpisodeAsFetched(12)); - - Mocker.GetMock() - .Setup(c => c.MarkEpisodeAsFetched(99)); - - Mocker.GetMock() - .Setup(c => c.OnGrab(It.IsAny())); - - Mocker.GetMock() - .Setup(c => c.DownloadClient) - .Returns(DownloadClientType.Sabnzbd); - - Mocker.Resolve().DownloadReport(parseResult); - - Mocker.VerifyAllMocks(); - } - - [Test] - public void Download_report_should_download_nzb_add_to_history_mark_as_grabbed() - { - WithStrictMocker(); - var parseResult = Builder.CreateNew() - .With(c => c.Quality = new Quality(QualityTypes.DVD, false)) - .Build(); - - var episodes = Builder.CreateListOfSize(2) - .TheFirst(1).With(s => s.EpisodeId = 12) - .TheNext(1).With(s => s.EpisodeId = 99) - .All().With(s => s.SeriesId = 5) - .Build(); - - - const string sabTitle = "My fake sab title"; - Mocker.GetMock() - .Setup(s => s.DownloadNzb(It.IsAny(), sabTitle)) - .Returns(true); - - Mocker.GetMock() - .Setup(s => s.GetSabTitle(parseResult)) - .Returns(sabTitle); - - Mocker.GetMock() - .Setup(s => s.Add(It.Is(h => h.EpisodeId == 12 && h.SeriesId == 5))); - Mocker.GetMock() - .Setup(s => s.Add(It.Is(h => h.EpisodeId == 99 && h.SeriesId == 5))); - - Mocker.GetMock() - .Setup(c => c.GetEpisodesByParseResult(It.IsAny(), false)).Returns(episodes); - - Mocker.GetMock() - .Setup(c => c.MarkEpisodeAsFetched(12)); - - Mocker.GetMock() - .Setup(c => c.MarkEpisodeAsFetched(99)); - - Mocker.GetMock() - .Setup(c => c.OnGrab(It.IsAny())); - - Mocker.GetMock() - .Setup(c => c.DownloadClient) - .Returns(DownloadClientType.Blackhole); - - Mocker.Resolve().DownloadReport(parseResult); - - Mocker.VerifyAllMocks(); - } - } -} \ No newline at end of file diff --git a/NzbDrone.Core.Test/ProviderTests/EpisodeProviderTest_GetEpisodesByParseResult.cs b/NzbDrone.Core.Test/ProviderTests/EpisodeProviderTest_GetEpisodesByParseResult.cs index 28827e81f..5f4b8bd4c 100644 --- a/NzbDrone.Core.Test/ProviderTests/EpisodeProviderTest_GetEpisodesByParseResult.cs +++ b/NzbDrone.Core.Test/ProviderTests/EpisodeProviderTest_GetEpisodesByParseResult.cs @@ -75,7 +75,7 @@ namespace NzbDrone.Core.Test.ProviderTests EpisodeNumbers = new List { fakeEpisode.EpisodeNumber } }; - var ep = episodeProvider.GetEpisodesByParseResult(parseResult, true); + var ep = episodeProvider.GetEpisodesByParseResult(parseResult); ep.Should().HaveCount(1); parseResult.EpisodeTitle.Should().Be(fakeEpisode.Title); @@ -93,7 +93,7 @@ namespace NzbDrone.Core.Test.ProviderTests EpisodeNumbers = new List { 10 } }; - var episode = episodeProvider.GetEpisodesByParseResult(parseResult, true); + var episode = episodeProvider.GetEpisodesByParseResult(parseResult); episode.Should().BeEmpty(); Db.Fetch().Should().HaveCount(0); @@ -109,7 +109,7 @@ namespace NzbDrone.Core.Test.ProviderTests EpisodeNumbers = new List { 10 } }; - var episode = episodeProvider.GetEpisodesByParseResult(parseResult, true); + var episode = episodeProvider.GetEpisodesByParseResult(parseResult); episode.Should().BeEmpty(); Db.Fetch().Should().HaveCount(0); @@ -130,7 +130,7 @@ namespace NzbDrone.Core.Test.ProviderTests EpisodeNumbers = new List { fakeEpisode.EpisodeNumber, fakeEpisode2.EpisodeNumber } }; - var ep = episodeProvider.GetEpisodesByParseResult(parseResult, true); + var ep = episodeProvider.GetEpisodesByParseResult(parseResult); ep.Should().HaveCount(2); Db.Fetch().Should().HaveCount(2); @@ -153,7 +153,7 @@ namespace NzbDrone.Core.Test.ProviderTests EpisodeNumbers = new List { fakeEpisode.EpisodeNumber, fakeEpisode2.EpisodeNumber } }; - var ep = episodeProvider.GetEpisodesByParseResult(parseResult,true); + var ep = episodeProvider.GetEpisodesByParseResult(parseResult); ep.Should().BeEmpty(); Db.Fetch().Should().BeEmpty(); @@ -188,7 +188,7 @@ namespace NzbDrone.Core.Test.ProviderTests Db.Insert(fakeDailyEpisode); //Act - var episodes = episodeProvider.GetEpisodesByParseResult(new EpisodeParseResult { AirDate = DateTime.Today, Series = fakeDailySeries },true); + var episodes = episodeProvider.GetEpisodesByParseResult(new EpisodeParseResult { AirDate = DateTime.Today, Series = fakeDailySeries }); //Assert episodes.Should().HaveCount(1); @@ -200,7 +200,7 @@ namespace NzbDrone.Core.Test.ProviderTests [Test] public void should_not_add_episode_when_episode_doesnt_exist() { - var episodes = episodeProvider.GetEpisodesByParseResult(new EpisodeParseResult { AirDate = DateTime.Today, Series = fakeDailySeries }, true); + var episodes = episodeProvider.GetEpisodesByParseResult(new EpisodeParseResult { AirDate = DateTime.Today, Series = fakeDailySeries }); //Assert episodes.Should().HaveCount(0); diff --git a/NzbDrone.Core.Test/ProviderTests/HistoryProviderTest.cs b/NzbDrone.Core.Test/ProviderTests/HistoryProviderTest.cs index 8e3b6921c..a73db927d 100644 --- a/NzbDrone.Core.Test/ProviderTests/HistoryProviderTest.cs +++ b/NzbDrone.Core.Test/ProviderTests/HistoryProviderTest.cs @@ -1,15 +1,12 @@ using System; using System.Linq; - using FizzWare.NBuilder; using FluentAssertions; -using Moq; using NUnit.Framework; using NzbDrone.Core.Providers; using NzbDrone.Core.Repository; using NzbDrone.Core.Repository.Quality; using NzbDrone.Core.Test.Framework; -using NzbDrone.Test.Common.AutoMoq; namespace NzbDrone.Core.Test.ProviderTests { @@ -20,14 +17,11 @@ namespace NzbDrone.Core.Test.ProviderTests [Test] public void AllItems() { + WithRealDb(); //Setup var historyItem = Builder.CreateListOfSize(10).Build(); - - var db = TestDbHelper.GetEmptyDatabase(); - Mocker.SetConstant(db); - - db.InsertMany(historyItem); + Db.InsertMany(historyItem); //Act var result = Mocker.Resolve().AllItems(); @@ -39,7 +33,7 @@ namespace NzbDrone.Core.Test.ProviderTests [Test] public void AllItemsWithRelationships() { - //Setup + WithRealDb(); var seriesOne = Builder.CreateNew().With(s => s.SeriesId = 12345).Build(); var seriesTwo = Builder.CreateNew().With(s => s.SeriesId = 54321).Build(); @@ -47,14 +41,11 @@ namespace NzbDrone.Core.Test.ProviderTests var historyItems = Builder.CreateListOfSize(10).TheFirst(5).With(h => h.SeriesId = seriesOne.SeriesId).TheLast(5).With(h => h.SeriesId = seriesTwo.SeriesId).Build(); - - var db = TestDbHelper.GetEmptyDatabase(); - Mocker.SetConstant(db); - db.InsertMany(historyItems); - db.InsertMany(episodes); - db.Insert(seriesOne); - db.Insert(seriesTwo); + Db.InsertMany(historyItems); + Db.InsertMany(episodes); + Db.Insert(seriesOne); + Db.Insert(seriesTwo); //Act var result = Mocker.Resolve().AllItemsWithRelationships(); @@ -72,46 +63,37 @@ namespace NzbDrone.Core.Test.ProviderTests [Test] public void PurgeItem() { - //Setup - var historyItem = Builder.CreateListOfSize(10).Build(); - - - var db = TestDbHelper.GetEmptyDatabase(); - Mocker.SetConstant(db); - - db.InsertMany(historyItem); + WithRealDb(); + var historyItem = Builder.CreateListOfSize(10).Build(); + Db.InsertMany(historyItem); //Act - db.Fetch().Should().HaveCount(10); + Db.Fetch().Should().HaveCount(10); Mocker.Resolve().Purge(); //Assert - db.Fetch().Should().HaveCount(0); + Db.Fetch().Should().HaveCount(0); } [Test] public void Trim_Items() { - //Setup + WithRealDb(); + var historyItem = Builder.CreateListOfSize(30) .TheFirst(10).With(c => c.Date = DateTime.Now) .TheNext(20).With(c => c.Date = DateTime.Now.AddDays(-31)) .Build(); - - var db = TestDbHelper.GetEmptyDatabase(); - Mocker.SetConstant(db); - - db.InsertMany(historyItem); - + Db.InsertMany(historyItem); //Act - db.Fetch().Should().HaveCount(30); + Db.Fetch().Should().HaveCount(30); Mocker.Resolve().Trim(); //Assert - var result = db.Fetch(); + var result = Db.Fetch(); result.Should().HaveCount(10); result.Should().OnlyContain(s => s.Date > DateTime.Now.AddDays(-30)); } @@ -120,44 +102,96 @@ namespace NzbDrone.Core.Test.ProviderTests [Test] public void GetBestQualityInHistory_no_result() { - WithStrictMocker(); + WithRealDb(); + Mocker.Resolve().GetBestQualityInHistory(12, 12, 12).Should().Be(null); + } + + [Test] + public void GetBestQualityInHistory_single_result() + { + WithRealDb(); - Mocker.SetConstant(TestDbHelper.GetEmptyDatabase()); + var episodes = Builder.CreateListOfSize(10).Build(); + var historyEpisode = episodes[6]; + + var history = Builder.CreateNew() + .With(h => h.Quality = QualityTypes.Bluray720p) + .With(h => h.IsProper = true) + .With(h => h.EpisodeId = historyEpisode.EpisodeId) + .Build(); + + Db.Insert(history); + Db.InsertMany(episodes); //Act - var result = Mocker.Resolve().GetBestQualityInHistory(12); + var result = Mocker.Resolve() + .GetBestQualityInHistory(historyEpisode.SeriesId, historyEpisode.SeasonNumber, historyEpisode.EpisodeNumber); //Assert - Assert.IsNull(result); + result.Should().NotBeNull(); + result.QualityType.Should().Be(QualityTypes.Bluray720p); + result.Proper.Should().BeTrue(); } [Test] - public void GetBestQualityInHistory_single_result() + public void GetBestQualityInHistory_should_return_highest_result() { - WithStrictMocker(); + WithRealDb(); - var db = TestDbHelper.GetEmptyDatabase(); - var history = Builder.CreateNew() - .With(h => h.Quality = QualityTypes.Bluray720p).Build(); + var episodes = Builder.CreateListOfSize(10).Build(); + var historyEpisode = episodes[6]; - db.Insert(history); - Mocker.SetConstant(db); + var history0 = Builder.CreateNew() + .With(h => h.Quality = QualityTypes.DVD) + .With(h => h.IsProper = true) + .With(h => h.EpisodeId = historyEpisode.EpisodeId) + .Build(); + + var history1 = Builder.CreateNew() + .With(h => h.Quality = QualityTypes.Bluray720p) + .With(h => h.IsProper = false) + .With(h => h.EpisodeId = historyEpisode.EpisodeId) + .Build(); + + var history2 = Builder.CreateNew() + .With(h => h.Quality = QualityTypes.Bluray720p) + .With(h => h.IsProper = true) + .With(h => h.EpisodeId = historyEpisode.EpisodeId) + .Build(); + + var history3 = Builder.CreateNew() + .With(h => h.Quality = QualityTypes.Bluray720p) + .With(h => h.IsProper = false) + .With(h => h.EpisodeId = historyEpisode.EpisodeId) + .Build(); + + var history4 = Builder.CreateNew() + .With(h => h.Quality = QualityTypes.SDTV) + .With(h => h.IsProper = true) + .With(h => h.EpisodeId = historyEpisode.EpisodeId) + .Build(); + + Db.Insert(history0); + Db.Insert(history1); + Db.Insert(history2); + Db.Insert(history2); + Db.Insert(history4); + Db.InsertMany(episodes); //Act - var result = Mocker.Resolve().GetBestQualityInHistory(history.EpisodeId); + var result = Mocker.Resolve() + .GetBestQualityInHistory(historyEpisode.SeriesId, historyEpisode.SeasonNumber, historyEpisode.EpisodeNumber); //Assert result.Should().NotBeNull(); result.QualityType.Should().Be(QualityTypes.Bluray720p); + result.Proper.Should().BeTrue(); } [Test] public void add_item() { - - var db = TestDbHelper.GetEmptyDatabase(); - - Mocker.SetConstant(db); + WithRealDb(); var episode = Builder.CreateNew().Build(); @@ -179,11 +213,11 @@ namespace NzbDrone.Core.Test.ProviderTests Mocker.Resolve().Add(history); //Assert - var storedHistory = db.Fetch(); + var storedHistory = Db.Fetch(); storedHistory.Should().HaveCount(1); history.Date.Should().BeWithin(TimeSpan.FromMinutes(1)).Before(storedHistory.First().Date); - + history.EpisodeId.Should().Be(storedHistory.First().EpisodeId); history.SeriesId.Should().Be(storedHistory.First().SeriesId); history.NzbTitle.Should().Be(storedHistory.First().NzbTitle); diff --git a/NzbDrone.Core.Test/ProviderTests/InventoryProviderTests/IsMonitoredFixture.cs b/NzbDrone.Core.Test/ProviderTests/InventoryProviderTests/IsMonitoredFixture.cs deleted file mode 100644 index 50a85e6a4..000000000 --- a/NzbDrone.Core.Test/ProviderTests/InventoryProviderTests/IsMonitoredFixture.cs +++ /dev/null @@ -1,272 +0,0 @@ -// ReSharper disable RedundantUsingDirective - -using System; -using System.Collections.Generic; - -using FizzWare.NBuilder; -using FluentAssertions; -using Moq; -using NUnit.Framework; -using NzbDrone.Core.Model; -using NzbDrone.Core.Providers; -using NzbDrone.Core.Repository; -using NzbDrone.Core.Repository.Quality; -using NzbDrone.Core.Test.Framework; -using NzbDrone.Test.Common.AutoMoq; - -namespace NzbDrone.Core.Test.ProviderTests.InventoryProviderTests -{ - [TestFixture] - // ReSharper disable InconsistentNaming - public class IsMonitoredFixture : CoreTest - { - private EpisodeParseResult parseResultMulti; - private Series series; - private Episode episode; - private Episode episode2; - private EpisodeParseResult parseResultSingle; - private EpisodeParseResult parseResultDaily; - - [SetUp] - public void Setup() - { - parseResultMulti = new EpisodeParseResult() - { - SeriesTitle = "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() - { - SeriesTitle = "Title", - Language = LanguageType.English, - Quality = new Quality(QualityTypes.Bluray720p, true), - EpisodeNumbers = new List { 3 }, - SeasonNumber = 12, - AirDate = DateTime.Now.AddDays(-12).Date, - }; - - parseResultDaily = new EpisodeParseResult() - { - SeriesTitle = "Title", - Language = LanguageType.English, - Quality = new Quality(QualityTypes.Bluray720p, true), - 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(); - } - - - [Test] - public void not_monitored_series_should_be_skipped() - { - series.Monitored = false; - - WithStrictMocker(); - - 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() - { - WithStrictMocker(); - - 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 IsMonitored_should_return_true() - { - WithStrictMocker(); - - Mocker.GetMock() - .Setup(p => p.FindSeries(It.IsAny())) - .Returns(series); - - Mocker.GetMock() - .Setup(p => p.GetEpisodesByParseResult(It.IsAny(), true)) - .Returns(new List { episode }); - - parseResultSingle.Series.Should().BeNull(); - - var result = Mocker.Resolve().IsMonitored(parseResultSingle); - - //Assert - result.Should().BeTrue(); - parseResultSingle.Series.Should().Be(series); - Mocker.VerifyAllMocks(); - } - - - [Test] - public void IsMonitored_ignored_single_episode_should_return_false() - { - WithStrictMocker(); - - Mocker.GetMock() - .Setup(p => p.FindSeries(It.IsAny())) - .Returns(series); - - Mocker.GetMock() - .Setup(p => p.GetEpisodesByParseResult(It.IsAny(), true)) - .Returns(new List { episode }); - - episode.Ignored = true; - - parseResultSingle.Series.Should().BeNull(); - - var result = Mocker.Resolve().IsMonitored(parseResultSingle); - - //Assert - result.Should().BeFalse(); - parseResultSingle.Series.Should().Be(series); - Mocker.VerifyAllMocks(); - } - - [Test] - public void IsMonitored_multi_some_episodes_ignored_should_return_true() - { - WithStrictMocker(); - - Mocker.GetMock() - .Setup(p => p.FindSeries(It.IsAny())) - .Returns(series); - - Mocker.GetMock() - .Setup(p => p.GetEpisodesByParseResult(It.IsAny(), true)) - .Returns(new List { episode, episode2 }); - - episode.Ignored = true; - episode2.Ignored = false; - - parseResultMulti.Series.Should().BeNull(); - - var result = Mocker.Resolve().IsMonitored(parseResultMulti); - - //Assert - result.Should().BeTrue(); - parseResultMulti.Series.Should().Be(series); - Mocker.VerifyAllMocks(); - } - - [Test] - public void IsMonitored_multi_all_episodes_ignored_should_return_false() - { - WithStrictMocker(); - - Mocker.GetMock() - .Setup(p => p.FindSeries(It.IsAny())) - .Returns(series); - - Mocker.GetMock() - .Setup(p => p.GetEpisodesByParseResult(It.IsAny(), true)) - .Returns(new List { episode, episode2 }); - - episode.Ignored = true; - episode2.Ignored = true; - - parseResultSingle.Series.Should().BeNull(); - - var result = Mocker.Resolve().IsMonitored(parseResultMulti); - - //Assert - result.Should().BeFalse(); - parseResultMulti.Series.Should().Be(series); - Mocker.VerifyAllMocks(); - } - - - [Test] - public void IsMonitored_multi_no_episodes_ignored_should_return_true() - { - WithStrictMocker(); - - Mocker.GetMock() - .Setup(p => p.FindSeries(It.IsAny())) - .Returns(series); - - Mocker.GetMock() - .Setup(p => p.GetEpisodesByParseResult(It.IsAny(), true)) - .Returns(new List { episode, episode2 }); - - episode.Ignored = false; - episode2.Ignored = false; - - parseResultSingle.Series.Should().BeNull(); - - var result = Mocker.Resolve().IsMonitored(parseResultMulti); - - //Assert - result.Should().BeTrue(); - parseResultMulti.Series.Should().Be(series); - Mocker.VerifyAllMocks(); - } - - [Test] - public void IsMonitored_daily_not_ignored_should_return_true() - { - WithStrictMocker(); - - Mocker.GetMock() - .Setup(p => p.FindSeries(It.IsAny())) - .Returns(series); - - Mocker.GetMock() - .Setup(p => p.GetEpisodesByParseResult(It.IsAny(), true)) - .Returns(new List { episode }); - - episode.Ignored = false; - - var result = Mocker.Resolve().IsMonitored(parseResultDaily); - - //Assert - result.Should().BeTrue(); - } - } -} \ No newline at end of file diff --git a/NzbDrone.Core.Test/ProviderTests/InventoryProviderTests/IsUpgradeFixture.cs b/NzbDrone.Core.Test/ProviderTests/InventoryProviderTests/IsUpgradeFixture.cs deleted file mode 100644 index ce5b6833d..000000000 --- a/NzbDrone.Core.Test/ProviderTests/InventoryProviderTests/IsUpgradeFixture.cs +++ /dev/null @@ -1,140 +0,0 @@ -// ReSharper disable RedundantUsingDirective - -using System; -using System.Collections.Generic; - -using FizzWare.NBuilder; -using FluentAssertions; -using Moq; -using NUnit.Framework; -using NzbDrone.Core.Model; -using NzbDrone.Core.Providers; -using NzbDrone.Core.Repository; -using NzbDrone.Core.Repository.Quality; -using NzbDrone.Core.Test.Framework; -using NzbDrone.Test.Common.AutoMoq; - -namespace NzbDrone.Core.Test.ProviderTests.InventoryProviderTests -{ - [TestFixture] - // ReSharper disable InconsistentNaming - public class IsUpgradeFixture : CoreTest - { - [Test] - public void IsUpgrade_should_return_true_if_new_is_proper_and_current_isnt_even_if_cutoff_is_met() - { - var currentQuality = new Quality(QualityTypes.SDTV, false); - var newQuality = new Quality(QualityTypes.SDTV, true); - var cutoff = QualityTypes.SDTV; - - var result = InventoryProvider.IsUpgrade(currentQuality, newQuality, cutoff); - - //Assert - result.Should().BeTrue(); - } - - [Test] - public void IsUpgrade_should_return_true_if_new_quality_is_better_than_current_and_cutoff_is_not_met() - { - var currentQuality = new Quality(QualityTypes.SDTV, false); - var newQuality = new Quality(QualityTypes.DVD, true); - var cutoff = QualityTypes.DVD; - - var result = InventoryProvider.IsUpgrade(currentQuality, newQuality, cutoff); - - //Assert - result.Should().BeTrue(); - } - - [Test] - public void IsUpgrade_should_return_false_if_new_quality_is_same_as_current_and_cutoff_is_met() - { - var currentQuality = new Quality(QualityTypes.SDTV, false); - var newQuality = new Quality(QualityTypes.SDTV, false); - var cutoff = QualityTypes.SDTV; - - var result = InventoryProvider.IsUpgrade(currentQuality, newQuality, cutoff); - - //Assert - result.Should().BeFalse(); - } - - [Test] - public void IsUpgrade_should_return_false_if_new_quality_is_better_than_current_and_cutoff_is_met() - { - var currentQuality = new Quality(QualityTypes.SDTV, false); - var newQuality = new Quality(QualityTypes.DVD, true); - var cutoff = QualityTypes.SDTV; - - var result = InventoryProvider.IsUpgrade(currentQuality, newQuality, cutoff); - - //Assert - result.Should().BeFalse(); - } - - [Test] - public void IsUpgrade_should_return_false_if_new_quality_is_worse_than_current_and_cutoff_is_not_met() - { - var currentQuality = new Quality(QualityTypes.WEBDL, false); - var newQuality = new Quality(QualityTypes.HDTV, true); - var cutoff = QualityTypes.Bluray720p; - - var result = InventoryProvider.IsUpgrade(currentQuality, newQuality, cutoff); - - //Assert - result.Should().BeFalse(); - } - - [Test] - public void IsUpgrade_should_return_false_if_new_quality_is_worse_than_current_and_cutoff_is_met() - { - var currentQuality = new Quality(QualityTypes.WEBDL, false); - var newQuality = new Quality(QualityTypes.HDTV, true); - var cutoff = QualityTypes.WEBDL; - - var result = InventoryProvider.IsUpgrade(currentQuality, newQuality, cutoff); - - //Assert - result.Should().BeFalse(); - } - - [Test] - public void IsUpgrade_should_return_false_if_new_quality_is_the_same_as_current_and_cutoff_is_met() - { - var currentQuality = new Quality(QualityTypes.WEBDL, false); - var newQuality = new Quality(QualityTypes.WEBDL, false); - var cutoff = QualityTypes.WEBDL; - - var result = InventoryProvider.IsUpgrade(currentQuality, newQuality, cutoff); - - //Assert - result.Should().BeFalse(); - } - - [Test] - public void IsUpgrade_should_return_true_if_new_quality_is_a_proper_with_the_same_quality_as_current_and_cutoff_is_not_met() - { - var currentQuality = new Quality(QualityTypes.WEBDL, false); - var newQuality = new Quality(QualityTypes.WEBDL, true); - var cutoff = QualityTypes.Bluray720p; - - var result = InventoryProvider.IsUpgrade(currentQuality, newQuality, cutoff); - - //Assert - result.Should().BeTrue(); - } - - [Test] - public void IsUpgrade_should_return_false_if_new_equals_current_but_current_is_proper_even_if_cutoff_is_met() - { - var currentQuality = new Quality(QualityTypes.SDTV, true); - var newQuality = new Quality(QualityTypes.SDTV, false); - var cutoff = QualityTypes.SDTV; - - var result = InventoryProvider.IsUpgrade(currentQuality, newQuality, cutoff); - - //Assert - result.Should().BeFalse(); - } - } -} \ No newline at end of file diff --git a/NzbDrone.Core.Test/ProviderTests/InventoryProviderTests/QualityNeededFixture.cs b/NzbDrone.Core.Test/ProviderTests/InventoryProviderTests/QualityNeededFixture.cs deleted file mode 100644 index 74d94f7d1..000000000 --- a/NzbDrone.Core.Test/ProviderTests/InventoryProviderTests/QualityNeededFixture.cs +++ /dev/null @@ -1,311 +0,0 @@ -// ReSharper disable RedundantUsingDirective - -using System; -using System.Collections.Generic; - -using FizzWare.NBuilder; -using FluentAssertions; -using Moq; -using NUnit.Framework; -using NzbDrone.Core.Model; -using NzbDrone.Core.Providers; -using NzbDrone.Core.Repository; -using NzbDrone.Core.Repository.Quality; -using NzbDrone.Core.Test.Framework; -using NzbDrone.Test.Common.AutoMoq; - -namespace NzbDrone.Core.Test.ProviderTests.InventoryProviderTests -{ - [TestFixture] - // ReSharper disable InconsistentNaming - public class QualityNeededFixture : CoreTest - { - 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 void Setup() - { - parseResultMulti = new EpisodeParseResult - { - SeriesTitle = "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 - { - SeriesTitle = "Title", - Language = LanguageType.English, - Quality = new Quality(QualityTypes.Bluray720p, true), - EpisodeNumbers = new List { 3 }, - SeasonNumber = 12, - AirDate = DateTime.Now.AddDays(-12).Date, - }; - - 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);*/ - } - - [Test] - public void IsQualityNeeded_report_not_in_quality_profile_should_be_skipped() - { - WithStrictMocker(); - - 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() - { - WithStrictMocker(); - - parseResultMulti.Series.QualityProfile = hdProfile; - - parseResultMulti.Quality = new Quality(QualityTypes.HDTV, true); - - Mocker.GetMock() - .Setup(p => p.GetEpisodesByParseResult(parseResultMulti, true)) - .Returns(new List { episode, episode2 }); - - Mocker.GetMock() - .Setup(s => s.Get(It.IsAny())) - .Returns(new QualityType { MaxSize = 100, MinSize = 0 }); - - episode.EpisodeFile.Quality = QualityTypes.Bluray720p; - - //Act - bool result = Mocker.Resolve().IsQualityNeeded(parseResultMulti); - - //Assert - Assert.IsFalse(result); - Mocker.VerifyAllMocks(); - } - - [Test] - public void IsQualityNeeded_file_in_history_should_be_skipped() - { - WithStrictMocker(); - - parseResultSingle.Series.QualityProfile = sdProfile; - parseResultSingle.Quality.QualityType = QualityTypes.DVD; - - Mocker.GetMock() - .Setup(p => p.GetBestQualityInHistory(episode.EpisodeId)) - .Returns(new Quality(QualityTypes.DVD, true)); - - Mocker.GetMock() - .Setup(p => p.GetEpisodesByParseResult(parseResultSingle, true)) - .Returns(new List { episode }); - - Mocker.GetMock() - .Setup(p => p.IsFirstOrLastEpisodeOfSeason(It.IsAny(), It.IsAny(), It.IsAny())) - .Returns(false); - - Mocker.GetMock() - .Setup(s => s.Get(It.IsAny())) - .Returns(new QualityType { MaxSize = 100, MinSize = 0 }); - - episode.EpisodeFile.Quality = QualityTypes.SDTV; - - //Act - bool result = Mocker.Resolve().IsQualityNeeded(parseResultSingle); - - //Assert - Assert.IsFalse(result); - Mocker.VerifyAllMocks(); - } - - [Test] - public void IsQualityNeeded_lesser_file_in_history_should_be_downloaded() - { - WithStrictMocker(); - - parseResultSingle.Series.QualityProfile = sdProfile; - parseResultSingle.Quality.QualityType = QualityTypes.DVD; - - Mocker.GetMock() - .Setup(p => p.GetBestQualityInHistory(episode.EpisodeId)) - .Returns(new Quality(QualityTypes.SDTV, true)); - - Mocker.GetMock() - .Setup(p => p.GetEpisodesByParseResult(parseResultSingle, true)) - .Returns(new List { episode }); - - Mocker.GetMock() - .Setup(p => p.IsFirstOrLastEpisodeOfSeason(It.IsAny(), It.IsAny(), It.IsAny())) - .Returns(false); - - Mocker.GetMock() - .Setup(s => s.Get(It.IsAny())) - .Returns(new QualityType { MaxSize = 100, MinSize = 0 }); - - episode.EpisodeFile.Quality = QualityTypes.SDTV; - - //Act - bool result = Mocker.Resolve().IsQualityNeeded(parseResultSingle); - - //Assert - result.Should().BeTrue(); - Mocker.VerifyAllMocks(); - } - - [Test] - public void IsQualityNeeded_file_not_in_history_should_be_downloaded() - { - WithStrictMocker(); - - parseResultSingle.Series.QualityProfile = sdProfile; - parseResultSingle.Quality.QualityType = QualityTypes.DVD; - - Mocker.GetMock() - .Setup(p => p.GetBestQualityInHistory(episode.EpisodeId)) - .Returns(null); - - Mocker.GetMock() - .Setup(p => p.GetEpisodesByParseResult(parseResultSingle, true)) - .Returns(new List { episode }); - - Mocker.GetMock() - .Setup(p => p.IsFirstOrLastEpisodeOfSeason(It.IsAny(), It.IsAny(), It.IsAny())) - .Returns(false); - - Mocker.GetMock() - .Setup(s => s.Get(It.IsAny())) - .Returns(new QualityType { MaxSize = 100, MinSize = 0 }); - - episode.EpisodeFile.Quality = QualityTypes.SDTV; - //Act - bool result = Mocker.Resolve().IsQualityNeeded(parseResultSingle); - - //Assert - result.Should().BeTrue(); - Mocker.VerifyAllMocks(); - } - - //Should Download - [TestCase(QualityTypes.SDTV, true, QualityTypes.HDTV, false, true)] - [TestCase(QualityTypes.DVD, true, QualityTypes.Bluray720p, true, true)] - [TestCase(QualityTypes.HDTV, false, QualityTypes.HDTV, true, true)] - [TestCase(QualityTypes.HDTV, false, QualityTypes.HDTV, false, false)] - [TestCase(QualityTypes.Bluray720p, true, QualityTypes.Bluray1080p, false, false)] - [TestCase(QualityTypes.HDTV, true, QualityTypes.Bluray720p, true, true)] - [TestCase(QualityTypes.Bluray1080p, true, QualityTypes.Bluray720p, true, false)] - [TestCase(QualityTypes.Bluray1080p, true, QualityTypes.Bluray720p, false, false)] - [TestCase(QualityTypes.Bluray1080p, false, QualityTypes.Bluray720p, true, false)] - [TestCase(QualityTypes.HDTV, false, QualityTypes.Bluray720p, true, true)] - [TestCase(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); - } - - [Test] - public void IsQualityNeeded_file_should_skip_history_check_for_manual_search() - { - WithStrictMocker(); - - parseResultSingle.Series.QualityProfile = sdProfile; - parseResultSingle.Quality.QualityType = QualityTypes.DVD; - - Mocker.GetMock() - .Setup(p => p.GetBestQualityInHistory(episode.EpisodeId)) - .Returns(null); - - Mocker.GetMock() - .Setup(p => p.GetEpisodesByParseResult(parseResultSingle, true)) - .Returns(new List { episode }); - - Mocker.GetMock() - .Setup(p => p.IsFirstOrLastEpisodeOfSeason(It.IsAny(), It.IsAny(), It.IsAny())) - .Returns(false); - - Mocker.GetMock() - .Setup(s => s.Get(It.IsAny())) - .Returns(new QualityType { MaxSize = 100, MinSize = 0 }); - - episode.EpisodeFile.Quality = QualityTypes.SDTV; - //Act - bool result = Mocker.Resolve().IsQualityNeeded(parseResultSingle, true); - - //Assert - result.Should().BeTrue(); - Mocker.Verify(c => c.GetBestQualityInHistory(It.IsAny()), Times.Never()); - } - } -} \ No newline at end of file diff --git a/NzbDrone.Core.Test/ProviderTests/PostDownloadProviderTests/ProcessDownloadProviderFixture.cs b/NzbDrone.Core.Test/ProviderTests/PostDownloadProviderTests/ProcessDownloadProviderFixture.cs index 3e93a4493..eb4e979d4 100644 --- a/NzbDrone.Core.Test/ProviderTests/PostDownloadProviderTests/ProcessDownloadProviderFixture.cs +++ b/NzbDrone.Core.Test/ProviderTests/PostDownloadProviderTests/ProcessDownloadProviderFixture.cs @@ -20,6 +20,13 @@ namespace NzbDrone.Core.Test.ProviderTests.PostDownloadProviderTests [TestFixture] public class ProcessDownloadProviderFixture : CoreTest { + Series fakeSeries; + + [SetUp] + public void Setup() + { + fakeSeries = Builder.CreateNew().Build(); + } private void WithOldWrite() { @@ -35,6 +42,20 @@ namespace NzbDrone.Core.Test.ProviderTests.PostDownloadProviderTests .Returns(DateTime.UtcNow); } + private void WithValidSeries() + { + Mocker.GetMock() + .Setup(c => c.FindSeries(It.IsAny())) + .Returns(fakeSeries); + } + + private void WithImportableFiles() + { + Mocker.GetMock() + .Setup(c => c.Scan(It.IsAny(), It.IsAny())) + .Returns(Builder.CreateListOfSize(1).Build().ToList()); + } + [Test] public void should_skip_if_folder_is_tagged_and_too_fresh() { @@ -82,6 +103,36 @@ namespace NzbDrone.Core.Test.ProviderTests.PostDownloadProviderTests ExceptionVerification.IgnoreWarns(); } + [Test] + public void should_search_for_series_using_folder_name() + { + WithOldWrite(); + WithValidSeries(); + WithImportableFiles(); + + var droppedFolder = new DirectoryInfo(@"C:\Test\Unsorted TV\The Office - S01E01 - Episode Title"); + Mocker.Resolve().ProcessDownload(droppedFolder); + + Mocker.GetMock() + .Verify(c=>c.Scan(fakeSeries, It.IsAny())); + + } + + [Test] + public void should_search_for_series_using_file_name() + { + WithOldWrite(); + WithValidSeries(); + WithImportableFiles(); + + var droppedFolder = new DirectoryInfo(@"C:\Test\Unsorted TV\The Office - S01E01 - Episode Title"); + Mocker.Resolve().ProcessDownload(droppedFolder); + + Mocker.GetMock() + .Verify(c => c.Scan(fakeSeries, It.IsAny())); + + } + [Test] [Ignore("Disabled tagging")] public void when_series_isnt_found_folder_should_be_tagged_as_unknown_series() @@ -267,7 +318,7 @@ namespace NzbDrone.Core.Test.ProviderTests.PostDownloadProviderTests [Test] public void ProcessDropFolder_should_only_process_folders_that_arent_known_series_folders() { - var subFolders = new [] + var subFolders = new[] { @"c:\drop\episode1", @"c:\drop\episode2", diff --git a/NzbDrone.Core.Test/ProviderTests/SabProviderTests/SabProviderTest.cs b/NzbDrone.Core.Test/ProviderTests/SabProviderTests/SabProviderTest.cs deleted file mode 100644 index 9eae13c6d..000000000 --- a/NzbDrone.Core.Test/ProviderTests/SabProviderTests/SabProviderTest.cs +++ /dev/null @@ -1,281 +0,0 @@ -// ReSharper disable RedundantUsingDirective - -using System; -using System.IO; -using System.Linq; -using FizzWare.NBuilder; -using FluentAssertions; -using Moq; -using NUnit.Framework; -using NzbDrone.Core.Model; -using NzbDrone.Core.Providers; -using NzbDrone.Core.Providers.Core; -using NzbDrone.Core.Repository; -using NzbDrone.Core.Repository.Quality; -using NzbDrone.Core.Test.Framework; -using NzbDrone.Test.Common; - -namespace NzbDrone.Core.Test.ProviderTests.SabProviderTests -{ - [TestFixture] - // ReSharper disable InconsistentNaming - public class SabProviderTest : CoreTest - { - [SetUp] - public void Setup() - { - //Setup - string sabHost = "192.168.5.55"; - int sabPort = 2222; - string apikey = "5c770e3197e4fe763423ee7c392c25d1"; - string username = "admin"; - string password = "pass"; - string cat = "tv"; - - var fakeConfig = Mocker.GetMock(); - fakeConfig.SetupGet(c => c.SabHost).Returns(sabHost); - fakeConfig.SetupGet(c => c.SabPort).Returns(sabPort); - fakeConfig.SetupGet(c => c.SabApiKey).Returns(apikey); - fakeConfig.SetupGet(c => c.SabUsername).Returns(username); - fakeConfig.SetupGet(c => c.SabPassword).Returns(password); - fakeConfig.SetupGet(c => c.SabTvCategory).Returns(cat); - } - - - private void WithFailResponse() - { - Mocker.GetMock() - .Setup(s => s.DownloadString(It.IsAny())).Returns("failed"); - } - - [Test] - public void add_url_should_format_request_properly() - { - Mocker.GetMock(MockBehavior.Strict) - .Setup( - s => - s.DownloadString( - "http://192.168.5.55:2222/api?mode=addurl&name=http://www.nzbclub.com/nzb_download.aspx?mid=1950232&priority=0&pp=3&cat=tv&nzbname=This+is+an+Nzb&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass")) - .Returns("ok"); - - //Act - bool result = Mocker.Resolve().AddByUrl( - "http://www.nzbclub.com/nzb_download.aspx?mid=1950232", - "This is an Nzb"); - - //Assert - result.Should().BeTrue(); - } - - - [Test] - public void newzbing_add_url_should_format_request_properly() - { - Mocker.GetMock(MockBehavior.Strict) - .Setup( - s => - s.DownloadString( - "http://192.168.5.55:2222/api?mode=addid&name=6107863&priority=0&pp=3&cat=tv&nzbname=This+is+an+Nzb&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass")) - .Returns("ok"); - - //Act - bool result = Mocker.Resolve().AddByUrl( - "http://www.newzbin.com/browse/post/6107863/nzb", - "This is an Nzb"); - - //Assert - result.Should().BeTrue(); - } - - [Test] - public void add_by_url_should_detect_and_handle_sab_errors() - { - WithFailResponse(); - - //Act - var sabProvider = Mocker.Resolve(); - var result = sabProvider.AddByUrl("http://www.nzbclub.com/nzb_download.aspx?mid=1950232", "This is an nzb"); - - //Assert - Assert.IsFalse(result); - ExceptionVerification.ExpectedWarns(1); - } - - - [TestCase(1, new[] { 2 }, "My Episode Title", QualityTypes.DVD, false, "My Series Name - 1x2 - My Episode Title [DVD]")] - [TestCase(1, new[] { 2 }, "My Episode Title", QualityTypes.DVD, true, "My Series Name - 1x2 - My Episode Title [DVD] [Proper]")] - [TestCase(1, new[] { 2 }, "", QualityTypes.DVD, true, "My Series Name - 1x2 - [DVD] [Proper]")] - [TestCase(1, new[] { 2, 4 }, "My Episode Title", QualityTypes.HDTV, false, "My Series Name - 1x2-1x4 - My Episode Title [HDTV]")] - [TestCase(1, new[] { 2, 4 }, "My Episode Title", QualityTypes.HDTV, true, "My Series Name - 1x2-1x4 - My Episode Title [HDTV] [Proper]")] - [TestCase(1, new[] { 2, 4 }, "", QualityTypes.HDTV, true, "My Series Name - 1x2-1x4 - [HDTV] [Proper]")] - public void create_proper_sab_titles(int seasons, int[] episodes, string title, QualityTypes quality, - bool proper, string expected) - { - var series = Builder.CreateNew() - .With(c => c.Title = "My Series Name") - .Build(); - - var parsResult = new EpisodeParseResult() - { - AirDate = DateTime.Now, - EpisodeNumbers = episodes.ToList(), - Quality = new Quality(quality, proper), - SeasonNumber = seasons, - Series = series, - EpisodeTitle = title - }; - - //Act - var actual = Mocker.Resolve().GetSabTitle(parsResult); - - //Assert - Assert.AreEqual(expected, actual); - } - - [TestCase(true, "My Series Name - Season 1 [Bluray720p] [Proper]")] - [TestCase(false, "My Series Name - Season 1 [Bluray720p]")] - public void create_proper_sab_season_title(bool proper, string expected) - { - - - var series = Builder.CreateNew() - .With(c => c.Title = "My Series Name") - .Build(); - - var parsResult = new EpisodeParseResult() - { - AirDate = DateTime.Now, - Quality = new Quality(QualityTypes.Bluray720p, proper), - SeasonNumber = 1, - Series = series, - EpisodeTitle = "My Episode Title", - FullSeason = true - }; - - //Act - var actual = Mocker.Resolve().GetSabTitle(parsResult); - - //Assert - Assert.AreEqual(expected, actual); - } - - [TestCase(true, "My Series Name - 2011-12-01 - My Episode Title [Bluray720p] [Proper]")] - [TestCase(false, "My Series Name - 2011-12-01 - My Episode Title [Bluray720p]")] - public void create_proper_sab_daily_titles(bool proper, string expected) - { - var series = Builder.CreateNew() - .With(c => c.IsDaily = true) - .With(c => c.Title = "My Series Name") - .Build(); - - var parsResult = new EpisodeParseResult - { - AirDate = new DateTime(2011, 12, 1), - Quality = new Quality(QualityTypes.Bluray720p, proper), - Series = series, - EpisodeTitle = "My Episode Title", - }; - - //Act - var actual = Mocker.Resolve().GetSabTitle(parsResult); - - //Assert - Assert.AreEqual(expected, actual); - } - - [Test] - public void should_be_able_to_get_categories_when_config_is_passed_in() - { - //Setup - const string host = "192.168.5.55"; - const int port = 2222; - const string apikey = "5c770e3197e4fe763423ee7c392c25d1"; - const string username = "admin"; - const string password = "pass"; - - - - Mocker.GetMock(MockBehavior.Strict) - .Setup( - s => - s.DownloadString( - "http://192.168.5.55:2222/api?mode=get_cats&output=json&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass")) - .Returns(File.ReadAllText(@".\Files\Categories_json.txt")); - - //Act - var result = Mocker.Resolve().GetCategories(host, port, apikey, username, password); - - //Assert - result.Should().NotBeNull(); - result.categories.Should().HaveCount(c => c > 0); - } - - [Test] - public void should_be_able_to_get_categories_using_config() - { - Mocker.GetMock(MockBehavior.Strict) - .Setup( - s => - s.DownloadString( - "http://192.168.5.55:2222/api?mode=get_cats&output=json&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass")) - .Returns(File.ReadAllText(@".\Files\Categories_json.txt")); - - //Act - var result = Mocker.Resolve().GetCategories(); - - //Assert - result.Should().NotBeNull(); - result.categories.Should().HaveCount(c => c > 0); - } - - - [Test] - public void GetHistory_should_return_a_list_with_items_when_the_history_has_items() - { - Mocker.GetMock() - .Setup( - s => - s.DownloadString( - "http://192.168.5.55:2222/api?mode=history&output=json&start=0&limit=0&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass")) - .Returns(File.ReadAllText(@".\Files\History.txt")); - - //Act - var result = Mocker.Resolve().GetHistory(); - - //Assert - result.Should().HaveCount(1); - } - - [Test] - public void GetHistory_should_return_an_empty_list_when_the_queue_is_empty() - { - Mocker.GetMock() - .Setup( - s => - s.DownloadString( - "http://192.168.5.55:2222/api?mode=history&output=json&start=0&limit=0&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass")) - .Returns(File.ReadAllText(@".\Files\HistoryEmpty.txt")); - - //Act - var result = Mocker.Resolve().GetHistory(); - - //Assert - result.Should().BeEmpty(); - } - - [Test] - public void GetHistory_should_return_an_empty_list_when_there_is_an_error_getting_the_queue() - { - Mocker.GetMock() - .Setup( - s => - s.DownloadString( - "http://192.168.5.55:2222/api?mode=history&output=json&start=0&limit=0&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass")) - .Returns(File.ReadAllText(@".\Files\JsonError.txt")); - - //Act - Assert.Throws(() => Mocker.Resolve().GetHistory(), "API Key Incorrect"); - } - - } -} \ No newline at end of file diff --git a/NzbDrone.Core.Test/ProviderTests/SearchProviderTests/ProcessDailySearchResultsFixture.cs b/NzbDrone.Core.Test/ProviderTests/SearchProviderTests/ProcessDailySearchResultsFixture.cs index 145272620..404f8acd0 100644 --- a/NzbDrone.Core.Test/ProviderTests/SearchProviderTests/ProcessDailySearchResultsFixture.cs +++ b/NzbDrone.Core.Test/ProviderTests/SearchProviderTests/ProcessDailySearchResultsFixture.cs @@ -9,6 +9,7 @@ using NUnit.Framework; using NzbDrone.Core.Model; using NzbDrone.Core.Model.Notification; using NzbDrone.Core.Providers; +using NzbDrone.Core.Providers.DecisionEngine; using NzbDrone.Core.Providers.Indexer; using NzbDrone.Core.Repository; using NzbDrone.Core.Repository.Quality; @@ -74,15 +75,15 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests private void WithQualityNeeded() { - Mocker.GetMock() - .Setup(s => s.IsQualityNeeded(It.IsAny(), true)) + Mocker.GetMock() + .Setup(s => s.IsSatisfiedBy(It.IsAny())) .Returns(true); } private void WithQualityNotNeeded() { - Mocker.GetMock() - .Setup(s => s.IsQualityNeeded(It.IsAny(), true)) + Mocker.GetMock() + .Setup(s => s.IsSatisfiedBy(It.IsAny())) .Returns(false); } @@ -100,8 +101,8 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests WithMatchingSeries(); WithSuccessfulDownload(); - Mocker.GetMock() - .Setup(s => s.IsQualityNeeded(It.Is(d => d.Quality.QualityType == QualityTypes.Bluray1080p), true)) + Mocker.GetMock() + .Setup(s => s.IsSatisfiedBy(It.Is(d => d.Quality.QualityType == QualityTypes.Bluray1080p))) .Returns(true); //Act @@ -110,7 +111,7 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests //Assert result.Should().BeTrue(); - Mocker.GetMock().Verify(c => c.IsQualityNeeded(It.IsAny(), true), + Mocker.GetMock().Verify(c => c.IsSatisfiedBy(It.IsAny()), Times.Once()); Mocker.GetMock().Verify(c => c.DownloadReport(It.IsAny()), Times.Once()); @@ -134,7 +135,7 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests //Assert result.Should().BeFalse(); - Mocker.GetMock().Verify(c => c.IsQualityNeeded(It.IsAny(), true), + Mocker.GetMock().Verify(c => c.IsSatisfiedBy(It.IsAny()), Times.Exactly(5)); Mocker.GetMock().Verify(c => c.DownloadReport(It.IsAny()), Times.Never()); diff --git a/NzbDrone.Core.Test/ProviderTests/SearchProviderTests/ProcessSearchResultsFixture.cs b/NzbDrone.Core.Test/ProviderTests/SearchProviderTests/ProcessSearchResultsFixture.cs index 3ea7317c9..d44b18034 100644 --- a/NzbDrone.Core.Test/ProviderTests/SearchProviderTests/ProcessSearchResultsFixture.cs +++ b/NzbDrone.Core.Test/ProviderTests/SearchProviderTests/ProcessSearchResultsFixture.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using FizzWare.NBuilder; @@ -9,12 +8,10 @@ using NUnit.Framework; using NzbDrone.Core.Model; using NzbDrone.Core.Model.Notification; using NzbDrone.Core.Providers; -using NzbDrone.Core.Providers.Indexer; +using NzbDrone.Core.Providers.DecisionEngine; using NzbDrone.Core.Repository; using NzbDrone.Core.Repository.Quality; using NzbDrone.Core.Test.Framework; -using NzbDrone.Test.Common; -using NzbDrone.Test.Common.AutoMoq; namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests { @@ -74,15 +71,15 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests private void WithQualityNeeded() { - Mocker.GetMock() - .Setup(s => s.IsQualityNeeded(It.IsAny(), true)) + Mocker.GetMock() + .Setup(s => s.IsSatisfiedBy(It.IsAny())) .Returns(true); } private void WithQualityNotNeeded() { - Mocker.GetMock() - .Setup(s => s.IsQualityNeeded(It.IsAny(), true)) + Mocker.GetMock() + .Setup(s => s.IsSatisfiedBy(It.IsAny())) .Returns(false); } @@ -101,8 +98,8 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests WithMatchingSeries(); WithSuccessfulDownload(); - Mocker.GetMock() - .Setup(s => s.IsQualityNeeded(It.Is(d => d.Quality.QualityType == QualityTypes.Bluray1080p), true)) + Mocker.GetMock() + .Setup(s => s.IsSatisfiedBy(It.Is(d => d.Quality.QualityType == QualityTypes.Bluray1080p))) .Returns(true); //Act @@ -112,7 +109,7 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests result.Should().HaveCount(1); result.First().Should().Be(1); - Mocker.GetMock().Verify(c => c.IsQualityNeeded(It.IsAny(), true), + Mocker.GetMock().Verify(c => c.IsSatisfiedBy(It.IsAny()), Times.Once()); Mocker.GetMock().Verify(c => c.DownloadReport(It.IsAny()), Times.Once()); @@ -137,7 +134,7 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests //Assert result.Should().HaveCount(0); - Mocker.GetMock().Verify(c => c.IsQualityNeeded(It.IsAny(), true), + Mocker.GetMock().Verify(c => c.IsSatisfiedBy(It.IsAny()), Times.Exactly(5)); Mocker.GetMock().Verify(c => c.DownloadReport(It.IsAny()), Times.Never()); diff --git a/NzbDrone.Core.Test/ProviderTests/SearchProviderTests/SearchFixture.cs b/NzbDrone.Core.Test/ProviderTests/SearchProviderTests/SearchFixture.cs index a1278cce0..3fcac983a 100644 --- a/NzbDrone.Core.Test/ProviderTests/SearchProviderTests/SearchFixture.cs +++ b/NzbDrone.Core.Test/ProviderTests/SearchProviderTests/SearchFixture.cs @@ -7,6 +7,7 @@ using Moq; using NUnit.Framework; using NzbDrone.Core.Model; using NzbDrone.Core.Providers; +using NzbDrone.Core.Providers.DecisionEngine; using NzbDrone.Core.Providers.Indexer; using NzbDrone.Core.Repository; using NzbDrone.Core.Test.Framework; @@ -192,7 +193,7 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests episode.AirDate = null; episode.Series = _series; - Mocker.GetMock().Setup(s => s.IsUpgradePossible(It.IsAny())) + Mocker.GetMock().Setup(s => s.IsSatisfiedBy(It.IsAny())) .Returns(true); Mocker.GetMock().Setup(s => s.GetEpisode(episode.EpisodeId)) diff --git a/NzbDrone.Core/Datastore/CustomeMapper.cs b/NzbDrone.Core/Datastore/CustomeMapper.cs index 74b322450..e31a7625b 100644 --- a/NzbDrone.Core/Datastore/CustomeMapper.cs +++ b/NzbDrone.Core/Datastore/CustomeMapper.cs @@ -40,9 +40,11 @@ namespace NzbDrone.Core.Datastore //if (propertyInfo == null) // return null; + if (propertyInfo == null) return base.GetFromDbConverter(propertyInfo, sourceType); + return GetFromDbConverter(propertyInfo.PropertyType, sourceType); } } - + } \ No newline at end of file diff --git a/NzbDrone.Core/Jobs/RssSyncJob.cs b/NzbDrone.Core/Jobs/RssSyncJob.cs index 600e825cb..630cda65e 100644 --- a/NzbDrone.Core/Jobs/RssSyncJob.cs +++ b/NzbDrone.Core/Jobs/RssSyncJob.cs @@ -6,6 +6,7 @@ using NLog; using NzbDrone.Core.Model; using NzbDrone.Core.Model.Notification; using NzbDrone.Core.Providers; +using NzbDrone.Core.Providers.DecisionEngine; using NzbDrone.Core.Providers.Indexer; namespace NzbDrone.Core.Jobs @@ -13,20 +14,25 @@ namespace NzbDrone.Core.Jobs public class RssSyncJob : IJob { private readonly IEnumerable _indexers; - private readonly InventoryProvider _inventoryProvider; private readonly DownloadProvider _downloadProvider; private readonly IndexerProvider _indexerProvider; + private readonly MonitoredEpisodeSpecification _isMonitoredEpisodeSpecification; + private readonly AllowedDownloadSpecification _allowedDownloadSpecification; + private readonly UpgradeHistorySpecification _upgradeHistorySpecification; private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); [Inject] - public RssSyncJob(IEnumerable indexers, InventoryProvider inventoryProvider, DownloadProvider downloadProvider, IndexerProvider indexerProvider) + public RssSyncJob(IEnumerable indexers, DownloadProvider downloadProvider, IndexerProvider indexerProvider, + MonitoredEpisodeSpecification isMonitoredEpisodeSpecification, AllowedDownloadSpecification allowedDownloadSpecification, UpgradeHistorySpecification upgradeHistorySpecification) { _indexers = indexers; - _inventoryProvider = inventoryProvider; _downloadProvider = downloadProvider; _indexerProvider = indexerProvider; + _isMonitoredEpisodeSpecification = isMonitoredEpisodeSpecification; + _allowedDownloadSpecification = allowedDownloadSpecification; + _upgradeHistorySpecification = upgradeHistorySpecification; } public string Name @@ -63,7 +69,9 @@ namespace NzbDrone.Core.Jobs { try { - if (_inventoryProvider.IsMonitored(episodeParseResult) && _inventoryProvider.IsQualityNeeded(episodeParseResult)) + if (_isMonitoredEpisodeSpecification.IsSatisfiedBy(episodeParseResult) && + _allowedDownloadSpecification.IsSatisfiedBy(episodeParseResult) && + _upgradeHistorySpecification.IsSatisfiedBy(episodeParseResult)) { _downloadProvider.DownloadReport(episodeParseResult); } diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index ea6f4b02c..9eb9c246e 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -136,6 +136,7 @@ ..\packages\DotNetZip.1.9.1.8\lib\net20\Ionic.Zip.dll + True ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll @@ -259,9 +260,19 @@ - + + + + + + + + + + + @@ -298,7 +309,6 @@ - @@ -343,7 +353,7 @@ - + diff --git a/NzbDrone.Core/Providers/BackupProvider.cs b/NzbDrone.Core/Providers/BackupProvider.cs index 17694437b..08c3a08fb 100644 --- a/NzbDrone.Core/Providers/BackupProvider.cs +++ b/NzbDrone.Core/Providers/BackupProvider.cs @@ -1,8 +1,5 @@ using System; -using System.Collections.Generic; -using System.IO; using System.Linq; -using System.Text; using Ionic.Zip; using NLog; using Ninject; diff --git a/NzbDrone.Core/Providers/BlackholeProvider.cs b/NzbDrone.Core/Providers/BlackholeProvider.cs deleted file mode 100644 index 11bca5755..000000000 --- a/NzbDrone.Core/Providers/BlackholeProvider.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using NLog; -using Ninject; -using NzbDrone.Common; -using NzbDrone.Core.Model; -using NzbDrone.Core.Providers.Core; - -namespace NzbDrone.Core.Providers -{ - public class BlackholeProvider - { - private readonly ConfigProvider _configProvider; - private readonly HttpProvider _httpProvider; - private readonly DiskProvider _diskProvider; - - private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - - [Inject] - public BlackholeProvider(ConfigProvider configProvider, HttpProvider httpProvider, - DiskProvider diskProvider) - { - _configProvider = configProvider; - _httpProvider = httpProvider; - _diskProvider = diskProvider; - } - - public BlackholeProvider() - { - } - - public virtual bool DownloadNzb(EpisodeParseResult parseResult, string title) - { - try - { - var filename = Path.Combine(_configProvider.BlackholeDirectory, title, ".nzb"); - - if(_diskProvider.FileExists(filename)) - { - //Return true so a lesser quality is not returned. - Logger.Info("NZB already exists on disk: {0)", filename); - return true; - } - - Logger.Trace("Downloading NZB from: {0} to: {1}", parseResult.NzbUrl, filename); - _httpProvider.DownloadFile(parseResult.NzbUrl, filename); - - Logger.Trace("NZB Download succeeded, saved to: {0}", filename); - return true; - } - catch(Exception ex) - { - Logger.WarnException("Failed to download NZB: " + parseResult.NzbUrl, ex); - return false; - } - } - } -} diff --git a/NzbDrone.Core/Providers/DecisionEngine/AcceptableSizeSpecification.cs b/NzbDrone.Core/Providers/DecisionEngine/AcceptableSizeSpecification.cs new file mode 100644 index 000000000..2c5d5bdcd --- /dev/null +++ b/NzbDrone.Core/Providers/DecisionEngine/AcceptableSizeSpecification.cs @@ -0,0 +1,66 @@ +using System.Linq; +using NLog; +using Ninject; +using NzbDrone.Core.Model; + +namespace NzbDrone.Core.Providers.DecisionEngine +{ + public class AcceptableSizeSpecification + { + private readonly QualityTypeProvider _qualityTypeProvider; + private readonly EpisodeProvider _episodeProvider; + private static readonly Logger logger = LogManager.GetCurrentClassLogger(); + + [Inject] + public AcceptableSizeSpecification(QualityTypeProvider qualityTypeProvider, EpisodeProvider episodeProvider) + { + _qualityTypeProvider = qualityTypeProvider; + _episodeProvider = episodeProvider; + } + + public AcceptableSizeSpecification() + { + + } + + public virtual bool IsSatisfiedBy(EpisodeParseResult subject) + { + var qualityType = _qualityTypeProvider.Get((int)subject.Quality.QualityType); + + //Need to determine if this is a 30 or 60 minute episode + //Is it a multi-episode release? + //Is it the first or last series of a season? + + //0 will be treated as unlimited + if (qualityType.MaxSize == 0) + return true; + + var maxSize = qualityType.MaxSize.Megabytes(); + var series = subject.Series; + + //Multiply maxSize by Series.Runtime + maxSize = maxSize * series.Runtime; + + //Multiply maxSize by the number of episodes parsed (if EpisodeNumbers is null it will be treated as a single episode) + //TODO: is this check really necessary? shouldn't we blowup? + if (subject.EpisodeNumbers != null) + maxSize = maxSize * subject.EpisodeNumbers.Count; + + //Check if there was only one episode parsed + //and it is the first or last episode of the season + if (subject.EpisodeNumbers != null && subject.EpisodeNumbers.Count == 1 && + _episodeProvider.IsFirstOrLastEpisodeOfSeason(series.SeriesId, + subject.SeasonNumber, subject.EpisodeNumbers[0])) + { + maxSize = maxSize * 2; + } + + //If the parsed size is greater than maxSize we don't want it + if (subject.Size > maxSize) + return false; + + return true; + } + + } +} diff --git a/NzbDrone.Core/Providers/DecisionEngine/AllowedDownloadSpecification.cs b/NzbDrone.Core/Providers/DecisionEngine/AllowedDownloadSpecification.cs new file mode 100644 index 000000000..6422cbd14 --- /dev/null +++ b/NzbDrone.Core/Providers/DecisionEngine/AllowedDownloadSpecification.cs @@ -0,0 +1,42 @@ +using System.Linq; +using NLog; +using Ninject; +using NzbDrone.Core.Model; + +namespace NzbDrone.Core.Providers.DecisionEngine +{ + public class AllowedDownloadSpecification + { + private readonly QualityAllowedByProfileSpecification _qualityAllowedByProfileSpecification; + private readonly UpgradeDiskSpecification _upgradeDiskSpecification; + private readonly AcceptableSizeSpecification _acceptableSizeSpecification; + private readonly AlreadyInQueueSpecification _alreadyInQueueSpecification; + private static readonly Logger logger = LogManager.GetCurrentClassLogger(); + + [Inject] + public AllowedDownloadSpecification(QualityAllowedByProfileSpecification qualityAllowedByProfileSpecification, + UpgradeDiskSpecification upgradeDiskSpecification, AcceptableSizeSpecification acceptableSizeSpecification, + AlreadyInQueueSpecification alreadyInQueueSpecification) + { + _qualityAllowedByProfileSpecification = qualityAllowedByProfileSpecification; + _upgradeDiskSpecification = upgradeDiskSpecification; + _acceptableSizeSpecification = acceptableSizeSpecification; + _alreadyInQueueSpecification = alreadyInQueueSpecification; + } + + public AllowedDownloadSpecification() + { + } + + public virtual bool IsSatisfiedBy(EpisodeParseResult subject) + { + if (!_qualityAllowedByProfileSpecification.IsSatisfiedBy(subject)) return false; + if (!_upgradeDiskSpecification.IsSatisfiedBy(subject)) return false; + if (!_acceptableSizeSpecification.IsSatisfiedBy(subject)) return false; + if (_alreadyInQueueSpecification.IsSatisfiedBy(subject)) return false; + + logger.Debug("Episode {0} is needed", subject); + return true; + } + } +} \ No newline at end of file diff --git a/NzbDrone.Core/Providers/DecisionEngine/AlreadyInQueueSpecification.cs b/NzbDrone.Core/Providers/DecisionEngine/AlreadyInQueueSpecification.cs new file mode 100644 index 000000000..02f5a7986 --- /dev/null +++ b/NzbDrone.Core/Providers/DecisionEngine/AlreadyInQueueSpecification.cs @@ -0,0 +1,32 @@ +using System.Linq; +using NLog; +using Ninject; +using NzbDrone.Core.Model; + +namespace NzbDrone.Core.Providers.DecisionEngine +{ + public class AlreadyInQueueSpecification + { + private readonly DownloadProvider _downloadProvider; + + private static readonly Logger logger = LogManager.GetCurrentClassLogger(); + + [Inject] + public AlreadyInQueueSpecification(DownloadProvider downloadProvider) + { + _downloadProvider = downloadProvider; + + } + + public AlreadyInQueueSpecification() + { + + } + + public virtual bool IsSatisfiedBy(EpisodeParseResult subject) + { + return _downloadProvider.GetActiveDownloadClient().IsInQueue(subject); + } + + } +} diff --git a/NzbDrone.Core/Providers/DecisionEngine/MonitoredEpisodeSpecification.cs b/NzbDrone.Core/Providers/DecisionEngine/MonitoredEpisodeSpecification.cs new file mode 100644 index 000000000..713b556e3 --- /dev/null +++ b/NzbDrone.Core/Providers/DecisionEngine/MonitoredEpisodeSpecification.cs @@ -0,0 +1,56 @@ +using System.Linq; +using NLog; +using Ninject; +using NzbDrone.Core.Model; + +namespace NzbDrone.Core.Providers.DecisionEngine +{ + public class MonitoredEpisodeSpecification + { + private readonly SeriesProvider _seriesProvider; + private readonly EpisodeProvider _episodeProvider; + private static readonly Logger logger = LogManager.GetCurrentClassLogger(); + + [Inject] + public MonitoredEpisodeSpecification(SeriesProvider seriesProvider, EpisodeProvider episodeProvider) + { + _seriesProvider = seriesProvider; + _episodeProvider = episodeProvider; + } + + public MonitoredEpisodeSpecification() + { + + } + + public virtual bool IsSatisfiedBy(EpisodeParseResult subject) + { + var series = _seriesProvider.FindSeries(subject.CleanTitle); + + if (series == null) + { + logger.Trace("{0} is not mapped to any series in DB. skipping", subject.CleanTitle); + return false; + } + + subject.Series = series; + + if (!series.Monitored) + { + logger.Debug("{0} is present in the DB but not tracked. skipping.", subject.CleanTitle); + return false; + } + + var episodes = _episodeProvider.GetEpisodesByParseResult(subject); + + //return monitored if any of the episodes are monitored + if (episodes.Any(episode => !episode.Ignored)) + { + return true; + } + + logger.Debug("All episodes are ignored. skipping."); + return false; + } + } +} diff --git a/NzbDrone.Core/Providers/DecisionEngine/QualityAllowedByProfileSpecification.cs b/NzbDrone.Core/Providers/DecisionEngine/QualityAllowedByProfileSpecification.cs new file mode 100644 index 000000000..f578a710c --- /dev/null +++ b/NzbDrone.Core/Providers/DecisionEngine/QualityAllowedByProfileSpecification.cs @@ -0,0 +1,35 @@ +using System.Linq; +using NLog; +using NzbDrone.Core.Model; +using NzbDrone.Core.Repository.Quality; + +namespace NzbDrone.Core.Providers.DecisionEngine +{ + public class QualityUpgradeSpecification + { + private static readonly Logger logger = LogManager.GetCurrentClassLogger(); + + public virtual bool IsSatisfiedBy(Quality currentQuality, Quality newQuality, QualityTypes cutOff) + { + if (currentQuality >= newQuality) + { + logger.Trace("existing item has better or equal quality. skipping"); + return false; + } + + if (currentQuality.QualityType == newQuality.QualityType && newQuality.Proper) + { + logger.Trace("Upgrading existing item to proper."); + return true; + } + + if (currentQuality.QualityType >= cutOff) + { + logger.Trace("Existing item meets cut-off. skipping."); + return false; + } + + return true; + } + } +} diff --git a/NzbDrone.Core/Providers/DecisionEngine/QualityUpgradeSpecification.cs b/NzbDrone.Core/Providers/DecisionEngine/QualityUpgradeSpecification.cs new file mode 100644 index 000000000..db32aa20a --- /dev/null +++ b/NzbDrone.Core/Providers/DecisionEngine/QualityUpgradeSpecification.cs @@ -0,0 +1,23 @@ +using System.Linq; +using NLog; +using NzbDrone.Core.Model; + +namespace NzbDrone.Core.Providers.DecisionEngine +{ + public class QualityAllowedByProfileSpecification + { + private static readonly Logger logger = LogManager.GetCurrentClassLogger(); + + public virtual bool IsSatisfiedBy(EpisodeParseResult subject) + { + logger.Trace("Checking if report meets quality requirements. {0}", subject.Quality); + if (!subject.Series.QualityProfile.Allowed.Contains(subject.Quality.QualityType)) + { + logger.Trace("Quality {0} rejected by Series' quality profile", subject.Quality); + return false; + } + + return true; + } + } +} diff --git a/NzbDrone.Core/Providers/DecisionEngine/UpgradeDiskSpecification.cs b/NzbDrone.Core/Providers/DecisionEngine/UpgradeDiskSpecification.cs new file mode 100644 index 000000000..ee9a500e0 --- /dev/null +++ b/NzbDrone.Core/Providers/DecisionEngine/UpgradeDiskSpecification.cs @@ -0,0 +1,37 @@ +using System.Linq; +using NLog; +using Ninject; +using NzbDrone.Core.Model; + +namespace NzbDrone.Core.Providers.DecisionEngine +{ + public class UpgradeDiskSpecification + { + private readonly EpisodeProvider _episodeProvider; + private readonly QualityUpgradeSpecification _qualityUpgradeSpecification; + private static readonly Logger logger = LogManager.GetCurrentClassLogger(); + + [Inject] + public UpgradeDiskSpecification(EpisodeProvider episodeProvider, QualityUpgradeSpecification qualityUpgradeSpecification) + { + _episodeProvider = episodeProvider; + _qualityUpgradeSpecification = qualityUpgradeSpecification; + } + + public UpgradeDiskSpecification() + { + } + + public virtual bool IsSatisfiedBy(EpisodeParseResult subject) + { + foreach (var file in _episodeProvider.GetEpisodesByParseResult(subject).Select(c => c.EpisodeFile).Where(c => c != null)) + { + logger.Trace("Comparing file quality with report. Existing file is {0} proper:{1}", file.Quality, file.Proper); + if (!_qualityUpgradeSpecification.IsSatisfiedBy(new Quality { QualityType = file.Quality, Proper = file.Proper }, subject.Quality, subject.Series.QualityProfile.Cutoff)) + return false; + } + + return true; + } + } +} diff --git a/NzbDrone.Core/Providers/DecisionEngine/UpgradeHistorySpecification.cs b/NzbDrone.Core/Providers/DecisionEngine/UpgradeHistorySpecification.cs new file mode 100644 index 000000000..86c61c586 --- /dev/null +++ b/NzbDrone.Core/Providers/DecisionEngine/UpgradeHistorySpecification.cs @@ -0,0 +1,44 @@ +using System.Linq; +using NLog; +using Ninject; +using NzbDrone.Core.Model; + +namespace NzbDrone.Core.Providers.DecisionEngine +{ + public class UpgradeHistorySpecification + { + private readonly EpisodeProvider _episodeProvider; + private readonly HistoryProvider _historyProvider; + private readonly QualityUpgradeSpecification _qualityUpgradeSpecification; + private static readonly Logger logger = LogManager.GetCurrentClassLogger(); + + [Inject] + public UpgradeHistorySpecification(EpisodeProvider episodeProvider, HistoryProvider historyProvider, QualityUpgradeSpecification qualityUpgradeSpecification) + { + _episodeProvider = episodeProvider; + _historyProvider = historyProvider; + _qualityUpgradeSpecification = qualityUpgradeSpecification; + } + + public UpgradeHistorySpecification() + { + + } + + public virtual bool IsSatisfiedBy(EpisodeParseResult subject) + { + foreach (var episode in _episodeProvider.GetEpisodesByParseResult(subject)) + { + var bestQualityInHistory = _historyProvider.GetBestQualityInHistory(subject.Series.SeriesId, episode.SeasonNumber, episode.EpisodeNumber); + if (bestQualityInHistory != null) + { + logger.Trace("Comparing history quality with report. History is {0}", bestQualityInHistory); + if (!_qualityUpgradeSpecification.IsSatisfiedBy(bestQualityInHistory, subject.Quality, subject.Series.QualityProfile.Cutoff)) + return false; + } + } + + return true; + } + } +} diff --git a/NzbDrone.Core/Providers/DecisionEngine/UpgradePossibleSpecification.cs b/NzbDrone.Core/Providers/DecisionEngine/UpgradePossibleSpecification.cs new file mode 100644 index 000000000..1f5a90e01 --- /dev/null +++ b/NzbDrone.Core/Providers/DecisionEngine/UpgradePossibleSpecification.cs @@ -0,0 +1,40 @@ +using System.Linq; +using NLog; +using Ninject; +using NzbDrone.Core.Repository; + +namespace NzbDrone.Core.Providers.DecisionEngine +{ + public class UpgradePossibleSpecification + { + private readonly QualityProvider _qualityProvider; + private static readonly Logger logger = LogManager.GetCurrentClassLogger(); + + [Inject] + public UpgradePossibleSpecification(QualityProvider qualityProvider) + { + _qualityProvider = qualityProvider; + } + + public UpgradePossibleSpecification() + { + + } + + public virtual bool IsSatisfiedBy(Episode subject) + { + //Used to check if the existing episode can be upgraded by searching (Before we search) + if (subject.EpisodeFileId == 0) + return true; + + var profile = _qualityProvider.Get(subject.Series.QualityProfileId); + + + //TODO:How about proper? + if (subject.EpisodeFile.Quality >= profile.Cutoff) + return false; + + return true; ; + } + } +} diff --git a/NzbDrone.Core/Providers/DiskScanProvider.cs b/NzbDrone.Core/Providers/DiskScanProvider.cs index 9265dbb3e..1ef1677d8 100644 --- a/NzbDrone.Core/Providers/DiskScanProvider.cs +++ b/NzbDrone.Core/Providers/DiskScanProvider.cs @@ -13,25 +13,25 @@ namespace NzbDrone.Core.Providers public class DiskScanProvider { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - private static readonly string[] MediaExtentions = new[] { ".mkv", ".avi", ".wmv", ".mp4", ".mpg", ".mpeg", ".xvid", ".flv", ".mov", ".rm", ".rmvb", ".divx", ".dvr-ms", ".ts", ".ogm" }; + private static readonly string[] mediaExtentions = new[] { ".mkv", ".avi", ".wmv", ".mp4", ".mpg", ".mpeg", ".xvid", ".flv", ".mov", ".rm", ".rmvb", ".divx", ".dvr-ms", ".ts", ".ogm" }; private readonly DiskProvider _diskProvider; private readonly EpisodeProvider _episodeProvider; private readonly MediaFileProvider _mediaFileProvider; private readonly SeriesProvider _seriesProvider; private readonly ExternalNotificationProvider _externalNotificationProvider; - private readonly SabProvider _sabProvider; + private readonly DownloadProvider _downloadProvider; [Inject] public DiskScanProvider(DiskProvider diskProvider, EpisodeProvider episodeProvider, SeriesProvider seriesProvider, MediaFileProvider mediaFileProvider, - ExternalNotificationProvider externalNotificationProvider, SabProvider sabProvider) + ExternalNotificationProvider externalNotificationProvider, DownloadProvider downloadProvider) { _diskProvider = diskProvider; _episodeProvider = episodeProvider; _seriesProvider = seriesProvider; _mediaFileProvider = mediaFileProvider; _externalNotificationProvider = externalNotificationProvider; - _sabProvider = sabProvider; + _downloadProvider = downloadProvider; } public DiskScanProvider() @@ -192,7 +192,7 @@ namespace NzbDrone.Core.Providers var parseResult = Parser.ParsePath(episodeFile.Path); parseResult.Series = series; - var message = _sabProvider.GetSabTitle(parseResult); + var message = _downloadProvider.GetDownloadTitle(parseResult); if (newDownload) { @@ -251,7 +251,7 @@ namespace NzbDrone.Core.Providers var filesOnDisk = _diskProvider.GetFiles(path, SearchOption.AllDirectories); - var mediaFileList = filesOnDisk.Where(c => MediaExtentions.Contains(Path.GetExtension(c).ToLower())).ToList(); + var mediaFileList = filesOnDisk.Where(c => mediaExtentions.Contains(Path.GetExtension(c).ToLower())).ToList(); Logger.Trace("{0} video files were found in {1}", mediaFileList.Count, path); return mediaFileList; diff --git a/NzbDrone.Core/Providers/DownloadClients/BlackholeProvider.cs b/NzbDrone.Core/Providers/DownloadClients/BlackholeProvider.cs new file mode 100644 index 000000000..6d0991b99 --- /dev/null +++ b/NzbDrone.Core/Providers/DownloadClients/BlackholeProvider.cs @@ -0,0 +1,70 @@ +using System; +using System.IO; +using System.Linq; +using NLog; +using Ninject; +using NzbDrone.Common; +using NzbDrone.Core.Model; +using NzbDrone.Core.Providers.Core; +using NzbDrone.Core.Providers.DecisionEngine; + +namespace NzbDrone.Core.Providers.DownloadClients +{ + public class BlackholeProvider : IDownloadClient + { + private readonly ConfigProvider _configProvider; + private readonly HttpProvider _httpProvider; + private readonly DiskProvider _diskProvider; + private readonly UpgradeHistorySpecification _upgradeHistorySpecification; + private readonly HistoryProvider _historyProvider; + + private static readonly Logger logger = LogManager.GetCurrentClassLogger(); + + [Inject] + public BlackholeProvider(ConfigProvider configProvider, HttpProvider httpProvider, + DiskProvider diskProvider, UpgradeHistorySpecification upgradeHistorySpecification) + { + _configProvider = configProvider; + _httpProvider = httpProvider; + _diskProvider = diskProvider; + _upgradeHistorySpecification = upgradeHistorySpecification; + } + + public BlackholeProvider() + { + } + + public virtual bool DownloadNzb(string url, string title) + { + try + { + var filename = Path.Combine(_configProvider.BlackholeDirectory, title + ".nzb"); + + if (_diskProvider.FileExists(filename)) + { + //Return true so a lesser quality is not returned. + logger.Info("NZB already exists on disk: {0)", filename); + return true; + } + + logger.Trace("Downloading NZB from: {0} to: {1}", url, filename); + _httpProvider.DownloadFile(url, filename); + + logger.Trace("NZB Download succeeded, saved to: {0}", filename); + return true; + } + catch (Exception ex) + { + logger.WarnException("Failed to download NZB: " + url, ex); + return false; + } + } + + public virtual bool IsInQueue(EpisodeParseResult newParseResult) + { + return !_upgradeHistorySpecification.IsSatisfiedBy(newParseResult); + } + + + } +} diff --git a/NzbDrone.Core/Providers/DownloadClients/IDownloadClient.cs b/NzbDrone.Core/Providers/DownloadClients/IDownloadClient.cs new file mode 100644 index 000000000..1ea0d603d --- /dev/null +++ b/NzbDrone.Core/Providers/DownloadClients/IDownloadClient.cs @@ -0,0 +1,11 @@ +using System.Linq; +using NzbDrone.Core.Model; + +namespace NzbDrone.Core.Providers.DownloadClients +{ + public interface IDownloadClient + { + bool IsInQueue(EpisodeParseResult newParseResult); + bool DownloadNzb(string url, string title); + } +} diff --git a/NzbDrone.Core/Providers/SabProvider.cs b/NzbDrone.Core/Providers/DownloadClients/SabProvider.cs similarity index 72% rename from NzbDrone.Core/Providers/SabProvider.cs rename to NzbDrone.Core/Providers/DownloadClients/SabProvider.cs index 0abc378fb..023f3bbb0 100644 --- a/NzbDrone.Core/Providers/SabProvider.cs +++ b/NzbDrone.Core/Providers/DownloadClients/SabProvider.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; using System.Web; -using System.Xml.Linq; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Ninject; @@ -12,18 +11,14 @@ using NzbDrone.Core.Model; using NzbDrone.Core.Model.Sabnzbd; using NzbDrone.Core.Providers.Core; -namespace NzbDrone.Core.Providers +namespace NzbDrone.Core.Providers.DownloadClients { - public class SabProvider + public class SabProvider : IDownloadClient { - private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + private static readonly Logger logger = LogManager.GetCurrentClassLogger(); private readonly ConfigProvider _configProvider; private readonly HttpProvider _httpProvider; - public SabProvider() - { - } - [Inject] public SabProvider(ConfigProvider configProvider, HttpProvider httpProvider) { @@ -31,34 +26,9 @@ namespace NzbDrone.Core.Providers _httpProvider = httpProvider; } - public virtual bool AddByUrl(string url, string title) - { - string cat = _configProvider.SabTvCategory; - int priority = (int)_configProvider.SabTvPriority; - string name = GetNzbName(url); - string nzbName = HttpUtility.UrlEncode(title); - - string action = string.Format("mode=addurl&name={0}&priority={1}&pp=3&cat={2}&nzbname={3}", - name, priority, cat, nzbName); - - if (url.ToLower().Contains("newzbin")) - { - action = action.Replace("mode=addurl", "mode=addid"); - } - - string request = GetSabRequest(action); - - Logger.Info("Adding report [{0}] to the queue.", title); - string response = _httpProvider.DownloadString(request).Replace("\n", String.Empty); - Logger.Debug("Queue Response: [{0}]", response); - - if (response == "ok") - return true; - - Logger.Warn("SAB returned unexpected response '{0}'", response); - - return false; + public SabProvider() + { } private static string GetNzbName(string urlString) @@ -97,6 +67,36 @@ namespace NzbDrone.Core.Providers return matchingSeason.Any(q => q.ParseResult.EpisodeNumbers != null && q.ParseResult.EpisodeNumbers.Any(e => newParseResult.EpisodeNumbers.Contains(e))); } + public virtual bool DownloadNzb(string url, string title) + { + string cat = _configProvider.SabTvCategory; + int priority = (int)_configProvider.SabTvPriority; + string name = GetNzbName(url); + string nzbName = HttpUtility.UrlEncode(title); + + string action = string.Format("mode=addurl&name={0}&priority={1}&pp=3&cat={2}&nzbname={3}", + name, priority, cat, nzbName); + + if (url.ToLower().Contains("newzbin")) + { + action = action.Replace("mode=addurl", "mode=addid"); + } + + string request = GetSabRequest(action); + + logger.Info("Adding report [{0}] to the queue.", title); + + string response = _httpProvider.DownloadString(request).Replace("\n", String.Empty); + logger.Debug("Queue Response: [{0}]", response); + + if (response == "ok") + return true; + + logger.Warn("SAB returned unexpected response '{0}'", response); + + return false; + } + public virtual List GetQueue(int start = 0, int limit = 0) { string action = String.Format("mode=queue&output=json&start={0}&limit={1}", start, limit); @@ -120,56 +120,6 @@ namespace NzbDrone.Core.Providers return items ?? new List(); } - public virtual String GetSabTitle(EpisodeParseResult parseResult) - { - //Handle Full Naming - if (parseResult.FullSeason) - { - var seasonResult = String.Format("{0} - Season {1} [{2}]", GetSabSeriesName(parseResult), - parseResult.SeasonNumber, parseResult.Quality.QualityType); - - if (parseResult.Quality.Proper) - seasonResult += " [Proper]"; - - return seasonResult; - } - - if (parseResult.Series.IsDaily) - { - var dailyResult = String.Format("{0} - {1:yyyy-MM-dd} - {2} [{3}]", GetSabSeriesName(parseResult), - parseResult.AirDate, parseResult.EpisodeTitle, parseResult.Quality.QualityType); - - if (parseResult.Quality.Proper) - dailyResult += " [Proper]"; - - return dailyResult; - } - - //Show Name - 1x01-1x02 - Episode Name - //Show Name - 1x01 - Episode Name - var episodeString = new List(); - - foreach (var episode in parseResult.EpisodeNumbers) - { - episodeString.Add(String.Format("{0}x{1}", parseResult.SeasonNumber, episode)); - } - - var epNumberString = String.Join("-", episodeString); - - var result = String.Format("{0} - {1} - {2} [{3}]", GetSabSeriesName(parseResult), epNumberString, parseResult.EpisodeTitle, parseResult.Quality.QualityType); - - if (parseResult.Quality.Proper) - { - result += " [Proper]"; - } - - return result; - } - - private static string GetSabSeriesName(EpisodeParseResult parseResult) - { - return MediaFileProvider.CleanFilename(parseResult.Series.Title); - } public virtual SabCategoryModel GetCategories(string host = null, int port = 0, string apiKey = null, string username = null, string password = null) { diff --git a/NzbDrone.Core/Providers/DownloadProvider.cs b/NzbDrone.Core/Providers/DownloadProvider.cs index 07966ae3f..4912b4640 100644 --- a/NzbDrone.Core/Providers/DownloadProvider.cs +++ b/NzbDrone.Core/Providers/DownloadProvider.cs @@ -1,8 +1,10 @@ using System; +using System.Collections.Generic; using Ninject; using NLog; using NzbDrone.Core.Model; using NzbDrone.Core.Providers.Core; +using NzbDrone.Core.Providers.DownloadClients; using NzbDrone.Core.Repository; namespace NzbDrone.Core.Providers @@ -16,7 +18,7 @@ namespace NzbDrone.Core.Providers private readonly ConfigProvider _configProvider; private readonly BlackholeProvider _blackholeProvider; - private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + private static readonly Logger logger = LogManager.GetCurrentClassLogger(); [Inject] public DownloadProvider(SabProvider sabProvider, HistoryProvider historyProvider, @@ -37,26 +39,16 @@ namespace NzbDrone.Core.Providers public virtual bool DownloadReport(EpisodeParseResult parseResult) { - var sabTitle = _sabProvider.GetSabTitle(parseResult); - bool addSuccess = false; + var downloadTitle = GetDownloadTitle(parseResult); - if (_configProvider.DownloadClient == DownloadClientType.Blackhole) - addSuccess = _blackholeProvider.DownloadNzb(parseResult, sabTitle); + var provider = GetActiveDownloadClient(); - if (_configProvider.DownloadClient == DownloadClientType.Sabnzbd) - { - if(_sabProvider.IsInQueue(parseResult)) - { - Logger.Warn("Episode {0} is already in sab's queue. skipping.", parseResult); - return false; - } - - addSuccess = _sabProvider.AddByUrl(parseResult.NzbUrl, sabTitle); - } + bool success = provider.DownloadNzb(parseResult.NzbUrl, GetDownloadTitle(parseResult)); - if (addSuccess) + if (success) { - Logger.Trace("Download added to Queue: {0}", sabTitle); + logger.Trace("Download added to Queue: {0}", downloadTitle); + foreach (var episode in _episodeProvider.GetEpisodesByParseResult(parseResult)) { @@ -72,11 +64,74 @@ namespace NzbDrone.Core.Providers _historyProvider.Add(history); _episodeProvider.MarkEpisodeAsFetched(episode.EpisodeId); } + + _externalNotificationProvider.OnGrab(downloadTitle); + } + + return success; + } + + + public virtual IDownloadClient GetActiveDownloadClient() + { + switch (_configProvider.DownloadClient) + { + case DownloadClientType.Blackhole: + return _blackholeProvider; + default: + return _sabProvider; + } + } + + + public virtual String GetDownloadTitle(EpisodeParseResult parseResult) + { + + var seriesTitle = MediaFileProvider.CleanFilename(parseResult.Series.Title); + + + //Handle Full Naming + if (parseResult.FullSeason) + { + var seasonResult = String.Format("{0} - Season {1} [{2}]", seriesTitle, + parseResult.SeasonNumber, parseResult.Quality.QualityType); + + if (parseResult.Quality.Proper) + seasonResult += " [Proper]"; + + return seasonResult; } - _externalNotificationProvider.OnGrab(sabTitle); + if (parseResult.Series.IsDaily) + { + var dailyResult = String.Format("{0} - {1:yyyy-MM-dd} - {2} [{3}]", seriesTitle, + parseResult.AirDate, parseResult.EpisodeTitle, parseResult.Quality.QualityType); + + if (parseResult.Quality.Proper) + dailyResult += " [Proper]"; + + return dailyResult; + } + + //Show Name - 1x01-1x02 - Episode Name + //Show Name - 1x01 - Episode Name + var episodeString = new List(); + + foreach (var episode in parseResult.EpisodeNumbers) + { + episodeString.Add(String.Format("{0}x{1}", parseResult.SeasonNumber, episode)); + } + + var epNumberString = String.Join("-", episodeString); + + var result = String.Format("{0} - {1} - {2} [{3}]", seriesTitle, epNumberString, parseResult.EpisodeTitle, parseResult.Quality.QualityType); + + if (parseResult.Quality.Proper) + { + result += " [Proper]"; + } - return addSuccess; + return result; } } } \ No newline at end of file diff --git a/NzbDrone.Core/Providers/EpisodeProvider.cs b/NzbDrone.Core/Providers/EpisodeProvider.cs index 77760810f..54a644214 100644 --- a/NzbDrone.Core/Providers/EpisodeProvider.cs +++ b/NzbDrone.Core/Providers/EpisodeProvider.cs @@ -127,10 +127,10 @@ namespace NzbDrone.Core.Providers _database.Execute("UPDATE Episodes SET GrabDate=@0 WHERE EpisodeId=@1", DateTime.Now, episodeId); } - public virtual IList GetEpisodesByParseResult(EpisodeParseResult parseResult, Boolean autoAddNew = false) + public virtual IList GetEpisodesByParseResult(EpisodeParseResult parseResult) { //Disabling auto add, need to make it a lot more conservative. - autoAddNew = false; + var autoAddNew = false; var result = new List(); diff --git a/NzbDrone.Core/Providers/HistoryProvider.cs b/NzbDrone.Core/Providers/HistoryProvider.cs index 14e17231e..94a3c8479 100644 --- a/NzbDrone.Core/Providers/HistoryProvider.cs +++ b/NzbDrone.Core/Providers/HistoryProvider.cs @@ -5,6 +5,7 @@ using Ninject; using NLog; using NzbDrone.Core.Model; using NzbDrone.Core.Repository; +using NzbDrone.Core.Repository.Quality; using PetaPoco; namespace NzbDrone.Core.Providers @@ -12,7 +13,7 @@ namespace NzbDrone.Core.Providers public class HistoryProvider { private readonly IDatabase _database; - private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + private static readonly Logger logger = LogManager.GetCurrentClassLogger(); [Inject] @@ -42,26 +43,34 @@ namespace NzbDrone.Core.Providers public virtual void Purge() { _database.Delete(""); - Logger.Info("History has been Purged"); + logger.Info("History has been Purged"); } public virtual void Trim() { _database.Delete("WHERE Date < @0", DateTime.Now.AddDays(-30).Date); - Logger.Info("History has been trimmed, items older than 30 days have been removed"); + logger.Info("History has been trimmed, items older than 30 days have been removed"); } public virtual void Add(History item) { _database.Insert(item); - Logger.Debug("Item added to history: {0}", item.NzbTitle); + logger.Debug("Item added to history: {0}", item.NzbTitle); } - public virtual Quality GetBestQualityInHistory(long episodeId) + public virtual Quality GetBestQualityInHistory(int seriesId, int seasonNumber, int episodeNumber) { - var history = AllItems().Where(c => c.EpisodeId == episodeId).ToList().Select(d => new Quality(d.Quality, d.IsProper)).OrderBy(c => c); + var quality = _database.SingleOrDefault(@"SELECT TOP 1 History.Quality , History.IsProper FROM History + INNER JOIN Episodes ON History.EpisodeId = Episodes.EpisodeId + WHERE Episodes.seriesId = @0 AND + Episodes.SeasonNumber = @1 AND + Episodes.EpisodeNumber = @2 + ORDER BY History.Quality DESC, History.IsProper DESC" + , seriesId, seasonNumber, episodeNumber); - return history.FirstOrDefault(); + if (quality == null) return null; + + return new Quality((QualityTypes)quality.Quality, quality.IsProper); } public virtual void Delete(int historyId) diff --git a/NzbDrone.Core/Providers/Indexer/Newzbin.cs b/NzbDrone.Core/Providers/Indexer/Newzbin.cs index 6a5f6089b..c1f19b35f 100644 --- a/NzbDrone.Core/Providers/Indexer/Newzbin.cs +++ b/NzbDrone.Core/Providers/Indexer/Newzbin.cs @@ -11,6 +11,9 @@ namespace NzbDrone.Core.Providers.Indexer { public class Newzbin : IndexerBase { + + private const string ROOT_DOMAIN = "https://www.newzbin2.es"; + [Inject] public Newzbin(HttpProvider httpProvider, ConfigProvider configProvider) : base(httpProvider, configProvider) @@ -25,7 +28,7 @@ namespace NzbDrone.Core.Providers.Indexer { return new[] { - "https://www.newzbin2.es/browse/category/p/tv?" + URL_PARAMS + ROOT_DOMAIN + "/browse/category/p/tv?" + URL_PARAMS }; } } @@ -50,7 +53,7 @@ namespace NzbDrone.Core.Providers.Indexer return new List { String.Format( - @"https://www.newzbin.es/search/query/?q={0}+{1}x{2:00}&fpn=p&searchaction=Go&category=8&{3}", + ROOT_DOMAIN + @"/search/query/?q={0}+{1}x{2:00}&fpn=p&searchaction=Go&category=8&{3}", seriesTitle, seasonNumber,episodeNumber, URL_PARAMS) }; } @@ -60,7 +63,7 @@ namespace NzbDrone.Core.Providers.Indexer return new List { String.Format( - @"https://www.newzbin.es/search/query/?q={0}+Season+{1}&fpn=p&searchaction=Go&category=8&{2}", + ROOT_DOMAIN + @"/search/query/?q={0}+Season+{1}&fpn=p&searchaction=Go&category=8&{2}", seriesTitle, seasonNumber, URL_PARAMS) }; } @@ -70,7 +73,7 @@ namespace NzbDrone.Core.Providers.Indexer return new List { String.Format( - @"https://www.newzbin.es/search/query/?q={0}+{1:yyyy-MM-dd}&fpn=p&searchaction=Go&category=8&{2}", + ROOT_DOMAIN + @"/search/query/?q={0}+{1:yyyy-MM-dd}&fpn=p&searchaction=Go&category=8&{2}", seriesTitle, date, URL_PARAMS) }; } @@ -80,7 +83,7 @@ namespace NzbDrone.Core.Providers.Indexer return new List { String.Format( - @"https://www.newzbin.es/search/query/?q={0}+{1}x{2}&fpn=p&searchaction=Go&category=8&{3}", + ROOT_DOMAIN + @"/search/query/?q={0}+{1}x{2}&fpn=p&searchaction=Go&category=8&{3}", seriesTitle, seasonNumber, episodeWildcard, URL_PARAMS) }; } diff --git a/NzbDrone.Core/Providers/InventoryProvider.cs b/NzbDrone.Core/Providers/InventoryProvider.cs deleted file mode 100644 index e374e5e77..000000000 --- a/NzbDrone.Core/Providers/InventoryProvider.cs +++ /dev/null @@ -1,209 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Ninject; -using NLog; -using NzbDrone.Core.Helpers; -using NzbDrone.Core.Model; -using NzbDrone.Core.Repository; -using NzbDrone.Core.Repository.Quality; - -namespace NzbDrone.Core.Providers -{ - public class InventoryProvider - { - private readonly SeriesProvider _seriesProvider; - private readonly EpisodeProvider _episodeProvider; - private readonly HistoryProvider _historyProvider; - private readonly QualityTypeProvider _qualityTypeProvider; - private readonly QualityProvider _qualityProvider; - - private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - - [Inject] - public InventoryProvider(SeriesProvider seriesProvider, EpisodeProvider episodeProvider, - HistoryProvider historyProvider, QualityTypeProvider qualityTypeProvider, - QualityProvider qualityProvider) - { - _seriesProvider = seriesProvider; - _episodeProvider = episodeProvider; - _historyProvider = historyProvider; - _qualityTypeProvider = qualityTypeProvider; - _qualityProvider = qualityProvider; - } - - public InventoryProvider() - { - - } - - - public virtual bool IsMonitored(EpisodeParseResult parseResult) - { - var series = _seriesProvider.FindSeries(parseResult.CleanTitle); - - if (series == null) - { - Logger.Trace("{0} is not mapped to any series in DB. skipping", parseResult.CleanTitle); - return false; - } - - parseResult.Series = series; - - if (!series.Monitored) - { - Logger.Debug("{0} is present in the DB but not tracked. skipping.", parseResult.CleanTitle); - return false; - } - - var episodes = _episodeProvider.GetEpisodesByParseResult(parseResult, true); - - //return monitored if any of the episodes are monitored - if (episodes.Any(episode => !episode.Ignored)) - { - return true; - } - - Logger.Debug("All episodes are ignored. skipping."); - return false; - } - - /// - /// Comprehensive check on whether or not this episode is needed. - /// - /// Episode that needs to be checked - /// False unless called by a manual search job - /// 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, bool skipHistory = false) - { - 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 (!IsAcceptableSize(parsedReport)) - { - Logger.Info("Size: {0} is not acceptable for Quality: {1}", FileSizeFormatHelper.Format(parsedReport.Size, 2), parsedReport.Quality); - return false; - } - - foreach (var episode in _episodeProvider.GetEpisodesByParseResult(parsedReport, true)) - { - //Checking File - var file = episode.EpisodeFile; - if (file != null) - { - 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; - } - - //Checking History (If not a manual search) - if (!skipHistory) - { - var bestQualityInHistory = _historyProvider.GetBestQualityInHistory(episode.EpisodeId); - if(bestQualityInHistory != null) - { - Logger.Trace("Comparing history quality with report. History is {0}", bestQualityInHistory); - if(!IsUpgrade(bestQualityInHistory, parsedReport.Quality, cutoff)) - return false; - } - } - - } - - 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) - { - if (newQuality.QualityType > currentQuality.QualityType || - (newQuality.QualityType == currentQuality.QualityType && newQuality.Proper == currentQuality.Proper)) - { - Logger.Trace("Existing item 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; - } - - Logger.Debug("New item has better quality than existing item"); - return true; - } - - public virtual bool IsAcceptableSize(EpisodeParseResult parseResult) - { - var qualityType = _qualityTypeProvider.Get((int) parseResult.Quality.QualityType); - - //Need to determine if this is a 30 or 60 minute episode - //Is it a multi-episode release? - //Is it the first or last series of a season? - - //0 will be treated as unlimited - if (qualityType.MaxSize == 0) - return true; - - var maxSize = qualityType.MaxSize.Megabytes(); - var series = parseResult.Series; - - //Multiply maxSize by Series.Runtime - maxSize = maxSize * series.Runtime; - - //Multiply maxSize by the number of episodes parsed (if EpisodeNumbers is null it will be treated as a single episode) - if (parseResult.EpisodeNumbers != null) - maxSize = maxSize * parseResult.EpisodeNumbers.Count; - - //Check if there was only one episode parsed - //and it is the first or last episode of the season - if (parseResult.EpisodeNumbers != null && parseResult.EpisodeNumbers.Count == 1 && - _episodeProvider.IsFirstOrLastEpisodeOfSeason(series.SeriesId, - parseResult.SeasonNumber, parseResult.EpisodeNumbers[0])) - { - maxSize = maxSize * 2; - } - - //If the parsed size is greater than maxSize we don't want it - if (parseResult.Size > maxSize) - return false; - - return true; - } - - public virtual bool IsUpgradePossible(Episode episode) - { - //Used to check if the existing episode can be upgraded by searching (Before we search) - - if (episode.EpisodeFileId == 0) - return true; - - var profile = _qualityProvider.Get(episode.Series.QualityProfileId); - - if (episode.EpisodeFile.Quality >= profile.Cutoff) - return false; - - return true; - } - } -} \ No newline at end of file diff --git a/NzbDrone.Core/Providers/SearchProvider.cs b/NzbDrone.Core/Providers/SearchProvider.cs index 6a122fe75..95e64141f 100644 --- a/NzbDrone.Core/Providers/SearchProvider.cs +++ b/NzbDrone.Core/Providers/SearchProvider.cs @@ -6,6 +6,7 @@ using NLog; using Ninject; using NzbDrone.Core.Model; using NzbDrone.Core.Model.Notification; +using NzbDrone.Core.Providers.DecisionEngine; using NzbDrone.Core.Repository; namespace NzbDrone.Core.Providers @@ -14,25 +15,27 @@ namespace NzbDrone.Core.Providers { //Season and Episode Searching private readonly EpisodeProvider _episodeProvider; - private readonly InventoryProvider _inventoryProvider; private readonly DownloadProvider _downloadProvider; private readonly SeriesProvider _seriesProvider; private readonly IndexerProvider _indexerProvider; private readonly SceneMappingProvider _sceneMappingProvider; + private readonly UpgradePossibleSpecification _upgradePossibleSpecification; + private readonly AllowedDownloadSpecification _allowedDownloadSpecification; private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); [Inject] - public SearchProvider(EpisodeProvider episodeProvider, InventoryProvider inventoryProvider, - DownloadProvider downloadProvider, SeriesProvider seriesProvider, - IndexerProvider indexerProvider, SceneMappingProvider sceneMappingProvider) + public SearchProvider(EpisodeProvider episodeProvider, DownloadProvider downloadProvider, SeriesProvider seriesProvider, + IndexerProvider indexerProvider, SceneMappingProvider sceneMappingProvider, + UpgradePossibleSpecification upgradePossibleSpecification, AllowedDownloadSpecification allowedDownloadSpecification) { _episodeProvider = episodeProvider; - _inventoryProvider = inventoryProvider; _downloadProvider = downloadProvider; _seriesProvider = seriesProvider; _indexerProvider = indexerProvider; _sceneMappingProvider = sceneMappingProvider; + _upgradePossibleSpecification = upgradePossibleSpecification; + _allowedDownloadSpecification = allowedDownloadSpecification; } public SearchProvider() @@ -130,7 +133,7 @@ namespace NzbDrone.Core.Providers } //Check to see if an upgrade is possible before attempting - if (!_inventoryProvider.IsUpgradePossible(episode)) + if (!_upgradePossibleSpecification.IsSatisfiedBy(episode)) { Logger.Info("Search for {0} was aborted, file in disk meets or exceeds Profile's Cutoff", episode); notification.CurrentMessage = String.Format("Skipping search for {0}, file you have is already at cutoff", episode); @@ -157,7 +160,7 @@ namespace NzbDrone.Core.Providers return true; Logger.Warn("Unable to find {0} in any of indexers.", episode); - + if (reports.Any()) { notification.CurrentMessage = String.Format("Sorry, couldn't find {0} in a non-sucky quality. (by your standards)", episode); @@ -185,7 +188,7 @@ namespace NzbDrone.Core.Providers title = series.Title; } - foreach(var indexer in indexers) + foreach (var indexer in indexers) { try { @@ -259,13 +262,13 @@ namespace NzbDrone.Core.Providers } //Make sure we haven't already downloaded a report with this episodenumber, if we have, skip the report. - if (successes.Intersect(episodeParseResult.EpisodeNumbers).Count() > 0) + if (successes.Intersect(episodeParseResult.EpisodeNumbers).Any()) { Logger.Trace("Episode has already been downloaded in this search, skipping."); continue; } - if (_inventoryProvider.IsQualityNeeded(episodeParseResult, true)) + if (_allowedDownloadSpecification.IsSatisfiedBy(episodeParseResult)) { Logger.Debug("Found '{0}'. Adding to download queue.", episodeParseResult); try @@ -316,7 +319,7 @@ namespace NzbDrone.Core.Providers if (!episodeParseResult.AirDate.HasValue || episodeParseResult.AirDate.Value.Date != airDate.Date) continue; - if (_inventoryProvider.IsQualityNeeded(episodeParseResult, true)) + if (_allowedDownloadSpecification.IsSatisfiedBy(episodeParseResult)) { Logger.Debug("Found '{0}'. Adding to download queue.", episodeParseResult); try diff --git a/NzbDrone.Core/Repository/Quality/QualityType.cs b/NzbDrone.Core/Repository/Quality/QualityType.cs index 88f816bff..22c431ff4 100644 --- a/NzbDrone.Core/Repository/Quality/QualityType.cs +++ b/NzbDrone.Core/Repository/Quality/QualityType.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.ComponentModel.DataAnnotations; -using System.Linq; +using System.Linq; using PetaPoco; namespace NzbDrone.Core.Repository.Quality diff --git a/NzbDrone.Services/NzbDrone.Services.Service/Global.asax.cs b/NzbDrone.Services/NzbDrone.Services.Service/Global.asax.cs index 3c2632fad..17c6c8f47 100644 --- a/NzbDrone.Services/NzbDrone.Services.Service/Global.asax.cs +++ b/NzbDrone.Services/NzbDrone.Services.Service/Global.asax.cs @@ -52,12 +52,6 @@ namespace NzbDrone.Services.Service } logger.FatalException(lastError.Message + Environment.NewLine + Request.Url.PathAndQuery, lastError); - - if (lastError is DbException) - { - logger.Warn("Restarting application"); - HttpRuntime.UnloadAppDomain(); - } } protected void Application_BeginRequest() @@ -67,5 +61,6 @@ namespace NzbDrone.Services.Service protected void Application_EndRequest() { } + } } \ No newline at end of file diff --git a/NzbDrone.Services/NzbDrone.Services.Service/JsonModelBinder.cs b/NzbDrone.Services/NzbDrone.Services.Service/JsonModelBinder.cs index ac9fd6a1d..2f59faee6 100644 --- a/NzbDrone.Services/NzbDrone.Services.Service/JsonModelBinder.cs +++ b/NzbDrone.Services/NzbDrone.Services.Service/JsonModelBinder.cs @@ -1,7 +1,9 @@ +using System; using System.IO; using System.Linq; using System.Web; using System.Web.Mvc; +using NLog; using Newtonsoft.Json; namespace NzbDrone.Services.Service @@ -9,27 +11,36 @@ namespace NzbDrone.Services.Service public class JsonModelBinder : DefaultModelBinder { private static readonly JsonSerializer serializer = new JsonSerializer(); + private static readonly Logger logger = LogManager.GetCurrentClassLogger(); public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { - var request = controllerContext.HttpContext.Request; - - if (!IsJsonRequest(request)) + try { - return base.BindModel(controllerContext, bindingContext); - } + var request = controllerContext.HttpContext.Request; - object deserializedObject; - using (var stream = request.InputStream) - { - stream.Seek(0, SeekOrigin.Begin); - using (var reader = new StreamReader(stream)) + if (!IsJsonRequest(request)) { - deserializedObject = serializer.Deserialize(reader, bindingContext.ModelMetadata.ModelType); + return base.BindModel(controllerContext, bindingContext); + } + + object deserializedObject; + using (var stream = request.InputStream) + { + stream.Seek(0, SeekOrigin.Begin); + using (var reader = new StreamReader(stream)) + { + deserializedObject = serializer.Deserialize(reader, bindingContext.ModelMetadata.ModelType); + } } - } - return deserializedObject; + return deserializedObject; + } + catch (Exception e) + { + logger.FatalException("Error while binding model.", e); + throw; + } } private static bool IsJsonRequest(HttpRequestBase request) diff --git a/NzbDrone.Services/NzbDrone.Services.Service/Migrations/Migration20120206.cs b/NzbDrone.Services/NzbDrone.Services.Service/Migrations/Migration20120206.cs new file mode 100644 index 000000000..fa9f2f710 --- /dev/null +++ b/NzbDrone.Services/NzbDrone.Services.Service/Migrations/Migration20120206.cs @@ -0,0 +1,21 @@ +using System; +using System.Data; +using Migrator.Framework; + +namespace NzbDrone.Services.Service.Migrations +{ + + [Migration(20120206)] + public class Migration20120206 : Migration + { + public override void Up() + { + Database.ExecuteNonQuery("ALTER TABLE ExceptionReports DROP CONSTRAINT PK_ExceptionReports"); + } + + public override void Down() + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/NzbDrone.Services/NzbDrone.Services.Service/NzbDrone.Services.Service.csproj b/NzbDrone.Services/NzbDrone.Services.Service/NzbDrone.Services.Service.csproj index b99c9e284..de592e43e 100644 --- a/NzbDrone.Services/NzbDrone.Services.Service/NzbDrone.Services.Service.csproj +++ b/NzbDrone.Services/NzbDrone.Services.Service/NzbDrone.Services.Service.csproj @@ -119,6 +119,7 @@ Global.asax + diff --git a/NzbDrone.Web/Controllers/CommandController.cs b/NzbDrone.Web/Controllers/CommandController.cs index dc1df693e..08cdb3a14 100644 --- a/NzbDrone.Web/Controllers/CommandController.cs +++ b/NzbDrone.Web/Controllers/CommandController.cs @@ -1,6 +1,7 @@ using System.Web.Mvc; using NzbDrone.Core.Jobs; using NzbDrone.Core.Providers; +using NzbDrone.Core.Providers.DownloadClients; using NzbDrone.Web.Filters; using NzbDrone.Web.Models; diff --git a/NzbDrone.Web/Controllers/SystemController.cs b/NzbDrone.Web/Controllers/SystemController.cs index 87a3789c5..3c079803b 100644 --- a/NzbDrone.Web/Controllers/SystemController.cs +++ b/NzbDrone.Web/Controllers/SystemController.cs @@ -8,6 +8,7 @@ using NzbDrone.Core.Helpers; using NzbDrone.Core.Jobs; using NzbDrone.Core.Providers; using NzbDrone.Core.Providers.Core; +using NzbDrone.Core.Providers.DownloadClients; using NzbDrone.Web.Models; using Telerik.Web.Mvc; diff --git a/NzbDrone/Router.cs b/NzbDrone/Router.cs index 1f95c7d39..0b720627c 100644 --- a/NzbDrone/Router.cs +++ b/NzbDrone/Router.cs @@ -35,16 +35,7 @@ namespace NzbDrone public void Route(ApplicationMode applicationMode) { - Logger.Info("Application mode: {0}", applicationMode); - - var batFiles = _diskProvider.GetFiles(_enviromentProvider.ApplicationPath, SearchOption.TopDirectoryOnly) - .Where(c => c.EndsWith(".bat", StringComparison.InvariantCultureIgnoreCase)).ToList(); - - foreach (var batFile in batFiles) - { - if (new FileInfo(batFile).Name.StartsWith("service", StringComparison.InvariantCultureIgnoreCase)) - _diskProvider.DeleteFile(batFile); - } + Logger.Info("Application mode: {0}", applicationMode); //TODO:move this outside, it should be one of application modes (ApplicationMode.Service?) if (!_enviromentProvider.IsUserInteractive)