using System; using System.Collections.Generic; using System.Linq; using System.IO; using FizzWare.NBuilder; using Moq; using NUnit.Framework; using NzbDrone.Common.Disk; using NzbDrone.Core.Configuration; using NzbDrone.Core.Download; using NzbDrone.Core.History; using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Test.Framework; using NzbDrone.Core.MediaFiles; using NzbDrone.Core.MediaFiles.EpisodeImport; using NzbDrone.Test.Common; using NzbDrone.Core.Tv; using NzbDrone.Core.Parser.Model; namespace NzbDrone.Core.Test.Download { [TestFixture] public class CompletedDownloadServiceFixture : CoreTest { private List _completed; [SetUp] public void Setup() { _completed = Builder.CreateListOfSize(1) .All() .With(h => h.Status = DownloadItemStatus.Completed) .With(h => h.OutputPath = @"C:\DropFolder\MyDownload".AsOsAgnostic()) .With(h => h.RemoteEpisode = new RemoteEpisode { Episodes = new List { new Episode { Id = 1 } } }) .Build() .ToList(); Mocker.GetMock() .Setup(c => c.GetDownloadClients()) .Returns( new IDownloadClient[] { Mocker.GetMock().Object }); Mocker.GetMock() .SetupGet(c => c.Definition) .Returns(new Core.Download.DownloadClientDefinition { Id = 1, Name = "testClient" }); Mocker.GetMock() .SetupGet(s => s.EnableCompletedDownloadHandling) .Returns(true); Mocker.GetMock() .SetupGet(s => s.RemoveCompletedDownloads) .Returns(true); Mocker.GetMock() .Setup(s => s.Failed()) .Returns(new List()); Mocker.SetConstant(Mocker.Resolve()); } private void GivenNoGrabbedHistory() { Mocker.GetMock() .Setup(s => s.Grabbed()) .Returns(new List()); } private void GivenGrabbedHistory(List history) { Mocker.GetMock() .Setup(s => s.Grabbed()) .Returns(history); } private void GivenNoImportedHistory() { Mocker.GetMock() .Setup(s => s.Imported()) .Returns(new List()); } private void GivenImportedHistory(List importedHistory) { Mocker.GetMock() .Setup(s => s.Imported()) .Returns(importedHistory); } private void GivenCompletedDownloadClientHistory(bool hasStorage = true) { Mocker.GetMock() .Setup(s => s.GetItems()) .Returns(_completed); Mocker.GetMock() .Setup(c => c.FolderExists(It.IsAny())) .Returns(hasStorage); } private void GivenCompletedImport() { Mocker.GetMock() .Setup(v => v.ProcessFolder(It.IsAny(), It.IsAny())) .Returns(new List() { new ImportDecision(null) }); } private void GivenFailedImport() { Mocker.GetMock() .Setup(v => v.ProcessFolder(It.IsAny(), It.IsAny())) .Returns(new List() { new ImportDecision(new LocalEpisode() { Path = @"C:\TestPath\Droned.S01E01.mkv" }, "Test Failure") }); } private void VerifyNoImports() { Mocker.GetMock() .Verify(v => v.ProcessFolder(It.IsAny(), It.IsAny()), Times.Never()); } private void VerifyImports() { Mocker.GetMock() .Verify(v => v.ProcessFolder(It.IsAny(), It.IsAny()), Times.Once()); } [Test] public void should_process_if_matching_history_is_not_found_but_category_specified() { _completed.First().Category = "tv"; GivenCompletedDownloadClientHistory(); GivenNoGrabbedHistory(); GivenNoImportedHistory(); GivenCompletedImport(); Subject.Execute(new CheckForFinishedDownloadCommand()); VerifyImports(); } [Test] public void should_not_process_if_matching_history_is_not_found_and_no_category_specified() { _completed.First().Category = null; GivenCompletedDownloadClientHistory(); GivenNoGrabbedHistory(); GivenNoImportedHistory(); Subject.Execute(new CheckForFinishedDownloadCommand()); VerifyNoImports(); } [Test] public void should_not_process_if_grabbed_history_contains_null_downloadclient_id() { _completed.First().Category = null; GivenCompletedDownloadClientHistory(); var historyGrabbed = Builder.CreateListOfSize(1) .Build() .ToList(); historyGrabbed.First().Data.Add("downloadClient", "SabnzbdClient"); historyGrabbed.First().Data.Add("downloadClientId", null); GivenGrabbedHistory(historyGrabbed); GivenNoImportedHistory(); GivenFailedImport(); Subject.Execute(new CheckForFinishedDownloadCommand()); VerifyNoImports(); } [Test] public void should_process_if_failed_history_contains_null_downloadclient_id() { GivenCompletedDownloadClientHistory(); var historyGrabbed = Builder.CreateListOfSize(1) .Build() .ToList(); historyGrabbed.First().Data.Add("downloadClient", "SabnzbdClient"); historyGrabbed.First().Data.Add("downloadClientId", _completed.First().DownloadClientId); GivenGrabbedHistory(historyGrabbed); var historyImported = Builder.CreateListOfSize(1) .Build() .ToList(); historyImported.First().Data.Add("downloadClient", "SabnzbdClient"); historyImported.First().Data.Add("downloadClientId", null); GivenImportedHistory(historyImported); GivenCompletedImport(); Subject.Execute(new CheckForFinishedDownloadCommand()); VerifyImports(); } [Test] public void should_not_process_if_already_added_to_history_as_imported() { GivenCompletedDownloadClientHistory(); var history = Builder.CreateListOfSize(1) .Build() .ToList(); GivenGrabbedHistory(history); GivenImportedHistory(history); history.First().Data.Add("downloadClient", "SabnzbdClient"); history.First().Data.Add("downloadClientId", _completed.First().DownloadClientId); Subject.Execute(new CheckForFinishedDownloadCommand()); VerifyNoImports(); } [Test] public void should_process_if_not_already_in_imported_history() { GivenCompletedDownloadClientHistory(); var history = Builder.CreateListOfSize(1) .Build() .ToList(); GivenGrabbedHistory(history); GivenNoImportedHistory(); GivenCompletedImport(); history.First().Data.Add("downloadClient", "SabnzbdClient"); history.First().Data.Add("downloadClientId", _completed.First().DownloadClientId); Subject.Execute(new CheckForFinishedDownloadCommand()); VerifyImports(); } [Test] public void should_not_process_if_storage_directory_does_not_exist() { GivenCompletedDownloadClientHistory(false); var history = Builder.CreateListOfSize(1) .Build() .ToList(); GivenGrabbedHistory(history); GivenNoImportedHistory(); history.First().Data.Add("downloadClient", "SabnzbdClient"); history.First().Data.Add("downloadClientId", _completed.First().DownloadClientId); Subject.Execute(new CheckForFinishedDownloadCommand()); VerifyNoImports(); ExceptionVerification.IgnoreErrors(); } [Test] public void should_not_process_if_storage_directory_in_drone_factory() { GivenCompletedDownloadClientHistory(true); var history = Builder.CreateListOfSize(1) .Build() .ToList(); GivenGrabbedHistory(history); GivenNoImportedHistory(); Mocker.GetMock() .SetupGet(v => v.DownloadedEpisodesFolder) .Returns(@"C:\DropFolder".AsOsAgnostic()); history.First().Data.Add("downloadClient", "SabnzbdClient"); history.First().Data.Add("downloadClientId", _completed.First().DownloadClientId); Subject.Execute(new CheckForFinishedDownloadCommand()); VerifyNoImports(); ExceptionVerification.IgnoreWarns(); } [Test] public void should_process_as_already_imported_if_drone_factory_import_history_exists() { GivenCompletedDownloadClientHistory(false); _completed.Clear(); _completed.AddRange(Builder.CreateListOfSize(2) .All() .With(h => h.Status = DownloadItemStatus.Completed) .With(h => h.OutputPath = @"C:\DropFolder\MyDownload".AsOsAgnostic()) .With(h => h.RemoteEpisode = new RemoteEpisode { Episodes = new List { new Episode { Id = 1 } } }) .Build()); var grabbedHistory = Builder.CreateListOfSize(2) .All() .With(d => d.Data["downloadClient"] = "SabnzbdClient") .TheFirst(1) .With(d => d.Data["downloadClientId"] = _completed.First().DownloadClientId) .With(d => d.SourceTitle = "Droned.S01E01.720p-LAZY") .TheLast(1) .With(d => d.Data["downloadClientId"] = _completed.Last().DownloadClientId) .With(d => d.SourceTitle = "Droned.S01E01.Proper.720p-LAZY") .Build() .ToList(); var importedHistory = Builder.CreateListOfSize(2) .All() .With(d => d.EpisodeId = 1) .TheFirst(1) .With(d => d.Data["droppedPath"] = @"C:\mydownload\Droned.S01E01.720p-LAZY\lzy-dr101.mkv".AsOsAgnostic()) .TheLast(1) .With(d => d.Data["droppedPath"] = @"C:\mydownload\Droned.S01E01.Proper.720p-LAZY\lzy-dr101.mkv".AsOsAgnostic()) .Build() .ToList(); GivenGrabbedHistory(grabbedHistory); GivenImportedHistory(importedHistory); Subject.Execute(new CheckForFinishedDownloadCommand()); VerifyNoImports(); Mocker.GetMock() .Verify(v => v.UpdateHistoryData(It.IsAny(), It.IsAny>()), Times.Exactly(2)); } [Test] public void should_not_remove_if_config_disabled() { GivenCompletedDownloadClientHistory(); var history = Builder.CreateListOfSize(1) .Build() .ToList(); GivenGrabbedHistory(history); GivenNoImportedHistory(); GivenCompletedImport(); history.First().Data.Add("downloadClient", "SabnzbdClient"); history.First().Data.Add("downloadClientId", _completed.First().DownloadClientId); Mocker.GetMock() .SetupGet(s => s.RemoveCompletedDownloads) .Returns(false); Subject.Execute(new CheckForFinishedDownloadCommand()); Mocker.GetMock() .Verify(c => c.DeleteFolder(It.IsAny(), true), Times.Never()); } [Test] public void should_not_remove_while_readonly() { GivenCompletedDownloadClientHistory(); var history = Builder.CreateListOfSize(1) .Build() .ToList(); GivenGrabbedHistory(history); GivenNoImportedHistory(); GivenCompletedImport(); _completed.First().IsReadOnly = true; history.First().Data.Add("downloadClient", "SabnzbdClient"); history.First().Data.Add("downloadClientId", _completed.First().DownloadClientId); Subject.Execute(new CheckForFinishedDownloadCommand()); Mocker.GetMock() .Verify(c => c.DeleteFolder(It.IsAny(), true), Times.Never()); } [Test] public void should_not_remove_if_imported_failed() { GivenCompletedDownloadClientHistory(); var history = Builder.CreateListOfSize(1) .Build() .ToList(); GivenGrabbedHistory(history); GivenNoImportedHistory(); GivenFailedImport(); _completed.First().IsReadOnly = true; history.First().Data.Add("downloadClient", "SabnzbdClient"); history.First().Data.Add("downloadClientId", _completed.First().DownloadClientId); Subject.Execute(new CheckForFinishedDownloadCommand()); Mocker.GetMock() .Verify(c => c.DeleteFolder(It.IsAny(), true), Times.Never()); ExceptionVerification.IgnoreErrors(); } [Test] public void should_remove_if_imported() { GivenCompletedDownloadClientHistory(); var history = Builder.CreateListOfSize(1) .Build() .ToList(); GivenGrabbedHistory(history); GivenNoImportedHistory(); GivenCompletedImport(); history.First().Data.Add("downloadClient", "SabnzbdClient"); history.First().Data.Add("downloadClientId", _completed.First().DownloadClientId); Subject.Execute(new CheckForFinishedDownloadCommand()); Mocker.GetMock() .Verify(c => c.DeleteFolder(It.IsAny(), true), Times.Once()); } } }