diff --git a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj
index 2d9d28c4c..218141dcd 100644
--- a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj
+++ b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj
@@ -92,8 +92,9 @@
-
+
+
diff --git a/NzbDrone.Core.Test/ProviderTests/HistoryProviderTest.cs b/NzbDrone.Core.Test/ProviderTests/HistoryProviderTest.cs
index cf5185e52..47f8272c8 100644
--- a/NzbDrone.Core.Test/ProviderTests/HistoryProviderTest.cs
+++ b/NzbDrone.Core.Test/ProviderTests/HistoryProviderTest.cs
@@ -1,6 +1,4 @@
-// ReSharper disable RedundantUsingDirective
-
-using System;
+using System;
using System.Linq;
using AutoMoq;
using FizzWare.NBuilder;
diff --git a/NzbDrone.Core.Test/ProviderTests/JobProviderTest.cs b/NzbDrone.Core.Test/ProviderTests/JobProviderTest.cs
index 5838f2ec3..348de3750 100644
--- a/NzbDrone.Core.Test/ProviderTests/JobProviderTest.cs
+++ b/NzbDrone.Core.Test/ProviderTests/JobProviderTest.cs
@@ -104,14 +104,12 @@ namespace NzbDrone.Core.Test.ProviderTests
timerProvider.QueueJob(typeof(FakeJob));
Thread.Sleep(1000);
timerProvider.QueueJob(typeof(FakeJob));
- Thread.Sleep(1000);
+ Thread.Sleep(2000);
JobProvider.Queue.Should().BeEmpty();
fakeJob.ExecutionCount.Should().Be(2);
}
[Test]
- //This test will confirm that the concurrency checks are rest
- //after execution so the job can successfully run.
public void no_concurent_jobs()
{
IList fakeJobs = new List { new SlowJob() };
@@ -127,7 +125,7 @@ namespace NzbDrone.Core.Test.ProviderTests
timerProvider.QueueJob(typeof(SlowJob), 3);
- Thread.Sleep(10000);
+ Thread.Sleep(5000);
JobProvider.Queue.Should().BeEmpty();
//Asserts are done in ExceptionVerification
}
@@ -538,7 +536,7 @@ namespace NzbDrone.Core.Test.ProviderTests
public void Start(ProgressNotification notification, int targetId, int secondaryTargetId)
{
Console.WriteLine("Starting Job");
- Thread.Sleep(2000);
+ Thread.Sleep(1000);
ExecutionCount++;
Console.WriteLine("Finishing Job");
}
diff --git a/NzbDrone.Core.Test/ProviderTests/PostDownloadProviderTest.cs b/NzbDrone.Core.Test/ProviderTests/PostDownloadProviderTest.cs
deleted file mode 100644
index 419933984..000000000
--- a/NzbDrone.Core.Test/ProviderTests/PostDownloadProviderTest.cs
+++ /dev/null
@@ -1,339 +0,0 @@
-// ReSharper disable RedundantUsingDirective
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using AutoMoq;
-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.Test.Framework;
-
-namespace NzbDrone.Core.Test.ProviderTests
-{
- [TestFixture]
- // ReSharper disable InconsistentNaming
- public class PostDownloadProviderTest : TestBase
- {
- [TestCase("_UNPACK_The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.Unpacking, 1)]
- [TestCase("_FAILED_The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.Failed, 1)]
- [TestCase("_UNPACK_The Office (US) - S01E01E02 - Episode Title", PostDownloadStatusType.Unpacking, 2)]
- [TestCase("_FAILED_The Office (US) - S01E01E02 - Episode Title", PostDownloadStatusType.Failed, 2)]
- [TestCase("_UNPACK_The Office (US) - Season 01 - Episode Title", PostDownloadStatusType.Unpacking, 10)]
- [TestCase("_FAILED_The Office (US) - Season 01 - Episode Title", PostDownloadStatusType.Failed, 10)]
- public void ProcessFailedOrUnpackingDownload(string folderName, PostDownloadStatusType postDownloadStatus, int episodeCount)
- {
- var db = MockLib.GetEmptyDatabase();
- var mocker = new AutoMoqer();
- mocker.SetConstant(db);
-
- var fakeSeries = Builder.CreateNew()
- .With(s => s.SeriesId = 12345)
- .With(s => s.CleanTitle = "officeus")
- .Build();
-
- var fakeEpisodes = Builder.CreateListOfSize(episodeCount)
- .All()
- .With(c => c.SeriesId = 12345)
- .With(c => c.SeasonNumber = 1)
- .With(c => c.PostDownloadStatus = PostDownloadStatusType.Unknown)
- .Build();
-
- var expectedEpisodesNumbers = fakeEpisodes.Select(e => e.EpisodeId).ToList();
-
- mocker.GetMock().Setup(s => s.FindSeries("officeus")).Returns(fakeSeries);
- mocker.GetMock().Setup(s => s.GetEpisodesByParseResult(It.IsAny(), false)).Returns(fakeEpisodes);
- mocker.GetMock().Setup(s => s.GetEpisodesBySeason(12345, 1)).Returns(fakeEpisodes);
- mocker.GetMock().Setup(
- s => s.SetPostDownloadStatus(expectedEpisodesNumbers, postDownloadStatus)).Verifiable();
-
- //Act
- mocker.Resolve().ProcessFailedOrUnpackingDownload(new DirectoryInfo(Path.Combine(Directory.GetCurrentDirectory(), folderName)), postDownloadStatus);
-
- //Assert
- mocker.GetMock().Verify(c => c.SetPostDownloadStatus(expectedEpisodesNumbers, postDownloadStatus), Times.Once());
- }
-
- [Test]
- public void ProcessFailedOrUnpackingDownload_Already_Existing_Time_Not_Passed()
- {
- var mocker = new AutoMoqer(MockBehavior.Strict);
-
- var path = Path.Combine(Directory.GetCurrentDirectory(),
- "_FAILED_The Office (US) - S01E01 - Episode Provider");
-
- var postDownloadStatus = PostDownloadStatusType.Failed;
-
- var postDownloadProvider = new PostDownloadProvider();
-
- var model = new PostDownloadInfoModel
- {
- Name = path,
- Status = postDownloadStatus,
- Added = DateTime.Now.AddMinutes(-5)
- };
-
- postDownloadProvider.Add(model);
-
- //Act
- mocker.Resolve().ProcessFailedOrUnpackingDownload(new DirectoryInfo(Path.Combine(Directory.GetCurrentDirectory(), path)), postDownloadStatus);
-
- //Assert
- mocker.VerifyAllMocks();
- postDownloadProvider.Remove(model);
- }
-
- [Test]
- public void ProcessFailedOrUnpackingDownload_Invalid_Episode()
- {
- var mocker = new AutoMoqer(MockBehavior.Strict);
-
- var path = Path.Combine(Directory.GetCurrentDirectory(),
- "_FAILED_The Office (US) - S01E01 - Episode Provider");
-
- var postDownloadStatus = PostDownloadStatusType.Failed;
-
- var fakeSeries = Builder.CreateNew()
- .With(s => s.SeriesId = 12345)
- .With(s => s.CleanTitle = "officeus")
- .Build();
-
- mocker.GetMock().Setup(s => s.FindSeries("officeus")).Returns(fakeSeries);
- mocker.GetMock().Setup(s => s.GetEpisodesByParseResult(It.IsAny(), false)).Returns(new List());
- mocker.GetMock().Setup(s => s.MoveDirectory(It.IsAny(), It.IsAny()));
-
- //Act
- mocker.Resolve().ProcessFailedOrUnpackingDownload(new DirectoryInfo(Path.Combine(Directory.GetCurrentDirectory(), path)), postDownloadStatus);
-
- //Assert
- ExceptionVerification.ExcpectedWarns(1);
- mocker.VerifyAllMocks();
- }
-
- [Test]
- public void ProcessDownload_InvalidSeries()
- {
- //Setup
- var mocker = new AutoMoqer(MockBehavior.Strict);
- var di = new DirectoryInfo(@"C:\Test\Unsorted TV\The Office - S01E01 - Episode Title");
-
- var newFolder = @"C:\Test\Unsorted TV\_NzbDrone_InvalidSeries_The Office - S01E01 - Episode Title";
- Series nullSeries = null;
-
- //Act
- mocker.GetMock().Setup(s => s.FindSeries("office")).Returns(nullSeries);
- mocker.GetMock().Setup(s => s.MoveDirectory(di.FullName, newFolder));
-
- mocker.Resolve().ProcessDownload(di);
-
- //Assert
- mocker.VerifyAllMocks();
- ExceptionVerification.ExcpectedWarns(1);
- }
-
- [Test]
- public void ProcessDownload_ParseError()
- {
- //Setup
- var mocker = new AutoMoqer(MockBehavior.Strict);
- var di = new DirectoryInfo(@"C:\Test\Unsorted TV\The Office - S01E01 - Episode Title");
-
- var newFolder = @"C:\Test\Unsorted TV\_NzbDrone_ParseError_The Office - S01E01 - Episode Title";
-
- var fakeSeries = Builder.CreateNew()
- .With(s => s.Title = "The Office")
- .Build();
-
- //Act
- mocker.GetMock().Setup(s => s.FindSeries("office")).Returns(fakeSeries);
- mocker.GetMock().Setup(s => s.MoveDirectory(di.FullName, newFolder));
- mocker.GetMock().Setup(s => s.GetDirectorySize(di.FullName)).Returns(100.Megabytes());
- mocker.GetMock().Setup(s => s.Scan(fakeSeries, di.FullName)).Returns(
- new List());
-
- mocker.Resolve().ProcessDownload(di);
-
- //Assert
- mocker.VerifyAllMocks();
- ExceptionVerification.ExcpectedWarns(1);
- }
-
- [Test]
- public void ProcessDownload_Unknown_Error()
- {
- //Setup
- var mocker = new AutoMoqer(MockBehavior.Strict);
- var di = new DirectoryInfo(@"C:\Test\Unsorted TV\The Office - Season 01");
-
- var newFolder = @"C:\Test\Unsorted TV\_NzbDrone_The Office - Season 01";
-
- var fakeSeries = Builder.CreateNew()
- .With(s => s.Title = "The Office")
- .Build();
-
- var fakeEpisodeFiles = Builder.CreateListOfSize(2)
- .All()
- .With(f => f.SeriesId = fakeSeries.SeriesId)
- .Build().ToList();
-
- //Act
- mocker.GetMock().Setup(s => s.FindSeries("office")).Returns(fakeSeries);
- mocker.GetMock().Setup(s => s.MoveDirectory(di.FullName, newFolder));
- mocker.GetMock().Setup(s => s.GetDirectorySize(di.FullName)).Returns(100.Megabytes());
- mocker.GetMock().Setup(s => s.Scan(fakeSeries, di.FullName)).Returns(fakeEpisodeFiles);
- mocker.GetMock().Setup(s => s.MoveEpisodeFile(It.IsAny(), true)).Returns(true);
-
- mocker.Resolve().ProcessDownload(di);
-
- //Assert
- mocker.VerifyAllMocks();
- ExceptionVerification.ExcpectedWarns(1);
- }
-
- [Test]
- public void ProcessDownload_Success()
- {
- //Setup
- var mocker = new AutoMoqer(MockBehavior.Strict);
- var di = new DirectoryInfo(@"C:\Test\Unsorted TV\The Office - Season 01");
-
- var fakeSeries = Builder.CreateNew()
- .With(s => s.Title = "The Office")
- .Build();
-
- var fakeEpisodeFiles = Builder.CreateListOfSize(2)
- .All()
- .With(f => f.SeriesId = fakeSeries.SeriesId)
- .Build().ToList();
-
- //Act
- mocker.GetMock().Setup(s => s.FindSeries("office")).Returns(fakeSeries);
- mocker.GetMock().Setup(s => s.DeleteFolder(di.FullName, true));
- mocker.GetMock().Setup(s => s.GetDirectorySize(di.FullName)).Returns(1.Megabytes());
- mocker.GetMock().Setup(s => s.Scan(fakeSeries, di.FullName)).Returns(fakeEpisodeFiles);
- mocker.GetMock().Setup(s => s.MoveEpisodeFile(It.IsAny(), true)).Returns(true);
-
- mocker.Resolve().ProcessDownload(di);
-
- //Assert
- mocker.VerifyAllMocks();
- }
-
- [TestCase("_NzbDrone_InvalidEpisode_The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.InvalidEpisode)]
- [TestCase("_NzbDrone_InvalidSeries_The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.InvalidSeries)]
- [TestCase("_NzbDrone_ParseError_The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.ParseError)]
- [TestCase("_UNPACK_The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.Unpacking)]
- [TestCase("_FAILED_The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.Failed)]
- [TestCase("_NzbDrone_The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.Unknown)]
- [TestCase("The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.NoError)]
- public void GetPostDownloadStatusForFolder_should_return_a_proper_match(string folderName, PostDownloadStatusType expectedStatus)
- {
- //Setup
- var mocker = new AutoMoqer(MockBehavior.Strict);
-
- //Act
- var result = mocker.Resolve().GetPostDownloadStatusForFolder(folderName);
-
- //Assert
- result.Should().Be(expectedStatus);
- }
-
- [TestCase("_NzbDrone_InvalidEpisode_", "The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.InvalidSeries)]
- [TestCase("_NzbDrone_InvalidSeries_", "The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.InvalidEpisode)]
- [TestCase("_NzbDrone_ParseError_", "The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.InvalidSeries)]
- [TestCase("_UNPACK_", "The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.InvalidEpisode)]
- [TestCase("_FAILED_", "The Office (US) - S01E01 - Title", PostDownloadStatusType.ParseError)]
- [TestCase("_NzbDrone_", "The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.ParseError)]
- public void GetNewFolderNameWithPostDownloadStatus_should_return_a_string_with_the_error_removing_existing_error(string existingErrorString, string folderName, PostDownloadStatusType postDownloadStatus)
- {
- //Setup
- var mocker = new AutoMoqer(MockBehavior.Strict);
-
- var di = new DirectoryInfo(Path.Combine(Directory.GetCurrentDirectory(), existingErrorString + folderName));
- var expectedFolderName = String.Format("_NzbDrone_{0}_{1}", postDownloadStatus.ToString(), folderName);
-
- var expectedResult = Path.Combine(Directory.GetCurrentDirectory(), expectedFolderName);
-
- //Act
- var result = mocker.Resolve().GetNewFolderNameWithPostDownloadStatus(di, postDownloadStatus);
-
- //Assert
- result.Should().Be(expectedResult);
- }
-
- [TestCase("The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.InvalidSeries)]
- [TestCase("The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.InvalidEpisode)]
- [TestCase("The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.ParseError)]
- public void GetNewFolderNameWithPostDownloadStatus_should_return_a_string_with_the_error(string folderName, PostDownloadStatusType postDownloadStatus)
- {
- //Setup
- var mocker = new AutoMoqer(MockBehavior.Strict);
-
- var di = new DirectoryInfo(Path.Combine(Directory.GetCurrentDirectory(), folderName));
- var expectedFolderName = String.Format("_NzbDrone_{0}_{1}", postDownloadStatus.ToString(), folderName);
-
- var expectedResult = Path.Combine(Directory.GetCurrentDirectory(), expectedFolderName);
-
- //Act
- var result = mocker.Resolve().GetNewFolderNameWithPostDownloadStatus(di, postDownloadStatus);
-
- //Assert
- result.Should().Be(expectedResult);
- }
-
- [TestCase("_NzbDrone_ParseError_", "The Office (US) - S01E01 - Episode Title")]
- [TestCase("", "The Office (US) - S01E01 - Episode Title")]
- public void GetNewFolderNameWithPostDownloadStatus_should_return_a_path_with_a_unknown_error(string existingError, string folderName)
- {
- //Setup
- var mocker = new AutoMoqer(MockBehavior.Strict);
-
- var di = new DirectoryInfo(Path.Combine(Directory.GetCurrentDirectory(), folderName));
- var expectedFolderName = String.Format("_NzbDrone_{0}", folderName);
-
- var expectedResult = Path.Combine(Directory.GetCurrentDirectory(), expectedFolderName);
-
- //Act
- var result = mocker.Resolve().GetNewFolderNameWithPostDownloadStatus(di, PostDownloadStatusType.Unknown);
-
- //Assert
- result.Should().Be(expectedResult);
- }
-
- [TestCase("_NzbDrone_ParseError_", "The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.NoError)]
- [TestCase("", "The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.NoError)]
- [TestCase("_NzbDrone_ParseError_", "The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.Processed)]
- [TestCase("", "The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.Processed)]
- public void GetNewFolderNameWithPostDownloadStatus_should_return_a_path_with_no_error(string existingError, string folderName, PostDownloadStatusType postDownloadStatus)
- {
- //Setup
- var mocker = new AutoMoqer(MockBehavior.Strict);
-
- var di = new DirectoryInfo(Path.Combine(Directory.GetCurrentDirectory(), folderName));
- var expectedFolderName = folderName;
-
- var expectedResult = Path.Combine(Directory.GetCurrentDirectory(), expectedFolderName);
-
- //Act
- var result = mocker.Resolve().GetNewFolderNameWithPostDownloadStatus(di, postDownloadStatus);
-
- //Assert
- result.Should().Be(expectedResult);
- }
-
- [TestCase("_NzbDrone_ParseError_The Office (US) - S01E01 - Episode Title", "The Office (US) - S01E01 - Episode Title")]
- [TestCase("_Status_The Office (US) - S01E01 - Episode Title", "The Office (US) - S01E01 - Episode Title")]
- [TestCase("The Office (US) - S01E01 - Episode Title", "The Office (US) - S01E01 - Episode Title")]
- [TestCase("_The Office (US) - S01E01 - Episode Title", "_The Office (US) - S01E01 - Episode Title")]
- public void RemoveStatus_should_remove_status_string_from_folder_name(string folderName, string cleanFolderName)
- {
- PostDownloadProvider.RemoveStatusFromFolderName(folderName).Should().Be(cleanFolderName);
- }
- }
-}
\ No newline at end of file
diff --git a/NzbDrone.Core.Test/ProviderTests/PostDownloadProviderTests/PostDownloadProviderFixture.cs b/NzbDrone.Core.Test/ProviderTests/PostDownloadProviderTests/PostDownloadProviderFixture.cs
new file mode 100644
index 000000000..ba71f228e
--- /dev/null
+++ b/NzbDrone.Core.Test/ProviderTests/PostDownloadProviderTests/PostDownloadProviderFixture.cs
@@ -0,0 +1,43 @@
+// ReSharper disable RedundantUsingDirective
+
+using System;
+using System.IO;
+using FluentAssertions;
+using NUnit.Framework;
+using NzbDrone.Core.Model;
+using NzbDrone.Core.Providers;
+using NzbDrone.Core.Test.Framework;
+
+namespace NzbDrone.Core.Test.ProviderTests
+{
+ [TestFixture]
+ // ReSharper disable InconsistentNaming
+ public class PostDownloadProviderFixture : TestBase
+ {
+ [TestCase(@"c:\_NzbDrone_InvalidEpisode_Title", @"c:\_UnknownSeries_Title", PostDownloadStatusType.UnknownSeries)]
+ [TestCase(@"c:\Title", @"c:\_Failed_Title", PostDownloadStatusType.Failed)]
+ [TestCase(@"c:\Root\Test Title", @"c:\Root\_ParseError_Test Title", PostDownloadStatusType.ParseError)]
+ public void GetFolderNameWithStatus_should_return_a_string_with_the_error_removing_existing_error(string currentName, string excpectedName, PostDownloadStatusType status)
+ {
+ PostDownloadProvider.GetFolderNameWithStatus(new DirectoryInfo(currentName), status).Should().Be(
+ excpectedName);
+ }
+
+ [TestCase(PostDownloadStatusType.NoError)]
+ [ExpectedException(typeof(InvalidOperationException))]
+ public void GetFolderNameWithStatus_should_throw_if_status_is_not_an_error(PostDownloadStatusType status)
+ {
+ PostDownloadProvider.GetFolderNameWithStatus(new DirectoryInfo(TempFolder), status);
+ }
+
+
+ [TestCase("_NzbDrone_ParseError_The Office (US) - S01E01 - Episode Title", "The Office (US) - S01E01 - Episode Title")]
+ [TestCase("_Status_The Office (US) - S01E01 - Episode Title", "The Office (US) - S01E01 - Episode Title")]
+ [TestCase("The Office (US) - S01E01 - Episode Title", "The Office (US) - S01E01 - Episode Title")]
+ [TestCase("_The Office (US) - S01E01 - Episode Title", "_The Office (US) - S01E01 - Episode Title")]
+ public void RemoveStatus_should_remove_status_string_from_folder_name(string folderName, string cleanFolderName)
+ {
+ PostDownloadProvider.RemoveStatusFromFolderName(folderName).Should().Be(cleanFolderName);
+ }
+ }
+}
\ No newline at end of file
diff --git a/NzbDrone.Core.Test/ProviderTests/PostDownloadProviderTests/ProcessDownloadFixture.cs b/NzbDrone.Core.Test/ProviderTests/PostDownloadProviderTests/ProcessDownloadFixture.cs
new file mode 100644
index 000000000..c1a13da78
--- /dev/null
+++ b/NzbDrone.Core.Test/ProviderTests/PostDownloadProviderTests/ProcessDownloadFixture.cs
@@ -0,0 +1,203 @@
+// ReSharper disable InconsistentNaming
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using AutoMoq;
+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.Test.Framework;
+
+namespace NzbDrone.Core.Test.ProviderTests.PostDownloadProviderTests
+{
+ [TestFixture]
+ public class ProcessDownloadFixture : TestBase
+ {
+ [Test]
+ public void should_skip_if_folder_is_tagged_and_too_fresh()
+ {
+ var mocker = new AutoMoqer(MockBehavior.Strict);
+
+ var droppedFolder = new DirectoryInfo(TempFolder + "\\_test\\");
+ droppedFolder.Create();
+
+ mocker.Resolve().ProcessDownload(droppedFolder);
+ }
+
+ [Test]
+ public void should_continue_processing_if_folder_is_tagged_and_not_fresh()
+ {
+ var mocker = new AutoMoqer(MockBehavior.Loose);
+
+ var droppedFolder = new DirectoryInfo(TempFolder + "\\_test\\");
+ droppedFolder.Create();
+
+ droppedFolder.LastWriteTime = DateTime.Now.AddMinutes(-2);
+
+ //Act
+ mocker.GetMock().Setup(s => s.FindSeries(It.IsAny())).Returns(null).Verifiable();
+ mocker.Resolve().ProcessDownload(droppedFolder);
+
+ //Assert
+ mocker.VerifyAllMocks();
+ ExceptionVerification.ExcpectedWarns(1);
+ }
+
+
+ [Test]
+ public void should_search_for_series_using_title_without_status()
+ {
+ //Setup
+ var mocker = new AutoMoqer(MockBehavior.Loose);
+ var droppedFolder = new DirectoryInfo(@"C:\Test\Unsorted TV\_unpack_The Office - S01E01 - Episode Title");
+
+ mocker.GetMock().Setup(s => s.FindSeries("office")).Returns(null).Verifiable();
+
+ //Act
+ mocker.Resolve().ProcessDownload(droppedFolder);
+
+ //Assert
+ mocker.VerifyAllMocks();
+ ExceptionVerification.ExcpectedWarns(1);
+ }
+
+ [Test]
+ public void when_series_isnt_found_folder_should_be_tagged_as_unknown_series()
+ {
+ //Setup
+ var mocker = new AutoMoqer(MockBehavior.Strict);
+ var droppedFolder = new DirectoryInfo(@"C:\Test\Unsorted TV\The Office - S01E01 - Episode Title");
+
+ var taggedFolder = @"C:\Test\Unsorted TV\_UnknownSeries_The Office - S01E01 - Episode Title";
+
+ //Act
+ mocker.GetMock().Setup(s => s.FindSeries("office")).Returns(null);
+ mocker.GetMock().Setup(s => s.MoveDirectory(droppedFolder.FullName, taggedFolder));
+
+ mocker.Resolve().ProcessDownload(droppedFolder);
+
+ //Assert
+ mocker.VerifyAllMocks();
+ ExceptionVerification.ExcpectedWarns(1);
+ }
+
+ [Test]
+ public void when_no_files_are_imported_folder_should_be_tagged_with_parse_error()
+ {
+ //Setup
+ var mocker = new AutoMoqer(MockBehavior.Strict);
+ var droppedFolder = new DirectoryInfo(@"C:\Test\Unsorted TV\The Office - S01E01 - Episode Title");
+
+ var taggedFolder = @"C:\Test\Unsorted TV\_ParseError_The Office - S01E01 - Episode Title";
+
+ var fakeSeries = Builder.CreateNew()
+ .With(s => s.Title = "The Office")
+ .Build();
+
+ //Act
+ mocker.GetMock().Setup(s => s.FindSeries("office")).Returns(fakeSeries);
+ mocker.GetMock().Setup(s => s.Scan(fakeSeries, droppedFolder.FullName)).Returns(new List());
+ mocker.GetMock().Setup(s => s.MoveDirectory(droppedFolder.FullName, taggedFolder));
+ mocker.GetMock().Setup(s => s.GetDirectorySize(droppedFolder.FullName)).Returns(100.Megabytes());
+
+
+ mocker.Resolve().ProcessDownload(droppedFolder);
+
+ //Assert
+ mocker.VerifyAllMocks();
+ ExceptionVerification.ExcpectedWarns(1);
+ }
+
+
+ [Test]
+ public void when_no_file_are_imported_and_folder_size_isnt_small_enought_folder_should_be_tagged_unknown()
+ {
+ //Setup
+ var mocker = new AutoMoqer(MockBehavior.Strict);
+ var droppedFolder = new DirectoryInfo(@"C:\Test\Unsorted TV\The Office - Season 01");
+
+ var taggedFolder = PostDownloadProvider.GetFolderNameWithStatus(droppedFolder, PostDownloadStatusType.Unknown);
+
+ var fakeSeries = Builder.CreateNew()
+ .With(s => s.Title = "The Office")
+ .Build();
+
+ var fakeEpisodeFiles = Builder.CreateListOfSize(2)
+ .All()
+ .With(f => f.SeriesId = fakeSeries.SeriesId)
+ .Build().ToList();
+
+ //Act
+ mocker.GetMock().Setup(s => s.FindSeries("office")).Returns(fakeSeries);
+ mocker.GetMock().Setup(s => s.MoveDirectory(droppedFolder.FullName, taggedFolder));
+ mocker.GetMock().Setup(s => s.GetDirectorySize(droppedFolder.FullName)).Returns(100.Megabytes());
+ mocker.GetMock().Setup(s => s.Scan(fakeSeries, droppedFolder.FullName)).Returns(fakeEpisodeFiles);
+ mocker.GetMock().Setup(s => s.MoveEpisodeFile(It.IsAny(), true)).Returns(true);
+
+ mocker.Resolve().ProcessDownload(droppedFolder);
+
+ //Assert
+ mocker.VerifyAllMocks();
+ ExceptionVerification.ExcpectedWarns(1);
+ }
+
+ [Test]
+ public void when_files_are_imported_and_folder_is_small_enought_dir_should_be_deleted()
+ {
+ //Setup
+ var mocker = new AutoMoqer(MockBehavior.Strict);
+ var droppedFolder = new DirectoryInfo(@"C:\Test\Unsorted TV\The Office - Season 01");
+
+ var fakeSeries = Builder.CreateNew()
+ .With(s => s.Title = "The Office")
+ .Build();
+
+ var fakeEpisodeFiles = Builder.CreateListOfSize(2)
+ .All()
+ .With(f => f.SeriesId = fakeSeries.SeriesId)
+ .Build().ToList();
+
+ mocker.GetMock().Setup(s => s.FindSeries("office")).Returns(fakeSeries);
+ mocker.GetMock().Setup(s => s.Scan(fakeSeries, droppedFolder.FullName)).Returns(fakeEpisodeFiles);
+ mocker.GetMock().Setup(s => s.MoveEpisodeFile(It.IsAny(), true)).Returns(true);
+ mocker.GetMock().Setup(s => s.GetDirectorySize(droppedFolder.FullName)).Returns(1.Megabytes());
+ mocker.GetMock().Setup(s => s.DeleteFolder(droppedFolder.FullName, true));
+
+ //Act
+ mocker.Resolve().ProcessDownload(droppedFolder);
+
+ //Assert
+ mocker.VerifyAllMocks();
+ }
+
+ [Test]
+ public void all_imported_files_should_be_moved()
+ {
+ //Setup
+ var mocker = new AutoMoqer(MockBehavior.Loose);
+ var droppedFolder = new DirectoryInfo(TempFolder);
+
+ var fakeSeries = Builder.CreateNew()
+ .Build();
+
+ var fakeEpisodeFiles = Builder.CreateListOfSize(2)
+ .Build().ToList();
+
+ mocker.GetMock().Setup(s => s.FindSeries(It.IsAny())).Returns(fakeSeries);
+ mocker.GetMock().Setup(s => s.Scan(fakeSeries, droppedFolder.FullName)).Returns(fakeEpisodeFiles);
+
+ //Act
+ mocker.Resolve().ProcessDownload(droppedFolder);
+
+ //Assert
+ mocker.GetMock().Verify(c => c.MoveEpisodeFile(It.IsAny(), true),
+ Times.Exactly(fakeEpisodeFiles.Count));
+ mocker.VerifyAllMocks();
+ }
+ }
+}
\ No newline at end of file
diff --git a/NzbDrone.Core/Model/PostDownloadInfoModel.cs b/NzbDrone.Core/Model/PostDownloadInfoModel.cs
deleted file mode 100644
index 572ef529e..000000000
--- a/NzbDrone.Core/Model/PostDownloadInfoModel.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-
-namespace NzbDrone.Core.Model
-{
- public class PostDownloadInfoModel
- {
- public string Name { get; set; }
- public DateTime Added { get; set; }
- public PostDownloadStatusType Status { get; set; }
- }
-}
diff --git a/NzbDrone.Core/Model/PostDownloadStatusType.cs b/NzbDrone.Core/Model/PostDownloadStatusType.cs
index 3094b7772..3d170cd4e 100644
--- a/NzbDrone.Core/Model/PostDownloadStatusType.cs
+++ b/NzbDrone.Core/Model/PostDownloadStatusType.cs
@@ -2,14 +2,11 @@
{
public enum PostDownloadStatusType
{
-
Unknown = 0,
Unpacking = 1,
Failed = 2,
- Processed = 3,
- InvalidSeries = 4,
- ParseError = 5,
- InvalidEpisode = 6,
- NoError = 7,
+ UnknownSeries = 3,
+ ParseError = 4,
+ NoError = 5,
}
}
\ No newline at end of file
diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj
index dc5c58ea9..52148e7bd 100644
--- a/NzbDrone.Core/NzbDrone.Core.csproj
+++ b/NzbDrone.Core/NzbDrone.Core.csproj
@@ -195,7 +195,6 @@
-
diff --git a/NzbDrone.Core/Providers/DiskScanProvider.cs b/NzbDrone.Core/Providers/DiskScanProvider.cs
index 441fa747a..e0988ce34 100644
--- a/NzbDrone.Core/Providers/DiskScanProvider.cs
+++ b/NzbDrone.Core/Providers/DiskScanProvider.cs
@@ -60,7 +60,7 @@ namespace NzbDrone.Core.Providers
if (!_diskProvider.FolderExists(path))
{
- Logger. Warn("Series folder doesn't exist: {0}", path);
+ Logger.Warn("Series folder doesn't exist: {0}", path);
return new List();
}
@@ -80,7 +80,9 @@ namespace NzbDrone.Core.Providers
{
var file = ImportFile(series, filePath);
if (file != null)
+ {
importedFiles.Add(file);
+ }
}
series.LastDiskSync = DateTime.Now;
@@ -153,7 +155,7 @@ namespace NzbDrone.Core.Providers
foreach (var ep in episodes)
{
ep.EpisodeFileId = fileId;
- ep.PostDownloadStatus = PostDownloadStatusType.Processed;
+ ep.PostDownloadStatus = PostDownloadStatusType.NoError;
_episodeProvider.UpdateEpisode(ep);
Logger.Debug("Linking [{0}] > [{1}]", filePath, ep);
}
@@ -191,12 +193,15 @@ namespace NzbDrone.Core.Providers
parseResult.Series = series;
var message = _sabProvider.GetSabTitle(parseResult);
-
+
if (newDownload)
+ {
_externalNotificationProvider.OnDownload(message, series);
-
+ }
else
+ {
_externalNotificationProvider.OnRename(message, series);
+ }
return true;
}
diff --git a/NzbDrone.Core/Providers/Jobs/PostDownloadScanJob.cs b/NzbDrone.Core/Providers/Jobs/PostDownloadScanJob.cs
index 47d85f9da..8ace8bf40 100644
--- a/NzbDrone.Core/Providers/Jobs/PostDownloadScanJob.cs
+++ b/NzbDrone.Core/Providers/Jobs/PostDownloadScanJob.cs
@@ -1,16 +1,25 @@
-using Ninject;
+using System;
+using NLog;
+using Ninject;
using NzbDrone.Core.Model.Notification;
+using NzbDrone.Core.Providers.Core;
namespace NzbDrone.Core.Providers.Jobs
{
public class PostDownloadScanJob : IJob
{
+ private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
+
private readonly PostDownloadProvider _postDownloadProvider;
+ private readonly ConfigProvider _configProvider;
+ private readonly DiskProvider _diskProvider;
[Inject]
- public PostDownloadScanJob(PostDownloadProvider postDownloadProvider)
+ public PostDownloadScanJob(PostDownloadProvider postDownloadProvider,ConfigProvider configProvider, DiskProvider diskProvider)
{
_postDownloadProvider = postDownloadProvider;
+ _configProvider = configProvider;
+ _diskProvider = diskProvider;
}
public PostDownloadScanJob()
@@ -29,7 +38,21 @@ namespace NzbDrone.Core.Providers.Jobs
public virtual void Start(ProgressNotification notification, int targetId, int secondaryTargetId)
{
- _postDownloadProvider.ScanDropFolder(notification);
+ var dropFolder = _configProvider.SabDropDirectory;
+
+ if (String.IsNullOrWhiteSpace(dropFolder))
+ {
+ Logger.Debug("No drop folder is defined. Skipping.");
+ return;
+ }
+
+ if (!_diskProvider.FolderExists(dropFolder))
+ {
+ Logger.Warn("Unable to Scan for New Downloads - folder Doesn't exist: [{0}]", dropFolder);
+ return;
+ }
+
+ _postDownloadProvider.ProcessDropFolder(dropFolder);
}
}
}
\ No newline at end of file
diff --git a/NzbDrone.Core/Providers/PostDownloadProvider.cs b/NzbDrone.Core/Providers/PostDownloadProvider.cs
index ef072a89e..456e2a0d2 100644
--- a/NzbDrone.Core/Providers/PostDownloadProvider.cs
+++ b/NzbDrone.Core/Providers/PostDownloadProvider.cs
@@ -13,53 +13,27 @@ namespace NzbDrone.Core.Providers
{
public class PostDownloadProvider
{
- //Used to perform Post Download Processing (Started by PostDownloadScanJob)
- private readonly ConfigProvider _configProvider;
private readonly DiskProvider _diskProvider;
+ private readonly EpisodeProvider _episodeProvider;
private readonly DiskScanProvider _diskScanProvider;
private readonly SeriesProvider _seriesProvider;
- private readonly EpisodeProvider _episodeProvider;
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
private static readonly Regex StatusRegex = new Regex(@"^_[\w_]*_", RegexOptions.Compiled);
- private static readonly List InfoList = new List();
-
[Inject]
- public PostDownloadProvider(ConfigProvider configProvider, DiskProvider diskProvider,
- DiskScanProvider diskScanProvider, SeriesProvider seriesProvider,
- EpisodeProvider episodeProvider)
+ public PostDownloadProvider(DiskProvider diskProvider, EpisodeProvider episodeProvider,
+ DiskScanProvider diskScanProvider, SeriesProvider seriesProvider)
{
- _configProvider = configProvider;
_diskProvider = diskProvider;
+ _episodeProvider = episodeProvider;
_diskScanProvider = diskScanProvider;
_seriesProvider = seriesProvider;
- _episodeProvider = episodeProvider;
}
public PostDownloadProvider()
{
-
- }
-
- public virtual void ScanDropFolder(ProgressNotification notification)
- {
- var dropFolder = _configProvider.SabDropDirectory;
-
- if (String.IsNullOrWhiteSpace(dropFolder))
- {
- Logger.Debug("No drop folder is defined. Skipping.");
- return;
- }
-
- if (!_diskProvider.FolderExists(dropFolder))
- {
- Logger.Warn("Unable to Scan for New Downloads - folder Doesn't exist: [{0}]", dropFolder);
- return;
- }
-
- ProcessDropFolder(dropFolder);
}
public virtual void ProcessDropFolder(string dropFolder)
@@ -68,57 +42,33 @@ namespace NzbDrone.Core.Providers
{
try
{
- var subfolderInfo = new DirectoryInfo(subfolder);
-
- var folderStatus = GetPostDownloadStatusForFolder(subfolderInfo.Name);
-
-
-
- if (folderStatus == PostDownloadStatusType.Unpacking)
- {
- ProcessFailedOrUnpackingDownload(subfolderInfo, PostDownloadStatusType.Unpacking);
- Logger.Debug("Folder [{0}] is still being unpacked. skipping.", subfolder);
- continue;
- }
-
- if (folderStatus == PostDownloadStatusType.Failed)
- {
- ProcessFailedOrUnpackingDownload(subfolderInfo, PostDownloadStatusType.Failed);
- Logger.Debug("Folder [{0}] is marked as failed. skipping.", subfolder);
- continue;
- }
-
- if (folderStatus != PostDownloadStatusType.NoError)
- {
- //Retry processing on the download
- ReProcessDownload(new PostDownloadInfoModel { Name = subfolderInfo.FullName, Status = folderStatus });
- continue;
- }
-
- //Process a successful download
- ProcessDownload(subfolderInfo);
+ ProcessDownload(new DirectoryInfo(subfolder));
}
-
catch (Exception e)
{
- Logger.ErrorException("An error has occurred while importing " + subfolder, e);
+ Logger.ErrorException("An error has occurred while importing folder" + subfolder, e);
}
}
}
public virtual void ProcessDownload(DirectoryInfo subfolderInfo)
{
- //Parse the Folder name
- var seriesName = Parser.ParseSeriesName(subfolderInfo.Name);
+
+ if (subfolderInfo.Name.StartsWith("_") && subfolderInfo.LastWriteTimeUtc.AddMinutes(1) > DateTime.UtcNow)
+ {
+ Logger.Trace("[{0}] is too fresh. skipping", subfolderInfo.Name);
+ return;
+ }
+
+ var seriesName = Parser.ParseSeriesName(RemoveStatusFromFolderName(subfolderInfo.Name));
var series = _seriesProvider.FindSeries(seriesName);
if (series == null)
{
- Logger.Warn("Unable to Import new download [{0}], series doesn't exist in database.", subfolderInfo.FullName);
+ Logger.Warn("Unable to Import new download [{0}], Can't find matching series in database.", subfolderInfo.Name);
//Rename the Directory so it's not processed again.
- _diskProvider.MoveDirectory(subfolderInfo.FullName,
- GetNewFolderNameWithPostDownloadStatus(subfolderInfo, PostDownloadStatusType.InvalidSeries));
+ TagFolder(subfolderInfo, PostDownloadStatusType.UnknownSeries);
return;
}
@@ -127,157 +77,41 @@ namespace NzbDrone.Core.Providers
//Delete the folder only if folder is small enough
if (_diskProvider.GetDirectorySize(subfolderInfo.FullName) < 10.Megabytes())
+ {
_diskProvider.DeleteFolder(subfolderInfo.FullName, true);
-
- //Otherwise rename the folder to say it was already processed once by NzbDrone
+ }
else
{
+ //Otherwise rename the folder to say it was already processed once by NzbDrone
if (importedFiles.Count == 0)
{
- Logger.Warn("Unable to Import new download [{0}], unable to parse episode file(s).", subfolderInfo.FullName);
- _diskProvider.MoveDirectory(subfolderInfo.FullName,
- GetNewFolderNameWithPostDownloadStatus(subfolderInfo, PostDownloadStatusType.ParseError));
+ Logger.Warn("Unable to Import new download [{0}], no importable files were found..", subfolderInfo.Name);
+ TagFolder(subfolderInfo, PostDownloadStatusType.ParseError);
}
-
- //Unknown Error Importing (Possibly a lesser quality than episode currently on disk)
+ //Unknown Error Importing (Possibly a lesser quality than episode currently on disk)
else
{
- Logger.Warn("Unable to Import new download [{0}].", subfolderInfo.FullName);
-
- _diskProvider.MoveDirectory(subfolderInfo.FullName, GetNewFolderNameWithPostDownloadStatus(subfolderInfo, PostDownloadStatusType.Unknown));
- }
- }
- }
-
- public virtual void ProcessFailedOrUnpackingDownload(DirectoryInfo directoryInfo, PostDownloadStatusType postDownloadStatus)
- {
- //Check to see if its already in InfoList, if it is, check if enough time has passed to process
- var model = CheckForExisting(directoryInfo.FullName);
-
- if (model != null)
- {
- //Process if 30 minutes has passed
- if (model.Added > DateTime.Now.AddMinutes(30))
- {
- ReProcessDownload(model);
-
- //If everything processed successfully up until now, remove it from InfoList
- Remove(model);
+ Logger.Warn("Unable to Import new download [{0}].", subfolderInfo.Name);
+ TagFolder(subfolderInfo, PostDownloadStatusType.Unknown);
}
-
- return;
- }
-
- //Remove the error prefix before processing
- var parseResult = Parser.ParseTitle(RemoveStatusFromFolderName(directoryInfo.Name));
-
- parseResult.Series = _seriesProvider.FindSeries(parseResult.CleanTitle);
-
- List episodeIds;
-
- if (parseResult.EpisodeNumbers.Count == 0 && parseResult.FullSeason)
- {
- episodeIds =
- _episodeProvider.GetEpisodesBySeason(parseResult.Series.SeriesId, parseResult.SeasonNumber)
- .Select(e => e.EpisodeId).ToList();
- }
- else
- episodeIds = _episodeProvider.GetEpisodesByParseResult(parseResult).Select(e => e.EpisodeId).ToList();
-
- if (episodeIds.Count == 0)
- {
- //Mark as InvalidEpisode
- Logger.Warn("Unable to Import new download [{0}], no episode(s) found in database.", directoryInfo.FullName);
-
- var newPath = GetNewFolderNameWithPostDownloadStatus(directoryInfo, PostDownloadStatusType.InvalidEpisode);
- _diskProvider.MoveDirectory(directoryInfo.FullName, newPath);
-
- return;
}
-
- //Set the PostDownloadStatus for all found episodes
- _episodeProvider.SetPostDownloadStatus(episodeIds, postDownloadStatus);
-
- //Add to InfoList for possible later processing
- Add(new PostDownloadInfoModel
- {
- Name = directoryInfo.FullName,
- Added = DateTime.Now,
- Status = postDownloadStatus
- });
- }
-
- public virtual void ReProcessDownload(PostDownloadInfoModel model)
- {
- var directoryInfo = new DirectoryInfo(model.Name);
- var newName = GetNewFolderNameWithPostDownloadStatus(directoryInfo, PostDownloadStatusType.NoError);
-
- _diskProvider.MoveDirectory(directoryInfo.FullName, newName);
-
- directoryInfo = new DirectoryInfo(newName);
-
- ProcessDownload(directoryInfo);
- }
-
- public void Add(PostDownloadInfoModel model)
- {
- InfoList.Add(model);
- }
-
- public void Remove(PostDownloadInfoModel model)
- {
- InfoList.Remove(model);
- }
-
- public PostDownloadInfoModel CheckForExisting(string path)
- {
- return InfoList.SingleOrDefault(i => i.Name == path);
}
- public PostDownloadStatusType GetPostDownloadStatusForFolder(string folderName)
+ public void TagFolder(DirectoryInfo directory, PostDownloadStatusType status)
{
- if (folderName.StartsWith("_UNPACK_"))
- return PostDownloadStatusType.Unpacking;
-
- if (folderName.StartsWith("_FAILED_"))
- return PostDownloadStatusType.Failed;
-
- foreach (PostDownloadStatusType postDownloadStatusType in Enum.GetValues(typeof(PostDownloadStatusType)))
- {
- var startsWith = String.Format("_NzbDrone_{0}_", postDownloadStatusType.ToString());
-
- if (folderName.StartsWith(startsWith))
- return postDownloadStatusType;
- }
-
- if (folderName.StartsWith("_NzbDrone_"))
- return PostDownloadStatusType.Unknown;
-
- return PostDownloadStatusType.NoError;
+ _diskProvider.MoveDirectory(directory.FullName, GetFolderNameWithStatus(directory, status));
}
- public string GetNewFolderNameWithPostDownloadStatus(DirectoryInfo directoryInfo, PostDownloadStatusType postDownloadStatus)
+ public static string GetFolderNameWithStatus(DirectoryInfo directoryInfo, PostDownloadStatusType status)
{
- var existingError = GetPostDownloadStatusForFolder(directoryInfo.Name);
- var newFolderName = directoryInfo.Name;
- var error = String.Format("_NzbDrone_{0}_", postDownloadStatus.ToString());
-
- if (existingError != PostDownloadStatusType.NoError)
- newFolderName = RemoveStatusFromFolderName(directoryInfo.Name);
-
- if (postDownloadStatus == PostDownloadStatusType.Unknown)
- error = "_NzbDrone_";
-
- if (postDownloadStatus == PostDownloadStatusType.NoError)
- error = String.Empty;
+ if (status == PostDownloadStatusType.NoError)
+ throw new InvalidOperationException("Can't tag a folder with a None-error status. " + status);
- if (postDownloadStatus == PostDownloadStatusType.Processed)
- error = String.Empty;
+ var cleanName = RemoveStatusFromFolderName(directoryInfo.Name);
- var parent = directoryInfo.Parent.FullName;
- var newName = error + newFolderName;
+ var newName = string.Format("_{0}_{1}", status, cleanName);
- return Path.Combine(parent, newName);
+ return Path.Combine(directoryInfo.Parent.FullName, newName);
}
public static string RemoveStatusFromFolderName(string folderName)