diff --git a/src/NzbDrone.Api/Blacklist/BlacklistResource.cs b/src/NzbDrone.Api/Blacklist/BlacklistResource.cs index b9638cf9c..e75ca83f3 100644 --- a/src/NzbDrone.Api/Blacklist/BlacklistResource.cs +++ b/src/NzbDrone.Api/Blacklist/BlacklistResource.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using NzbDrone.Api.REST; using NzbDrone.Core.Qualities; +using NzbDrone.Api.Series; namespace NzbDrone.Api.Blacklist { @@ -12,5 +13,7 @@ namespace NzbDrone.Api.Blacklist public string SourceTitle { get; set; } public QualityModel Quality { get; set; } public DateTime Date { get; set; } + + public SeriesResource Series { get; set; } } } diff --git a/src/NzbDrone.Api/RootFolders/RootFolderModule.cs b/src/NzbDrone.Api/RootFolders/RootFolderModule.cs index be1c43674..36e034946 100644 --- a/src/NzbDrone.Api/RootFolders/RootFolderModule.cs +++ b/src/NzbDrone.Api/RootFolders/RootFolderModule.cs @@ -42,7 +42,7 @@ namespace NzbDrone.Api.RootFolders private int CreateRootFolder(RootFolderResource rootFolderResource) { - return GetNewId(_rootFolderService.Add, rootFolderResource); + return GetNewId(_rootFolderService.Add, rootFolderResource); } private List GetRootFolders() diff --git a/src/NzbDrone.Automation.Test/NzbDrone.Automation.Test.csproj b/src/NzbDrone.Automation.Test/NzbDrone.Automation.Test.csproj index c2a226a14..c09932bcb 100644 --- a/src/NzbDrone.Automation.Test/NzbDrone.Automation.Test.csproj +++ b/src/NzbDrone.Automation.Test/NzbDrone.Automation.Test.csproj @@ -52,15 +52,17 @@ - - ..\packages\Selenium.WebDriver.2.37.0\lib\net40\WebDriver.dll - - - ..\packages\Selenium.Support.2.37.0\lib\net40\WebDriver.Support.dll - ..\packages\FluentAssertions.2.1.0.0\lib\net40\FluentAssertions.dll + + False + ..\packages\Selenium.WebDriver.2.41.0\lib\net40\WebDriver.dll + + + False + ..\packages\Selenium.Support.2.41.0\lib\net40\WebDriver.Support.dll + diff --git a/src/NzbDrone.Automation.Test/packages.config b/src/NzbDrone.Automation.Test/packages.config index f51e94b57..5e1ee41b7 100644 --- a/src/NzbDrone.Automation.Test/packages.config +++ b/src/NzbDrone.Automation.Test/packages.config @@ -3,6 +3,6 @@ - - + + \ No newline at end of file diff --git a/src/NzbDrone.Common.Test/DiskProviderTests/DiskProviderFixtureBase.cs b/src/NzbDrone.Common.Test/DiskProviderTests/DiskProviderFixtureBase.cs index e4a953fce..8c62331de 100644 --- a/src/NzbDrone.Common.Test/DiskProviderTests/DiskProviderFixtureBase.cs +++ b/src/NzbDrone.Common.Test/DiskProviderTests/DiskProviderFixtureBase.cs @@ -10,30 +10,26 @@ namespace NzbDrone.Common.Test.DiskProviderTests { public class DiskProviderFixtureBase : TestBase where TSubject : class, IDiskProvider { - DirectoryInfo _binFolder; - DirectoryInfo _binFolderCopy; - DirectoryInfo _binFolderMove; - [SetUp] public void Setup() { - _binFolder = new DirectoryInfo(Directory.GetCurrentDirectory()); - _binFolderCopy = new DirectoryInfo(Path.Combine(_binFolder.Parent.FullName, "bin_copy")); - _binFolderMove = new DirectoryInfo(Path.Combine(_binFolder.Parent.FullName, "bin_move")); - if (_binFolderCopy.Exists) - { - foreach (var file in _binFolderCopy.GetFiles("*", SearchOption.AllDirectories)) - { - file.Attributes = FileAttributes.Normal; - } - _binFolderCopy.Delete(true); - } + } - if (_binFolderMove.Exists) - { - _binFolderMove.Delete(true); - } + public DirectoryInfo GetFilledTempFolder() + { + var tempFolder = GetTempFilePath(); + Directory.CreateDirectory(tempFolder); + + File.WriteAllText(Path.Combine(tempFolder, Path.GetRandomFileName()), "RootFile"); + + var subDir = Path.Combine(tempFolder, Path.GetRandomFileName()); + Directory.CreateDirectory(subDir); + + File.WriteAllText(Path.Combine(subDir, Path.GetRandomFileName()), "SubFile1"); + File.WriteAllText(Path.Combine(subDir, Path.GetRandomFileName()), "SubFile2"); + + return new DirectoryInfo(tempFolder); } [Test] @@ -57,79 +53,94 @@ namespace NzbDrone.Common.Test.DiskProviderTests } [Test] - public void moveFile_should_overwrite_existing_file() + public void MoveFile_should_overwrite_existing_file() { + var source1 = GetTempFilePath(); + var source2 = GetTempFilePath(); + var destination = GetTempFilePath(); - Subject.CopyFolder(_binFolder.FullName, _binFolderCopy.FullName); + File.WriteAllText(source1, "SourceFile1"); + File.WriteAllText(source2, "SourceFile2"); - var targetPath = Path.Combine(_binFolderCopy.FullName, "file.move"); + Subject.MoveFile(source1, destination); + Subject.MoveFile(source2, destination); - Subject.MoveFile(_binFolderCopy.GetFiles("*.dll", SearchOption.AllDirectories).First().FullName, targetPath); - Subject.MoveFile(_binFolderCopy.GetFiles("*.pdb", SearchOption.AllDirectories).First().FullName, targetPath); - - File.Exists(targetPath).Should().BeTrue(); + File.Exists(destination).Should().BeTrue(); } [Test] - public void moveFile_should_not_move_overwrite_itself() + public void MoveFile_should_not_move_overwrite_itself() { + var source = GetTempFilePath(); - Subject.CopyFolder(_binFolder.FullName, _binFolderCopy.FullName); - - var targetPath = _binFolderCopy.GetFiles("*.dll", SearchOption.AllDirectories).First().FullName; + File.WriteAllText(source, "SourceFile1"); - Subject.MoveFile(targetPath, targetPath); + Subject.MoveFile(source, source); - File.Exists(targetPath).Should().BeTrue(); + File.Exists(source).Should().BeTrue(); ExceptionVerification.ExpectedWarns(1); } [Test] public void CopyFolder_should_copy_folder() { - Subject.CopyFolder(_binFolder.FullName, _binFolderCopy.FullName); - VerifyCopy(); + var source = GetFilledTempFolder(); + var destination = new DirectoryInfo(GetTempFilePath()); + + Subject.CopyFolder(source.FullName, destination.FullName); + + VerifyCopy(source.FullName, destination.FullName); } [Test] public void CopyFolder_should_overwrite_existing_folder() { + var source = GetFilledTempFolder(); + var destination = new DirectoryInfo(GetTempFilePath()); + Subject.CopyFolder(source.FullName, destination.FullName); + + //Delete Random File + destination.GetFiles("*.*", SearchOption.AllDirectories).First().Delete(); + Subject.CopyFolder(source.FullName, destination.FullName); + VerifyCopy(source.FullName, destination.FullName); + } - Subject.CopyFolder(_binFolder.FullName, _binFolderCopy.FullName); - - //Delete Random File - _binFolderCopy.Refresh(); - _binFolderCopy.GetFiles("*.*", SearchOption.AllDirectories).First().Delete(); + [Test] + public void MoveFolder_should_move_folder() + { + var original = GetFilledTempFolder(); + var source = new DirectoryInfo(GetTempFilePath()); + var destination = new DirectoryInfo(GetTempFilePath()); - Subject.CopyFolder(_binFolder.FullName, _binFolderCopy.FullName); + Subject.CopyFolder(original.FullName, source.FullName); + Subject.MoveFolder(source.FullName, destination.FullName); - VerifyCopy(); + VerifyMove(original.FullName, source.FullName, destination.FullName); } [Test] public void MoveFolder_should_overwrite_existing_folder() { + var original = GetFilledTempFolder(); + var source = new DirectoryInfo(GetTempFilePath()); + var destination = new DirectoryInfo(GetTempFilePath()); + Subject.CopyFolder(original.FullName, source.FullName); + Subject.CopyFolder(original.FullName, destination.FullName); - Subject.CopyFolder(_binFolder.FullName, _binFolderCopy.FullName); - Subject.CopyFolder(_binFolder.FullName, _binFolderMove.FullName); - VerifyCopy(); - - - Subject.MoveFolder(_binFolderCopy.FullName, _binFolderMove.FullName); - + Subject.MoveFolder(source.FullName, destination.FullName); - VerifyMove(); + VerifyMove(original.FullName, source.FullName, destination.FullName); } [Test] public void move_read_only_file() { - var source = GetTestFilePath(); - var destination = GetTestFilePath(); + var source = GetTempFilePath(); + var destination = GetTempFilePath(); Subject.WriteAllText(source, "SourceFile"); Subject.WriteAllText(destination, "DestinationFile"); @@ -150,23 +161,25 @@ namespace NzbDrone.Common.Test.DiskProviderTests [Test] public void folder_should_return_correct_value_for_last_write() { - var testDir = Path.Combine(SandboxFolder, "LastWrite"); + var testDir = GetTempFilePath(); var testFile = Path.Combine(testDir, Path.GetRandomFileName()); Directory.CreateDirectory(testDir); + Subject.FolderSetLastWriteTimeUtc(TempFolder, DateTime.UtcNow.AddMinutes(-5)); + TestLogger.Info("Path is: {0}", testFile); Subject.WriteAllText(testFile, "Test"); - Subject.FolderGetLastWrite(SandboxFolder).Should().BeOnOrAfter(DateTime.UtcNow.AddMinutes(-1)); - Subject.FolderGetLastWrite(SandboxFolder).Should().BeBefore(DateTime.UtcNow.AddMinutes(1)); + Subject.FolderGetLastWrite(TempFolder).Should().BeOnOrAfter(DateTime.UtcNow.AddMinutes(-1)); + Subject.FolderGetLastWrite(TempFolder).Should().BeBefore(DateTime.UtcNow.AddMinutes(1)); } [Test] public void should_return_false_for_unlocked_file() { - var testFile = GetTestFilePath(); + var testFile = GetTempFilePath(); Subject.WriteAllText(testFile, new Guid().ToString()); Subject.IsFileLocked(testFile).Should().BeFalse(); @@ -175,7 +188,7 @@ namespace NzbDrone.Common.Test.DiskProviderTests [Test] public void should_return_false_for_unlocked_and_readonly_file() { - var testFile = GetTestFilePath(); + var testFile = GetTempFilePath(); Subject.WriteAllText(testFile, new Guid().ToString()); File.SetAttributes(testFile, FileAttributes.ReadOnly); @@ -186,7 +199,7 @@ namespace NzbDrone.Common.Test.DiskProviderTests [Test] public void should_return_true_for_unlocked_file() { - var testFile = GetTestFilePath(); + var testFile = GetTempFilePath(); Subject.WriteAllText(testFile, new Guid().ToString()); using (var file = File.OpenWrite(testFile)) @@ -198,7 +211,7 @@ namespace NzbDrone.Common.Test.DiskProviderTests [Test] public void should_be_able_to_set_permission_from_parrent() { - var testFile = GetTestFilePath(); + var testFile = GetTempFilePath(); Subject.WriteAllText(testFile, new Guid().ToString()); Subject.InheritFolderPermissions(testFile); @@ -208,33 +221,26 @@ namespace NzbDrone.Common.Test.DiskProviderTests [Explicit] public void check_last_write() { - Console.WriteLine(Subject.FolderGetLastWrite(_binFolder.FullName)); - Console.WriteLine(_binFolder.LastWriteTimeUtc); + Console.WriteLine(Subject.FolderGetLastWrite(GetFilledTempFolder().FullName)); + Console.WriteLine(GetFilledTempFolder().LastWriteTimeUtc); } - private void VerifyCopy() + private void VerifyCopy(string source, string destination) { - _binFolder.Refresh(); - _binFolderCopy.Refresh(); - - _binFolderCopy.GetFiles("*.*", SearchOption.AllDirectories) - .Should().HaveSameCount(_binFolder.GetFiles("*.*", SearchOption.AllDirectories)); + var sourceFiles = Directory.GetFileSystemEntries(source, "*", SearchOption.AllDirectories).Select(v => v.Substring(source.Length + 1)).ToArray(); + var destFiles = Directory.GetFileSystemEntries(destination, "*", SearchOption.AllDirectories).Select(v => v.Substring(destination.Length + 1)).ToArray(); - _binFolderCopy.GetDirectories().Should().HaveSameCount(_binFolder.GetDirectories()); + CollectionAssert.AreEquivalent(sourceFiles, destFiles); } - private void VerifyMove() + private void VerifyMove(string source, string from, string destination) { - _binFolder.Refresh(); - _binFolderCopy.Refresh(); - _binFolderMove.Refresh(); - - _binFolderCopy.Exists.Should().BeFalse(); + Directory.Exists(from).Should().BeFalse(); - _binFolderMove.GetFiles("*.*", SearchOption.AllDirectories) - .Should().HaveSameCount(_binFolder.GetFiles("*.*", SearchOption.AllDirectories)); + var sourceFiles = Directory.GetFileSystemEntries(source, "*", SearchOption.AllDirectories).Select(v => v.Substring(source.Length + 1)).ToArray(); + var destFiles = Directory.GetFileSystemEntries(destination, "*", SearchOption.AllDirectories).Select(v => v.Substring(destination.Length + 1)).ToArray(); - _binFolderMove.GetDirectories().Should().HaveSameCount(_binFolder.GetDirectories()); + CollectionAssert.AreEquivalent(sourceFiles, destFiles); } } } diff --git a/src/NzbDrone.Common.Test/DiskProviderTests/FreeSpaceFixtureBase.cs b/src/NzbDrone.Common.Test/DiskProviderTests/FreeSpaceFixtureBase.cs index f63942a11..098456276 100644 --- a/src/NzbDrone.Common.Test/DiskProviderTests/FreeSpaceFixtureBase.cs +++ b/src/NzbDrone.Common.Test/DiskProviderTests/FreeSpaceFixtureBase.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Linq; using FluentAssertions; using NUnit.Framework; using NzbDrone.Common.Disk; @@ -61,7 +62,17 @@ namespace NzbDrone.Common.Test.DiskProviderTests { WindowsOnly(); - Assert.Throws(() => Subject.GetAvailableSpace(@"Z:\NOT_A_REAL_PATH\DOES_NOT_EXIST".AsOsAgnostic())); + // Find a drive that doesn't exist. + for (char driveletter = 'Z'; driveletter > 'D' ; driveletter--) + { + if (new DriveInfo(driveletter.ToString()).IsReady) + continue; + + Assert.Throws(() => Subject.GetAvailableSpace(driveletter + @":\NOT_A_REAL_PATH\DOES_NOT_EXIST".AsOsAgnostic())); + return; + } + + Assert.Inconclusive("No drive available for testing."); } [Test] diff --git a/src/NzbDrone.Common.Test/PathExtensionFixture.cs b/src/NzbDrone.Common.Test/PathExtensionFixture.cs index 8c75708e2..4dd274a33 100644 --- a/src/NzbDrone.Common.Test/PathExtensionFixture.cs +++ b/src/NzbDrone.Common.Test/PathExtensionFixture.cs @@ -120,7 +120,7 @@ namespace NzbDrone.Common.Test public void get_actual_casing_should_return_actual_casing_for_local_file_in_windows() { WindowsOnly(); - var path = Process.GetCurrentProcess().MainModule.FileName; + var path = Environment.ExpandEnvironmentVariables("%SystemRoot%\\System32"); path.ToUpper().GetActualCasing().Should().Be(path); path.ToLower().GetActualCasing().Should().Be(path); } diff --git a/src/NzbDrone.Common/Cache/CacheManger.cs b/src/NzbDrone.Common/Cache/CacheManager.cs similarity index 100% rename from src/NzbDrone.Common/Cache/CacheManger.cs rename to src/NzbDrone.Common/Cache/CacheManager.cs diff --git a/src/NzbDrone.Common/NzbDrone.Common.csproj b/src/NzbDrone.Common/NzbDrone.Common.csproj index b2dd6301f..01cd2da76 100644 --- a/src/NzbDrone.Common/NzbDrone.Common.csproj +++ b/src/NzbDrone.Common/NzbDrone.Common.csproj @@ -61,7 +61,7 @@ - + diff --git a/src/NzbDrone.Core.Test/Datastore/MappingExtentionFixture.cs b/src/NzbDrone.Core.Test/Datastore/MappingExtentionFixture.cs index 0aaaf840f..cbc032849 100644 --- a/src/NzbDrone.Core.Test/Datastore/MappingExtentionFixture.cs +++ b/src/NzbDrone.Core.Test/Datastore/MappingExtentionFixture.cs @@ -5,7 +5,7 @@ using Marr.Data; using NUnit.Framework; using NzbDrone.Core.Datastore; using NzbDrone.Core.Datastore.Converters; -using NzbDrone.Core.Datastore.Extentions; +using NzbDrone.Core.Datastore.Extensions; using NzbDrone.Core.Tv; namespace NzbDrone.Core.Test.Datastore diff --git a/src/NzbDrone.Core.Test/Datastore/PagingSpecExtenstionsTests/PagingOffsetFixture.cs b/src/NzbDrone.Core.Test/Datastore/PagingSpecExtensionsTests/PagingOffsetFixture.cs similarity index 86% rename from src/NzbDrone.Core.Test/Datastore/PagingSpecExtenstionsTests/PagingOffsetFixture.cs rename to src/NzbDrone.Core.Test/Datastore/PagingSpecExtensionsTests/PagingOffsetFixture.cs index 65819a686..5ece0f8a4 100644 --- a/src/NzbDrone.Core.Test/Datastore/PagingSpecExtenstionsTests/PagingOffsetFixture.cs +++ b/src/NzbDrone.Core.Test/Datastore/PagingSpecExtensionsTests/PagingOffsetFixture.cs @@ -1,10 +1,10 @@ using FluentAssertions; using NUnit.Framework; using NzbDrone.Core.Datastore; -using NzbDrone.Core.Datastore.Extentions; +using NzbDrone.Core.Datastore.Extensions; using NzbDrone.Core.Tv; -namespace NzbDrone.Core.Test.Datastore.PagingSpecExtenstionsTests +namespace NzbDrone.Core.Test.Datastore.PagingSpecExtensionsTests { public class PagingOffsetFixture { diff --git a/src/NzbDrone.Core.Test/Datastore/PagingSpecExtenstionsTests/ToSortDirectionFixture.cs b/src/NzbDrone.Core.Test/Datastore/PagingSpecExtensionsTests/ToSortDirectionFixture.cs similarity index 90% rename from src/NzbDrone.Core.Test/Datastore/PagingSpecExtenstionsTests/ToSortDirectionFixture.cs rename to src/NzbDrone.Core.Test/Datastore/PagingSpecExtensionsTests/ToSortDirectionFixture.cs index de74a63f2..b0eaa64c0 100644 --- a/src/NzbDrone.Core.Test/Datastore/PagingSpecExtenstionsTests/ToSortDirectionFixture.cs +++ b/src/NzbDrone.Core.Test/Datastore/PagingSpecExtensionsTests/ToSortDirectionFixture.cs @@ -1,10 +1,10 @@ using FluentAssertions; using NUnit.Framework; using NzbDrone.Core.Datastore; -using NzbDrone.Core.Datastore.Extentions; +using NzbDrone.Core.Datastore.Extensions; using NzbDrone.Core.Tv; -namespace NzbDrone.Core.Test.Datastore.PagingSpecExtenstionsTests +namespace NzbDrone.Core.Test.Datastore.PagingSpecExtensionsTests { public class ToSortDirectionFixture { diff --git a/src/NzbDrone.Core.Test/DecisionEngineTests/AcceptableSizeSpecificationFixture.cs b/src/NzbDrone.Core.Test/DecisionEngineTests/AcceptableSizeSpecificationFixture.cs index 117c81ec0..5515fcedf 100644 --- a/src/NzbDrone.Core.Test/DecisionEngineTests/AcceptableSizeSpecificationFixture.cs +++ b/src/NzbDrone.Core.Test/DecisionEngineTests/AcceptableSizeSpecificationFixture.cs @@ -48,7 +48,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests Series = series, Release = new ReleaseInfo(), ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.SDTV, true) }, - Episodes = new List { new Episode() } + Episodes = new List { new Episode() { Id = 2 } } }; @@ -59,13 +59,21 @@ namespace NzbDrone.Core.Test.DecisionEngineTests .Build(); Mocker.GetMock().Setup(s => s.Get(Quality.SDTV)).Returns(qualityType); + + Mocker.GetMock().Setup( + s => s.GetEpisodesBySeason(It.IsAny(), It.IsAny())) + .Returns(new List() { + new Episode(), new Episode(), new Episode(), new Episode(), new Episode(), + new Episode(), new Episode(), new Episode(), new Episode() { Id = 2 }, new Episode() }); } private void GivenLastEpisode() { Mocker.GetMock().Setup( - s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny())) - .Returns(true); + s => s.GetEpisodesBySeason(It.IsAny(), It.IsAny())) + .Returns(new List() { + new Episode(), new Episode(), new Episode(), new Episode(), new Episode(), + new Episode(), new Episode(), new Episode(), new Episode(), new Episode() { Id = 2 } }); } [TestCase(30, 50, false)] @@ -110,10 +118,6 @@ namespace NzbDrone.Core.Test.DecisionEngineTests parseResultMulti.Series = series; parseResultMulti.Release.Size = sizeInMegaBytes.Megabytes(); - Mocker.GetMock().Setup( - s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny())) - .Returns(false); - Subject.IsSatisfiedBy(parseResultMulti, null).Should().Be(expectedResult); } @@ -129,10 +133,6 @@ namespace NzbDrone.Core.Test.DecisionEngineTests parseResultMultiSet.Series = series; parseResultMultiSet.Release.Size = sizeInMegaBytes.Megabytes(); - Mocker.GetMock().Setup( - s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny())) - .Returns(false); - Subject.IsSatisfiedBy(parseResultMultiSet, null).Should().Be(expectedResult); } diff --git a/src/NzbDrone.Core.Test/FluentTest.cs b/src/NzbDrone.Core.Test/FluentTest.cs index 7af26ed45..66addf0c7 100644 --- a/src/NzbDrone.Core.Test/FluentTest.cs +++ b/src/NzbDrone.Core.Test/FluentTest.cs @@ -4,6 +4,7 @@ using System.Text; using FluentAssertions; using NUnit.Framework; using NzbDrone.Core.Test.Framework; +using NzbDrone.Test.Common; namespace NzbDrone.Core.Test { @@ -22,10 +23,11 @@ namespace NzbDrone.Core.Test } [Test] - [ExpectedException(typeof(ArgumentNullException))] public void WithDefault_Fail() { - "test".WithDefault(null); + Assert.Throws(() => "test".WithDefault(null)); + + ExceptionVerification.IgnoreWarns(); } [Test] diff --git a/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj index 22a8d5042..2e7790ae8 100644 --- a/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj +++ b/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj @@ -103,8 +103,8 @@ - - + + diff --git a/src/NzbDrone.Core.Test/ParserTests/DailyEpisodeParserFixture.cs b/src/NzbDrone.Core.Test/ParserTests/DailyEpisodeParserFixture.cs index 66b9b5733..67f3bed2d 100644 --- a/src/NzbDrone.Core.Test/ParserTests/DailyEpisodeParserFixture.cs +++ b/src/NzbDrone.Core.Test/ParserTests/DailyEpisodeParserFixture.cs @@ -25,6 +25,7 @@ namespace NzbDrone.Core.Test.ParserTests [TestCase("2020.NZ.2012.13.02.PDTV.XviD-C4TV", "2020nz", 2012, 2, 13)] [TestCase("2020.NZ.2011.12.02.PDTV.XviD-C4TV", "2020nz", 2011, 12, 2)] [TestCase("Series Title - 2013-10-30 - Episode Title (1) [HDTV-720p]", "Series Title", 2013, 10, 30)] + [TestCase("The_Voice_US_04.28.2014_hdtv.x264.Poke.mp4", "The Voice US", 2014, 4, 28)] public void should_parse_daily_episode(string postTitle, string title, int year, int month, int day) { var result = Parser.Parser.ParseTitle(postTitle); diff --git a/src/NzbDrone.Core.Test/ParserTests/QualityParserFixture.cs b/src/NzbDrone.Core.Test/ParserTests/QualityParserFixture.cs index a3a7c4a58..8ef71e8d3 100644 --- a/src/NzbDrone.Core.Test/ParserTests/QualityParserFixture.cs +++ b/src/NzbDrone.Core.Test/ParserTests/QualityParserFixture.cs @@ -55,6 +55,7 @@ namespace NzbDrone.Core.Test.ParserTests [TestCase("The.Girls.Next.Door.S03E06.DVDRip.XviD-WiDE", false)] [TestCase("The.Girls.Next.Door.S03E06.DVD.Rip.XviD-WiDE", false)] [TestCase("the.shield.1x13.circles.ws.xvidvd-tns", false)] + [TestCase("the_x-files.9x18.sunshine_days.ac3.ws_dvdrip_xvid-fov.avi", false)] public void should_parse_dvd_quality(string title, bool proper) { ParseAndVerifyQuality(title, Quality.DVD, proper); diff --git a/src/NzbDrone.Core.Test/ParserTests/ReleaseGroupParserFixture.cs b/src/NzbDrone.Core.Test/ParserTests/ReleaseGroupParserFixture.cs index 7e84877d4..7c1504d4a 100644 --- a/src/NzbDrone.Core.Test/ParserTests/ReleaseGroupParserFixture.cs +++ b/src/NzbDrone.Core.Test/ParserTests/ReleaseGroupParserFixture.cs @@ -9,8 +9,8 @@ namespace NzbDrone.Core.Test.ParserTests public class ReleaseGroupParserFixture : CoreTest { [TestCase("Castle.2009.S01E14.English.HDTV.XviD-LOL", "LOL")] - [TestCase("Castle 2009 S01E14 English HDTV XviD LOL", "LOL")] - [TestCase("Acropolis Now S05 EXTRAS DVDRip XviD RUNNER", "RUNNER")] + [TestCase("Castle 2009 S01E14 English HDTV XviD LOL", "DRONE")] + [TestCase("Acropolis Now S05 EXTRAS DVDRip XviD RUNNER", "DRONE")] [TestCase("Punky.Brewster.S01.EXTRAS.DVDRip.XviD-RUNNER", "RUNNER")] [TestCase("2020.NZ.2011.12.02.PDTV.XviD-C4TV", "C4TV")] [TestCase("The.Office.S03E115.DVDRip.XviD-OSiTV", "OSiTV")] @@ -18,6 +18,7 @@ namespace NzbDrone.Core.Test.ParserTests [TestCase("The Office - S01E01 - Pilot [HTDV-720p]", "DRONE")] [TestCase("The Office - S01E01 - Pilot [HTDV-1080p]", "DRONE")] [TestCase("The.Walking.Dead.S04E13.720p.WEB-DL.AAC2.0.H.264-Cyphanix", "Cyphanix")] + [TestCase("Arrow.S02E01.720p.WEB-DL.DD5.1.H.264.mkv", "DRONE")] public void should_parse_release_group(string title, string expected) { Parser.Parser.ParseReleaseGroup(title).Should().Be(expected); diff --git a/src/NzbDrone.Core.Test/ParserTests/SingleEpisodeParserFixture.cs b/src/NzbDrone.Core.Test/ParserTests/SingleEpisodeParserFixture.cs index fa6626113..bb0b8ecd2 100644 --- a/src/NzbDrone.Core.Test/ParserTests/SingleEpisodeParserFixture.cs +++ b/src/NzbDrone.Core.Test/ParserTests/SingleEpisodeParserFixture.cs @@ -83,6 +83,7 @@ namespace NzbDrone.Core.Test.ParserTests [TestCase("Homeland - 2x12 - The Choice [HDTV-1080p].mkv", "Homeland", 2, 12)] [TestCase("Homeland - 2x4 - New Car Smell [HDTV-1080p].mkv", "Homeland", 2, 4)] [TestCase("Top Gear - 06x11 - 2005.08.07", "Top Gear", 6, 11)] + [TestCase("The_Voice_US_s06e19_04.28.2014_hdtv.x264.Poke.mp4", "The Voice US", 6, 19)] public void should_parse_single_episode(string postTitle, string title, int seasonNumber, int episodeNumber) { var result = Parser.Parser.ParseTitle(postTitle); diff --git a/src/NzbDrone.Core.Test/ProviderTests/DiskProviderTests/ArchiveProviderFixture.cs b/src/NzbDrone.Core.Test/ProviderTests/DiskProviderTests/ArchiveProviderFixture.cs index a9f3e2f0d..6f4cacea5 100644 --- a/src/NzbDrone.Core.Test/ProviderTests/DiskProviderTests/ArchiveProviderFixture.cs +++ b/src/NzbDrone.Core.Test/ProviderTests/DiskProviderTests/ArchiveProviderFixture.cs @@ -13,12 +13,10 @@ namespace NzbDrone.Core.Test.ProviderTests.DiskProviderTests [Test] public void Should_extract_to_correct_folder() { - var destination = Path.Combine(TempFolder, "destination"); + var destinationFolder = new DirectoryInfo(GetTempFilePath()); var testArchive = OsInfo.IsWindows ? "TestArchive.zip" : "TestArchive.tar.gz"; - Subject.Extract(GetTestFilePath(testArchive), destination); - - var destinationFolder = new DirectoryInfo(destination); + Subject.Extract(Path.Combine("Files", testArchive), destinationFolder.FullName); destinationFolder.Exists.Should().BeTrue(); destinationFolder.GetDirectories().Should().HaveCount(1); diff --git a/src/NzbDrone.Core.Test/UpdateTests/UpdateServiceFixture.cs b/src/NzbDrone.Core.Test/UpdateTests/UpdateServiceFixture.cs index 357463bdf..a414ea8eb 100644 --- a/src/NzbDrone.Core.Test/UpdateTests/UpdateServiceFixture.cs +++ b/src/NzbDrone.Core.Test/UpdateTests/UpdateServiceFixture.cs @@ -128,7 +128,7 @@ namespace NzbDrone.Core.Test.UpdateTests Subject.Execute(new ApplicationUpdateCommand()); - ExceptionVerification.AssertNoUnexcpectedLogs(); + ExceptionVerification.AssertNoUnexpectedLogs(); } [Test] diff --git a/src/NzbDrone.Core/Blacklisting/Blacklist.cs b/src/NzbDrone.Core/Blacklisting/Blacklist.cs index 19dd800a6..91c927f05 100644 --- a/src/NzbDrone.Core/Blacklisting/Blacklist.cs +++ b/src/NzbDrone.Core/Blacklisting/Blacklist.cs @@ -2,12 +2,14 @@ using System.Collections.Generic; using NzbDrone.Core.Datastore; using NzbDrone.Core.Qualities; +using NzbDrone.Core.Tv; namespace NzbDrone.Core.Blacklisting { public class Blacklist : ModelBase { public Int32 SeriesId { get; set; } + public Series Series { get; set; } public List EpisodeIds { get; set; } public String SourceTitle { get; set; } public QualityModel Quality { get; set; } diff --git a/src/NzbDrone.Core/Blacklisting/BlacklistRepository.cs b/src/NzbDrone.Core/Blacklisting/BlacklistRepository.cs index 4e105865f..681fcdf98 100644 --- a/src/NzbDrone.Core/Blacklisting/BlacklistRepository.cs +++ b/src/NzbDrone.Core/Blacklisting/BlacklistRepository.cs @@ -1,6 +1,8 @@ using System.Collections.Generic; using NzbDrone.Core.Datastore; using NzbDrone.Core.Messaging.Events; +using Marr.Data.QGen; +using NzbDrone.Core.Tv; namespace NzbDrone.Core.Blacklisting { @@ -27,5 +29,12 @@ namespace NzbDrone.Core.Blacklisting { return Query.Where(b => b.SeriesId == seriesId); } + + protected override SortBuilder GetPagedQuery(QueryBuilder query, PagingSpec pagingSpec) + { + var baseQuery = query.Join(JoinType.Inner, h => h.Series, (h, s) => h.SeriesId == s.Id); + + return base.GetPagedQuery(baseQuery, pagingSpec); + } } } diff --git a/src/NzbDrone.Core/Datastore/BasicRepository.cs b/src/NzbDrone.Core/Datastore/BasicRepository.cs index bb1173b3b..ce5287472 100644 --- a/src/NzbDrone.Core/Datastore/BasicRepository.cs +++ b/src/NzbDrone.Core/Datastore/BasicRepository.cs @@ -6,7 +6,7 @@ using Marr.Data; using Marr.Data.QGen; using NzbDrone.Core.Datastore.Events; using NzbDrone.Common; -using NzbDrone.Core.Datastore.Extentions; +using NzbDrone.Core.Datastore.Extensions; using NzbDrone.Core.Messaging.Events; diff --git a/src/NzbDrone.Core/Datastore/Extentions/MappingExtensions.cs b/src/NzbDrone.Core/Datastore/Extensions/MappingExtensions.cs similarity index 97% rename from src/NzbDrone.Core/Datastore/Extentions/MappingExtensions.cs rename to src/NzbDrone.Core/Datastore/Extensions/MappingExtensions.cs index e5a000004..090c2560c 100644 --- a/src/NzbDrone.Core/Datastore/Extentions/MappingExtensions.cs +++ b/src/NzbDrone.Core/Datastore/Extensions/MappingExtensions.cs @@ -4,7 +4,7 @@ using Marr.Data; using Marr.Data.Mapping; using NzbDrone.Common.Reflection; -namespace NzbDrone.Core.Datastore.Extentions +namespace NzbDrone.Core.Datastore.Extensions { public static class MappingExtensions { diff --git a/src/NzbDrone.Core/Datastore/Extentions/PagingSpecExtensions.cs b/src/NzbDrone.Core/Datastore/Extensions/PagingSpecExtensions.cs similarity index 96% rename from src/NzbDrone.Core/Datastore/Extentions/PagingSpecExtensions.cs rename to src/NzbDrone.Core/Datastore/Extensions/PagingSpecExtensions.cs index d5593876e..39cc5b7a6 100644 --- a/src/NzbDrone.Core/Datastore/Extentions/PagingSpecExtensions.cs +++ b/src/NzbDrone.Core/Datastore/Extensions/PagingSpecExtensions.cs @@ -2,7 +2,7 @@ using System.Linq; using System.Linq.Expressions; -namespace NzbDrone.Core.Datastore.Extentions +namespace NzbDrone.Core.Datastore.Extensions { public static class PagingSpecExtensions { diff --git a/src/NzbDrone.Core/Datastore/Extentions/RelationshipExtensions.cs b/src/NzbDrone.Core/Datastore/Extensions/RelationshipExtensions.cs similarity index 97% rename from src/NzbDrone.Core/Datastore/Extentions/RelationshipExtensions.cs rename to src/NzbDrone.Core/Datastore/Extensions/RelationshipExtensions.cs index 6bade070f..2e40accd4 100644 --- a/src/NzbDrone.Core/Datastore/Extentions/RelationshipExtensions.cs +++ b/src/NzbDrone.Core/Datastore/Extensions/RelationshipExtensions.cs @@ -4,7 +4,7 @@ using System.Linq.Expressions; using Marr.Data; using Marr.Data.Mapping; -namespace NzbDrone.Core.Datastore.Extentions +namespace NzbDrone.Core.Datastore.Extensions { public static class RelationshipExtensions { diff --git a/src/NzbDrone.Core/Datastore/TableMapping.cs b/src/NzbDrone.Core/Datastore/TableMapping.cs index 02c728f22..74ab43f69 100644 --- a/src/NzbDrone.Core/Datastore/TableMapping.cs +++ b/src/NzbDrone.Core/Datastore/TableMapping.cs @@ -7,7 +7,7 @@ using NzbDrone.Core.Blacklisting; using NzbDrone.Core.Configuration; using NzbDrone.Core.DataAugmentation.Scene; using NzbDrone.Core.Datastore.Converters; -using NzbDrone.Core.Datastore.Extentions; +using NzbDrone.Core.Datastore.Extensions; using NzbDrone.Core.Download; using NzbDrone.Core.Indexers; using NzbDrone.Core.Instrumentation; diff --git a/src/NzbDrone.Core/DecisionEngine/Specifications/AcceptableSizeSpecification.cs b/src/NzbDrone.Core/DecisionEngine/Specifications/AcceptableSizeSpecification.cs index 5073ca546..1d776f3e1 100644 --- a/src/NzbDrone.Core/DecisionEngine/Specifications/AcceptableSizeSpecification.cs +++ b/src/NzbDrone.Core/DecisionEngine/Specifications/AcceptableSizeSpecification.cs @@ -4,6 +4,7 @@ using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Qualities; using NzbDrone.Core.Tv; +using System.Collections.Generic; namespace NzbDrone.Core.DecisionEngine.Specifications { @@ -66,10 +67,27 @@ namespace NzbDrone.Core.DecisionEngine.Specifications //Multiply maxSize by Series.Runtime maxSize = maxSize * subject.Series.Runtime * subject.Episodes.Count; - //Check if there was only one episode parsed and it is the first - if (subject.Episodes.Count == 1 && _episodeService.IsFirstOrLastEpisodeOfSeason(subject.Episodes.First().Id)) + if (subject.Episodes.Count == 1) { - maxSize = maxSize * 2; + Episode episode = subject.Episodes.First(); + List seasonEpisodes; + + var seasonSearchCriteria = searchCriteria as SeasonSearchCriteria; + if (seasonSearchCriteria != null && !seasonSearchCriteria.Series.UseSceneNumbering && seasonSearchCriteria.Episodes.Any(v => v.Id == episode.Id)) + { + seasonEpisodes = (searchCriteria as SeasonSearchCriteria).Episodes; + } + else + { + seasonEpisodes = _episodeService.GetEpisodesBySeason(episode.SeriesId, episode.SeasonNumber); + } + + //Ensure that this is either the first episode + //or is the last episode in a season that has 10 or more episodes + if (seasonEpisodes.First().Id == episode.Id || (seasonEpisodes.Count() >= 10 && seasonEpisodes.Last().Id == episode.Id)) + { + maxSize = maxSize * 2; + } } //If the parsed size is greater than maxSize we don't want it diff --git a/src/NzbDrone.Core/Jobs/TaskManager.cs b/src/NzbDrone.Core/Jobs/TaskManager.cs index 4c7daba7e..459b2ddb5 100644 --- a/src/NzbDrone.Core/Jobs/TaskManager.cs +++ b/src/NzbDrone.Core/Jobs/TaskManager.cs @@ -100,6 +100,9 @@ namespace NzbDrone.Core.Jobs public void Handle(CommandExecutedEvent message) { + if (message.Command.GetType().Name == "BroadcastSignalRMessage") + return; + var scheduledTask = _scheduledTaskRepository.All().SingleOrDefault(c => c.TypeName == message.Command.GetType().FullName); if (scheduledTask != null) diff --git a/src/NzbDrone.Core/NzbDrone.Core.csproj b/src/NzbDrone.Core/NzbDrone.Core.csproj index b8938f15e..5e81c437d 100644 --- a/src/NzbDrone.Core/NzbDrone.Core.csproj +++ b/src/NzbDrone.Core/NzbDrone.Core.csproj @@ -138,9 +138,9 @@ - - - + + + diff --git a/src/NzbDrone.Core/Parser/Parser.cs b/src/NzbDrone.Core/Parser/Parser.cs index 5b4cf8d2d..986e13f47 100644 --- a/src/NzbDrone.Core/Parser/Parser.cs +++ b/src/NzbDrone.Core/Parser/Parser.cs @@ -24,15 +24,15 @@ namespace NzbDrone.Core.Parser //Anime - [SubGroup] Title Absolute Episode Number + Season+Episode new Regex(@"^(?:\[(?.+?)\](?:_|-|\s|\.))(?.+?)(?:(?:\W|_)+(?<absoluteepisode>\d{2,3}))+(?:_|-|\s|\.)+(?:S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:\-|[ex]|\W[ex]){1,2}(?<episode>\d{2}(?!\d+)))+)", - RegexOptions.IgnoreCase | RegexOptions.Compiled), + RegexOptions.IgnoreCase | RegexOptions.Compiled), //Anime - [SubGroup] Title Season+Episode + Absolute Episode Number new Regex(@"^(?:\[(?<subgroup>.+?)\](?:_|-|\s|\.))(?<title>.+?)(?:\W|_)+(?:S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:\-|[ex]|\W[ex]){1,2}(?<episode>\d{2}(?!\d+)))+)(?:\s|\.)(?:(?<absoluteepisode>\d{2,3})(?:_|-|\s|\.|$)+)+", - RegexOptions.IgnoreCase | RegexOptions.Compiled), + RegexOptions.IgnoreCase | RegexOptions.Compiled), //Anime - [SubGroup] Title Absolute Episode Number new Regex(@"^\[(?<subgroup>.+?)\](?:_|-|\s|\.)?(?<title>.+?)(?:(?:\W|_)+(?<absoluteepisode>\d{2,}))+", - RegexOptions.IgnoreCase | RegexOptions.Compiled), + RegexOptions.IgnoreCase | RegexOptions.Compiled), //Multi-Part episodes without a title (S01E05.S01E06) new Regex(@"^(?:\W*S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:[ex]){1,2}(?<episode>\d{1,3}(?!\d+)))+){2,}", @@ -60,7 +60,7 @@ namespace NzbDrone.Core.Parser //Anime - Title Absolute Episode Number [SubGroup] new Regex(@"^(?<title>.+?)(?:(?:_|-|\s|\.)+(?<absoluteepisode>\d{3}(?!\d+)))+(?:.+?)\[(?<subgroup>.+?)\](?:\.|$)", - RegexOptions.IgnoreCase | RegexOptions.Compiled), + RegexOptions.IgnoreCase | RegexOptions.Compiled), //Supports 103/113 naming new Regex(@"^(?<title>.+?)?(?:\W?(?<season>(?<!\d+)\d{1})(?<episode>\d{2}(?!\w|\d+)))+", @@ -97,7 +97,7 @@ namespace NzbDrone.Core.Parser //Anime - Title Absolute Episode Number new Regex(@"^(?<title>.+?)(?:(?:_|-|\s|\.)+e(?<absoluteepisode>\d{2,3}))+", - RegexOptions.IgnoreCase | RegexOptions.Compiled) + RegexOptions.IgnoreCase | RegexOptions.Compiled) }; private static readonly Regex[] RejectHashedReleasesRegex = new Regex[] @@ -113,10 +113,16 @@ namespace NzbDrone.Core.Parser private static readonly Regex ReversedTitleRegex = new Regex(@"\.p027\.|\.p0801\.|\.\d{2}E\d{2}S\.", RegexOptions.Compiled); private static readonly Regex NormalizeRegex = new Regex(@"((?:\b|_)(?<!^)(a|an|the|and|or|of)(?:\b|_))|\W|_", - RegexOptions.IgnoreCase | RegexOptions.Compiled); + RegexOptions.IgnoreCase | RegexOptions.Compiled); private static readonly Regex SimpleTitleRegex = new Regex(@"480[i|p]|720[i|p]|1080[i|p]|[xh][\W_]?264|DD\W?5\W1|\<|\>|\?|\*|\:|\|", - RegexOptions.IgnoreCase | RegexOptions.Compiled); + RegexOptions.IgnoreCase | RegexOptions.Compiled); + + private static readonly Regex AirDateRegex = new Regex(@"^(.*?)(?<!\d)((?<airyear>\d{4})[_.-](?<airmonth>[0-1][0-9])[_.-](?<airday>[0-3][0-9])|(?<airmonth>[0-1][0-9])[_.-](?<airday>[0-3][0-9])[_.-](?<airyear>\d{4}))(?!\d)", + RegexOptions.IgnoreCase | RegexOptions.Compiled); + + private static readonly Regex ReleaseGroupRegex = new Regex(@"-(?<releasegroup>[a-z0-9]+)\b(?<!WEB-DL|480p|720p|1080p)", + RegexOptions.IgnoreCase | RegexOptions.Compiled); private static readonly Regex MultiPartCleanupRegex = new Regex(@"\(\d+\)$", RegexOptions.Compiled); @@ -124,14 +130,14 @@ namespace NzbDrone.Core.Parser RegexOptions.IgnoreCase | RegexOptions.Compiled); private static readonly Regex YearInTitleRegex = new Regex(@"^(?<title>.+?)(?:\W|_)?(?<year>\d{4})", - RegexOptions.IgnoreCase | RegexOptions.Compiled); + RegexOptions.IgnoreCase | RegexOptions.Compiled); private static readonly Regex WordDelimiterRegex = new Regex(@"(\s|\.|,|_|-|=|\|)+", RegexOptions.Compiled); private static readonly Regex PunctuationRegex = new Regex(@"[^\w\s]", RegexOptions.Compiled); private static readonly Regex CommonWordRegex = new Regex(@"\b(a|an|the|and|or|of)\b\s?", - RegexOptions.IgnoreCase | RegexOptions.Compiled); + RegexOptions.IgnoreCase | RegexOptions.Compiled); private static readonly Regex SpecialEpisodeWordRegex = new Regex(@"\b(part|special|edition)\b\s?", - RegexOptions.IgnoreCase | RegexOptions.Compiled); + RegexOptions.IgnoreCase | RegexOptions.Compiled); public static ParsedEpisodeInfo ParsePath(string path) { @@ -180,6 +186,12 @@ namespace NzbDrone.Core.Parser var simpleTitle = SimpleTitleRegex.Replace(title, String.Empty); + var airDateMatch = AirDateRegex.Match(simpleTitle); + if (airDateMatch.Success) + { + simpleTitle = airDateMatch.Groups[1].Value + airDateMatch.Groups["airyear"].Value + "." + airDateMatch.Groups["airmonth"].Value + "." + airDateMatch.Groups["airday"].Value; + } + foreach (var regex in ReportTitleRegex) { var match = regex.Matches(simpleTitle); @@ -272,24 +284,13 @@ namespace NzbDrone.Core.Parser title = title.TrimEnd("-RP"); - var index = title.LastIndexOf('-'); - - if (index < 0) - index = title.LastIndexOf(' '); - - if (index < 0) - return defaultReleaseGroup; - - var group = title.Substring(index + 1); - - if (group.Length == title.Length) - return String.Empty; - - group = group.Trim('-', ' ', '[', ']'); - - if (group.ToLower() == "480p" || - group.ToLower() == "720p" || - group.ToLower() == "1080p") + string group; + var matches = ReleaseGroupRegex.Matches(title); + if (matches.Count != 0) + { + group = matches.OfType<Match>().Last().Groups["releasegroup"].Value; + } + else { return defaultReleaseGroup; } diff --git a/src/NzbDrone.Core/Parser/QualityParser.cs b/src/NzbDrone.Core/Parser/QualityParser.cs index c21cb3e19..b45c3d281 100644 --- a/src/NzbDrone.Core/Parser/QualityParser.cs +++ b/src/NzbDrone.Core/Parser/QualityParser.cs @@ -13,37 +13,50 @@ namespace NzbDrone.Core.Parser { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - private static readonly Regex SourceRegex = new Regex(@"(?<bluray>BluRay)| + private static readonly Regex SourceRegex = new Regex(@"\b(?: + (?<bluray>BluRay)| (?<webdl>WEB-DL|WEBDL|WEB\sDL|WEB\-DL|WebRip)| (?<hdtv>HDTV)| - (?<bdrip>BDRiP)|(?<brrip>BRRip)|(?<dvd>\b(?:DVD|DVDRip|NTSC|PAL|xvidvd)\b)| - (?<dsr>WS\sDSR|WS_DSR|WS\.DSR|DSR)|(?<pdtv>PDTV)|(?<sdtv>SDTV)", - RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); + (?<bdrip>BDRiP)| + (?<brrip>BRRip)| + (?<dvd>DVD|DVDRip|NTSC|PAL|xvidvd)| + (?<dsr>WS\sDSR|WS_DSR|WS\.DSR|DSR)| + (?<pdtv>PDTV)| + (?<sdtv>SDTV) + )\b", + RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); - private static readonly Regex ResolutionRegex = new Regex(@"(?<_480p>480p)|(?<_720p>720p)|(?<_1080p>1080p)", - RegexOptions.Compiled | RegexOptions.IgnoreCase); + private static readonly Regex RawHDRegex = new Regex(@"\b(?<rawhd>TrollHD|RawHD)\b", + RegexOptions.Compiled | RegexOptions.IgnoreCase); - private static readonly Regex CodecRegex = new Regex(@"(?<x264>x264)|(?<h264>h264)|(?<xvidhd>XvidHD)|(?<xvid>Xvid)|(?<divx>divx)", - RegexOptions.Compiled | RegexOptions.IgnoreCase); + private static readonly Regex ProperRegex = new Regex(@"\b(?<proper>proper|repack)\b", + RegexOptions.Compiled | RegexOptions.IgnoreCase); + + private static readonly Regex ResolutionRegex = new Regex(@"\b(?:(?<_480p>480p)|(?<_720p>720p)|(?<_1080p>1080p))\b", + RegexOptions.Compiled | RegexOptions.IgnoreCase); + + private static readonly Regex CodecRegex = new Regex(@"\b(?:(?<x264>x264)|(?<h264>h264)|(?<xvidhd>XvidHD)|(?<xvid>Xvid)|(?<divx>divx))\b", + RegexOptions.Compiled | RegexOptions.IgnoreCase); public static QualityModel ParseQuality(string name) { Logger.Debug("Trying to parse quality for {0}", name); name = name.Trim(); - var normalizedName = name.CleanSeriesTitle(); + var normalizedName = name.Replace('_', ' ').Trim().ToLower(); var result = new QualityModel { Quality = Quality.Unknown }; - result.Proper = (normalizedName.Contains("proper") || normalizedName.Contains("repack")); - if (normalizedName.Contains("trollhd") || normalizedName.Contains("rawhd")) + result.Proper = ProperRegex.IsMatch(normalizedName); + + if (RawHDRegex.IsMatch(normalizedName)) { result.Quality = Quality.RAWHD; return result; } - - var sourceMatch = SourceRegex.Match(name); - var resolution = ParseResolution(name); - var codecRegex = CodecRegex.Match(name); + + var sourceMatch = SourceRegex.Match(normalizedName); + var resolution = ParseResolution(normalizedName); + var codecRegex = CodecRegex.Match(normalizedName); if (sourceMatch.Groups["bluray"].Success) { @@ -111,9 +124,27 @@ namespace NzbDrone.Core.Parser return result; } - if (sourceMatch.Groups["dvd"].Success || - sourceMatch.Groups["bdrip"].Success || + if (sourceMatch.Groups["bdrip"].Success || sourceMatch.Groups["brrip"].Success) + { + if (resolution == Resolution._720p) + { + result.Quality = Quality.Bluray720p; + return result; + } + else if (resolution == Resolution._1080p) + { + result.Quality = Quality.Bluray1080p; + return result; + } + else + { + result.Quality = Quality.DVD; + return result; + } + } + + if (sourceMatch.Groups["dvd"].Success) { result.Quality = Quality.DVD; return result; diff --git a/src/NzbDrone.Core/Qualities/QualityDefinitionService.cs b/src/NzbDrone.Core/Qualities/QualityDefinitionService.cs index 9895461ec..a388f1667 100644 --- a/src/NzbDrone.Core/Qualities/QualityDefinitionService.cs +++ b/src/NzbDrone.Core/Qualities/QualityDefinitionService.cs @@ -4,6 +4,7 @@ using NLog; using NzbDrone.Core.Lifecycle; using NzbDrone.Core.Messaging.Events; using System; +using NzbDrone.Common.Cache; namespace NzbDrone.Core.Qualities { @@ -17,22 +18,31 @@ namespace NzbDrone.Core.Qualities public class QualityDefinitionService : IQualityDefinitionService, IHandle<ApplicationStartedEvent> { private readonly IQualityDefinitionRepository _qualityDefinitionRepository; + private readonly ICached<Dictionary<Quality, QualityDefinition>> _cache; private readonly Logger _logger; - public QualityDefinitionService(IQualityDefinitionRepository qualityDefinitionRepository, Logger logger) + public QualityDefinitionService(IQualityDefinitionRepository qualityDefinitionRepository, ICacheManager cacheManager, Logger logger) { _qualityDefinitionRepository = qualityDefinitionRepository; + _cache = cacheManager.GetCache<Dictionary<Quality, QualityDefinition>>(this.GetType()); _logger = logger; } + private Dictionary<Quality, QualityDefinition> GetAll() + { + return _cache.Get("all", () => _qualityDefinitionRepository.All().ToDictionary(v => v.Quality), TimeSpan.FromSeconds(5.0)); + } + public void Update(QualityDefinition qualityDefinition) { _qualityDefinitionRepository.Update(qualityDefinition); + + _cache.Clear(); } public List<QualityDefinition> All() { - return _qualityDefinitionRepository.All().ToList(); + return GetAll().Values.ToList(); } public QualityDefinition Get(Quality quality) @@ -40,7 +50,7 @@ namespace NzbDrone.Core.Qualities if (quality == Quality.Unknown) return new QualityDefinition(Quality.Unknown); - return _qualityDefinitionRepository.GetByQualityId((int)quality); + return GetAll()[quality]; } public void InsertMissingDefinitions(List<QualityDefinition> allDefinitions) @@ -89,10 +99,12 @@ namespace NzbDrone.Core.Qualities _qualityDefinitionRepository.Update(existingDefinitions[i]); } } + + _cache.Clear(); } public void Handle(ApplicationStartedEvent message) - { + { _logger.Debug("Setting up default quality config"); InsertMissingDefinitions(Quality.DefaultQualityDefinitions.ToList()); diff --git a/src/NzbDrone.Core/Tv/EpisodeRepository.cs b/src/NzbDrone.Core/Tv/EpisodeRepository.cs index 2a6a1792e..db43e8f26 100644 --- a/src/NzbDrone.Core/Tv/EpisodeRepository.cs +++ b/src/NzbDrone.Core/Tv/EpisodeRepository.cs @@ -5,7 +5,7 @@ using System.Linq; using Marr.Data.QGen; using NLog; using NzbDrone.Core.Datastore; -using NzbDrone.Core.Datastore.Extentions; +using NzbDrone.Core.Datastore.Extensions; using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.MediaFiles; using NzbDrone.Core.Qualities; diff --git a/src/NzbDrone.Core/Tv/EpisodeService.cs b/src/NzbDrone.Core/Tv/EpisodeService.cs index 402642e0a..09c073e56 100644 --- a/src/NzbDrone.Core/Tv/EpisodeService.cs +++ b/src/NzbDrone.Core/Tv/EpisodeService.cs @@ -27,7 +27,6 @@ namespace NzbDrone.Core.Tv List<Episode> GetEpisodesByFileId(int episodeFileId); void UpdateEpisode(Episode episode); void SetEpisodeMonitored(int episodeId, bool monitored); - bool IsFirstOrLastEpisodeOfSeason(int episodeId); void UpdateEpisodes(List<Episode> episodes); List<Episode> EpisodesBetweenDates(DateTime start, DateTime end); void InsertMany(List<Episode> episodes); @@ -141,19 +140,6 @@ namespace NzbDrone.Core.Tv _episodeRepository.SetMonitoredBySeason(seriesId, seasonNumber, monitored); } - public bool IsFirstOrLastEpisodeOfSeason(int episodeId) - { - var episode = GetEpisode(episodeId); - var seasonEpisodes = GetEpisodesBySeason(episode.SeriesId, episode.SeasonNumber); - - //Ensure that this is either the first episode - //or is the last episode in a season that has 10 or more episodes - if (seasonEpisodes.First().EpisodeNumber == episode.EpisodeNumber || (seasonEpisodes.Count() >= 10 && seasonEpisodes.Last().EpisodeNumber == episode.EpisodeNumber)) - return true; - - return false; - } - public void UpdateEpisodes(List<Episode> episodes) { _episodeRepository.UpdateMany(episodes); diff --git a/src/NzbDrone.Mono.Test/DiskProviderTests/DiskProviderFixture.cs b/src/NzbDrone.Mono.Test/DiskProviderTests/DiskProviderFixture.cs index dffd16153..542cf6d58 100644 --- a/src/NzbDrone.Mono.Test/DiskProviderTests/DiskProviderFixture.cs +++ b/src/NzbDrone.Mono.Test/DiskProviderTests/DiskProviderFixture.cs @@ -4,6 +4,7 @@ using NzbDrone.Common.Test.DiskProviderTests; namespace NzbDrone.Mono.Test.DiskProviderTests { [TestFixture] + [Platform("Mono")] public class DiskProviderFixture : DiskProviderFixtureBase<DiskProvider> { public DiskProviderFixture() diff --git a/src/NzbDrone.Mono.Test/DiskProviderTests/FreeSpaceFixture.cs b/src/NzbDrone.Mono.Test/DiskProviderTests/FreeSpaceFixture.cs index 109fb4825..768fb73fa 100644 --- a/src/NzbDrone.Mono.Test/DiskProviderTests/FreeSpaceFixture.cs +++ b/src/NzbDrone.Mono.Test/DiskProviderTests/FreeSpaceFixture.cs @@ -4,6 +4,7 @@ using NzbDrone.Common.Test.DiskProviderTests; namespace NzbDrone.Mono.Test.DiskProviderTests { [TestFixture] + [Platform("Mono")] public class FreeSpaceFixture : FreeSpaceFixtureBase<DiskProvider> { public FreeSpaceFixture() diff --git a/src/NzbDrone.Mono.Test/ServiceFactoryFixture.cs b/src/NzbDrone.Mono.Test/ServiceFactoryFixture.cs index 1d5e77f87..811edfc66 100644 --- a/src/NzbDrone.Mono.Test/ServiceFactoryFixture.cs +++ b/src/NzbDrone.Mono.Test/ServiceFactoryFixture.cs @@ -13,15 +13,13 @@ namespace NzbDrone.Mono.Test [TestFixture] public class ServiceFactoryFixture : TestBase<ServiceFactory> { - [SetUp] - public void setup() - { - Mocker.SetConstant(MainAppContainerBuilder.BuildContainer(new StartupContext())); - } - [Test] public void event_handlers_should_be_unique() { + MonoOnly(); + + Mocker.SetConstant(MainAppContainerBuilder.BuildContainer(new StartupContext())); + var handlers = Subject.BuildAll<IHandle<ApplicationShutdownRequested>>() .Select(c => c.GetType().FullName); diff --git a/src/NzbDrone.Test.Common/ExceptionVerification.cs b/src/NzbDrone.Test.Common/ExceptionVerification.cs index 6d98c912f..79bb6c2c7 100644 --- a/src/NzbDrone.Test.Common/ExceptionVerification.cs +++ b/src/NzbDrone.Test.Common/ExceptionVerification.cs @@ -26,7 +26,7 @@ namespace NzbDrone.Test.Common _logs = new List<LogEventInfo>(); } - public static void AssertNoUnexcpectedLogs() + public static void AssertNoUnexpectedLogs() { ExpectedFatals(0); ExpectedErrors(0); diff --git a/src/NzbDrone.Test.Common/LoggingTest.cs b/src/NzbDrone.Test.Common/LoggingTest.cs index 4d11d696a..f7ad739fb 100644 --- a/src/NzbDrone.Test.Common/LoggingTest.cs +++ b/src/NzbDrone.Test.Common/LoggingTest.cs @@ -50,7 +50,7 @@ namespace NzbDrone.Test.Common //https://bugs.launchpad.net/nunitv2/+bug/1076932 if (BuildInfo.IsDebug && TestContext.CurrentContext.Result.State == TestState.Success) { - ExceptionVerification.AssertNoUnexcpectedLogs(); + ExceptionVerification.AssertNoUnexpectedLogs(); } } } diff --git a/src/NzbDrone.Test.Common/NzbDrone.Test.Common.csproj b/src/NzbDrone.Test.Common/NzbDrone.Test.Common.csproj index 2274be620..e871e8478 100644 --- a/src/NzbDrone.Test.Common/NzbDrone.Test.Common.csproj +++ b/src/NzbDrone.Test.Common/NzbDrone.Test.Common.csproj @@ -83,7 +83,7 @@ <Compile Include="LoggingTest.cs" /> <Compile Include="MockerExtensions.cs" /> <Compile Include="NzbDroneRunner.cs" /> - <Compile Include="ObjectExtentions.cs" /> + <Compile Include="ObjectExtensions.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="ReflectionExtensions.cs" /> <Compile Include="StringExtensions.cs" /> diff --git a/src/NzbDrone.Test.Common/ObjectExtentions.cs b/src/NzbDrone.Test.Common/ObjectExtensions.cs similarity index 85% rename from src/NzbDrone.Test.Common/ObjectExtentions.cs rename to src/NzbDrone.Test.Common/ObjectExtensions.cs index 40667ef8d..702797269 100644 --- a/src/NzbDrone.Test.Common/ObjectExtentions.cs +++ b/src/NzbDrone.Test.Common/ObjectExtensions.cs @@ -2,7 +2,7 @@ namespace NzbDrone.Test.Common { - public static class ObjectExtentions + public static class ObjectExtensions { public static T JsonClone<T>(this T source) where T : new() { diff --git a/src/NzbDrone.Test.Common/TestBase.cs b/src/NzbDrone.Test.Common/TestBase.cs index 403b52fec..b04231d57 100644 --- a/src/NzbDrone.Test.Common/TestBase.cs +++ b/src/NzbDrone.Test.Common/TestBase.cs @@ -109,9 +109,15 @@ namespace NzbDrone.Test.Common try { - if (Directory.Exists(TempFolder)) + var tempFolder = new DirectoryInfo(TempFolder); + if (tempFolder.Exists) { - Directory.Delete(TempFolder, true); + foreach (var file in tempFolder.GetFiles("*", SearchOption.AllDirectories)) + { + file.IsReadOnly = false; + } + + tempFolder.Delete(true); } } catch (Exception) @@ -119,7 +125,6 @@ namespace NzbDrone.Test.Common } } - protected IAppFolderInfo TestFolderInfo { get; private set; } protected void WindowsOnly() @@ -148,26 +153,11 @@ namespace NzbDrone.Test.Common TestFolderInfo = Mocker.GetMock<IAppFolderInfo>().Object; } - protected string GetTestFilePath(string fileName) - { - return Path.Combine(SandboxFolder, fileName); - } - - protected string GetTestFilePath() + protected string GetTempFilePath() { - return GetTestFilePath(Path.GetRandomFileName()); + return Path.Combine(TempFolder, Path.GetRandomFileName()); } - protected string SandboxFolder - { - get - { - var folder = Path.Combine(Directory.GetCurrentDirectory(), "Files"); - Directory.CreateDirectory(folder); - return folder; - } - - } protected void VerifyEventPublished<TEvent>() where TEvent : class, IEvent { VerifyEventPublished<TEvent>(Times.Once()); diff --git a/src/NzbDrone.Windows.Test/DiskProviderTests/DiskProviderFixture.cs b/src/NzbDrone.Windows.Test/DiskProviderTests/DiskProviderFixture.cs index 68b2d1f0c..f81c379f1 100644 --- a/src/NzbDrone.Windows.Test/DiskProviderTests/DiskProviderFixture.cs +++ b/src/NzbDrone.Windows.Test/DiskProviderTests/DiskProviderFixture.cs @@ -4,6 +4,7 @@ using NzbDrone.Common.Test.DiskProviderTests; namespace NzbDrone.Windows.Test.DiskProviderTests { [TestFixture] + [Platform("Win")] public class DiskProviderFixture : DiskProviderFixtureBase<DiskProvider> { public DiskProviderFixture() diff --git a/src/NzbDrone.Windows.Test/DiskProviderTests/FreeSpaceFixture.cs b/src/NzbDrone.Windows.Test/DiskProviderTests/FreeSpaceFixture.cs index a642b49a9..0334a6d3c 100644 --- a/src/NzbDrone.Windows.Test/DiskProviderTests/FreeSpaceFixture.cs +++ b/src/NzbDrone.Windows.Test/DiskProviderTests/FreeSpaceFixture.cs @@ -4,6 +4,7 @@ using NzbDrone.Common.Test.DiskProviderTests; namespace NzbDrone.Windows.Test.DiskProviderTests { [TestFixture] + [Platform("Win")] public class FreeSpaceFixture : FreeSpaceFixtureBase<DiskProvider> { public FreeSpaceFixture() diff --git a/src/UI/Settings/MediaManagement/FileManagement/FileManagementViewTemplate.html b/src/UI/Settings/MediaManagement/FileManagement/FileManagementViewTemplate.html index 6e7de342c..1290bd49f 100644 --- a/src/UI/Settings/MediaManagement/FileManagement/FileManagementViewTemplate.html +++ b/src/UI/Settings/MediaManagement/FileManagement/FileManagementViewTemplate.html @@ -1,4 +1,4 @@ -<fieldset class="advanced-setting"> +<fieldset> <legend>File Management</legend> <div class="control-group"> @@ -21,7 +21,7 @@ </div> </div> - <div class="control-group"> + <div class="control-group advanced-setting"> <label class="control-label">Download Propers</label> <div class="controls"> @@ -52,7 +52,7 @@ </div> </div> - <div class="control-group"> + <div class="control-group advanced-setting"> <label class="control-label">Change File Date</label> <div class="controls">