using System; using System.Collections.Generic; using System.Linq; using FizzWare.NBuilder; using FluentAssertions; using Moq; using NUnit.Framework; using NzbDrone.Common.Disk; using NzbDrone.Core.Download; using NzbDrone.Core.Download.Clients.Nzbget; using NzbDrone.Core.Exceptions; using NzbDrone.Core.RemotePathMappings; using NzbDrone.Test.Common; namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetTests { [TestFixture] public class NzbgetFixture : DownloadClientFixtureBase { private NzbgetQueueItem _queued; private NzbgetHistoryItem _failed; private NzbgetHistoryItem _completed; private Dictionary _configItems; private DownloadClientItem _downloadClientItem; [SetUp] public void Setup() { Subject.Definition = new DownloadClientDefinition(); Subject.Definition.Settings = new NzbgetSettings { Host = "127.0.0.1", Port = 2222, Username = "admin", Password = "pass", MovieCategory = "movie", RecentMoviePriority = (int)NzbgetPriority.High }; _queued = new NzbgetQueueItem { FileSizeLo = 1000, RemainingSizeLo = 10, Category = "movie", NzbName = "Droned.1998.1080p.WEB-DL-DRONE", Parameters = new List { new NzbgetParameter { Name = "drone", Value = "id" } } }; _failed = new NzbgetHistoryItem { FileSizeLo = 1000, Category = "movie", Name = "Droned.1998.1080p.WEB-DL-DRONE", DestDir = "somedirectory", Parameters = new List { new NzbgetParameter { Name = "drone", Value = "id" } }, ParStatus = "Some Error", UnpackStatus = "NONE", MoveStatus = "NONE", ScriptStatus = "NONE", DeleteStatus = "NONE", MarkStatus = "NONE" }; _completed = new NzbgetHistoryItem { FileSizeLo = 1000, Category = "movie", Name = "Droned.1998.1080p.WEB-DL-DRONE", DestDir = "/remote/mount/tv/Droned.1998.1080p.WEB-DL-DRONE", Parameters = new List { new NzbgetParameter { Name = "drone", Value = "id" } }, ParStatus = "SUCCESS", UnpackStatus = "NONE", MoveStatus = "SUCCESS", ScriptStatus = "NONE", DeleteStatus = "NONE", MarkStatus = "NONE" }; _downloadClientItem = Builder .CreateNew() .With(d => d.DownloadId = "_Droned.S01E01.Pilot.1080p.WEB-DL-DRONE_0") .With(d => d.OutputPath = new OsPath("/remote/mount/tv/Droned.S01E01.Pilot.1080p.WEB-DL-DRONE".AsOsAgnostic())) .Build(); Mocker.GetMock() .Setup(s => s.GetGlobalStatus(It.IsAny())) .Returns(new NzbgetGlobalStatus { DownloadRate = 7000000 }); Mocker.GetMock() .Setup(v => v.GetVersion(It.IsAny())) .Returns("14.0"); _configItems = new Dictionary(); _configItems.Add("Category1.Name", "movie"); _configItems.Add("Category1.DestDir", @"/remote/mount/movie"); Mocker.GetMock() .Setup(v => v.GetConfig(It.IsAny())) .Returns(_configItems); } protected void GivenFailedDownload() { Mocker.GetMock() .Setup(s => s.DownloadNzb(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Returns((string)null); } protected void GivenSuccessfulDownload() { Mocker.GetMock() .Setup(s => s.DownloadNzb(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Returns(Guid.NewGuid().ToString().Replace("-", "")); } protected virtual void GivenQueue(NzbgetQueueItem queue) { var list = new List(); if (queue != null) { list.Add(queue); } Mocker.GetMock() .Setup(s => s.GetQueue(It.IsAny())) .Returns(list); } protected virtual void GivenHistory(NzbgetHistoryItem history) { var list = new List(); if (history != null) { list.Add(history); } Mocker.GetMock() .Setup(s => s.GetHistory(It.IsAny())) .Returns(list); } [Test] public void GetItems_should_return_no_items_when_queue_is_empty() { GivenQueue(null); GivenHistory(null); Subject.GetItems().Should().BeEmpty(); } [Test] public void RemoveItem_should_delete_folder() { GivenQueue(null); GivenHistory(_completed); Mocker.GetMock() .Setup(v => v.FolderExists(It.IsAny())) .Returns(true); Subject.RemoveItem(_downloadClientItem, true); Mocker.GetMock() .Verify(v => v.DeleteFolder(It.IsAny(), true), Times.Once()); } [Test] public void queued_item_should_have_required_properties() { _queued.ActiveDownloads = 0; GivenQueue(_queued); GivenHistory(null); var result = Subject.GetItems().Single(); VerifyQueued(result); result.CanBeRemoved.Should().BeTrue(); result.CanMoveFiles.Should().BeTrue(); } [Test] public void paused_item_should_have_required_properties() { _queued.PausedSizeLo = _queued.RemainingSizeLo; GivenQueue(_queued); GivenHistory(null); var result = Subject.GetItems().Single(); VerifyPaused(result); result.CanBeRemoved.Should().BeTrue(); result.CanMoveFiles.Should().BeTrue(); } [Test] public void downloading_item_should_have_required_properties() { _queued.ActiveDownloads = 1; GivenQueue(_queued); GivenHistory(null); var result = Subject.GetItems().Single(); VerifyDownloading(result); result.CanBeRemoved.Should().BeTrue(); result.CanMoveFiles.Should().BeTrue(); } [Test] public void post_processing_item_should_have_required_properties() { _queued.ActiveDownloads = 1; GivenQueue(_queued); GivenHistory(null); _queued.RemainingSizeLo = 0; var result = Subject.GetItems().Single(); result.CanBeRemoved.Should().BeTrue(); result.CanMoveFiles.Should().BeTrue(); } [Test] public void completed_download_should_have_required_properties() { GivenQueue(null); GivenHistory(_completed); var result = Subject.GetItems().Single(); VerifyCompleted(result); result.CanBeRemoved.Should().BeTrue(); result.CanMoveFiles.Should().BeTrue(); } [Test] public void failed_item_should_have_required_properties() { GivenQueue(null); GivenHistory(_failed); var result = Subject.GetItems().Single(); VerifyFailed(result); } [Test] public void should_report_deletestatus_health_as_failed() { _completed.DeleteStatus = "HEALTH"; GivenQueue(null); GivenHistory(_completed); var result = Subject.GetItems().Single(); result.Status.Should().Be(DownloadItemStatus.Failed); } [Test] public void should_report_deletestatus_dupe_as_failed() { _completed.DeleteStatus = "DUPE"; GivenQueue(null); GivenHistory(_completed); var result = Subject.GetItems().Single(); result.Status.Should().Be(DownloadItemStatus.Failed); } [Test] public void should_report_deletestatus_copy_as_failed() { _completed.DeleteStatus = "COPY"; GivenQueue(null); GivenHistory(_completed); var result = Subject.GetItems().Single(); result.Status.Should().Be(DownloadItemStatus.Failed); } [Test] public void should_report_unpackstatus_freespace_as_warning() { _completed.UnpackStatus = "SPACE"; GivenQueue(null); GivenHistory(_completed); var items = Subject.GetItems(); items.First().Status.Should().Be(DownloadItemStatus.Warning); } [Test] public void should_report_movestatus_failure_as_warning() { _completed.MoveStatus = "FAILURE"; GivenQueue(null); GivenHistory(_completed); var items = Subject.GetItems(); items.First().Status.Should().Be(DownloadItemStatus.Warning); } [Test] public void should_report_scriptstatus_failure_as_failed() { // TODO: We would love to have a way to distinguish between scripts reporting video corruption, or some internal script error. // That way we could return Warning instead of Failed to notify the user to take action. _completed.ScriptStatus = "FAILURE"; GivenQueue(null); GivenHistory(_completed); var items = Subject.GetItems(); items.First().Status.Should().Be(DownloadItemStatus.Failed); } [Test] public void Download_should_return_unique_id() { GivenSuccessfulDownload(); var remoteMovie = CreateRemoteMovie(); var id = Subject.Download(remoteMovie); id.Should().NotBeNullOrEmpty(); } [Test] public void Download_should_throw_if_failed() { GivenFailedDownload(); var remoteMovie = CreateRemoteMovie(); Assert.Throws(() => Subject.Download(remoteMovie)); } [Test] public void GetItems_should_ignore_downloads_from_other_categories() { _completed.Category = "mycat"; GivenQueue(null); GivenHistory(_completed); var items = Subject.GetItems(); items.Should().BeEmpty(); } [Test] public void should_return_status_with_outputdir() { var result = Subject.GetStatus(); result.IsLocalhost.Should().BeTrue(); result.OutputRootFolders.Should().NotBeNull(); result.OutputRootFolders.First().Should().Be(@"/remote/mount/movie"); } [Test] public void should_return_status_with_mounted_outputdir() { Mocker.GetMock() .Setup(v => v.RemapRemoteToLocal("127.0.0.1", It.IsAny())) .Returns(new OsPath(@"O:\mymount".AsOsAgnostic())); var result = Subject.GetStatus(); result.IsLocalhost.Should().BeTrue(); result.OutputRootFolders.Should().NotBeNull(); result.OutputRootFolders.First().Should().Be(@"O:\mymount".AsOsAgnostic()); } [Test] public void should_remap_storage_if_mounted() { Mocker.GetMock() .Setup(v => v.RemapRemoteToLocal("127.0.0.1", It.IsAny())) .Returns(new OsPath(@"O:\mymount\Droned.1998.1080p.WEB-DL-DRONE".AsOsAgnostic())); GivenQueue(null); GivenHistory(_completed); var result = Subject.GetItems().Single(); result.OutputPath.Should().Be(@"O:\mymount\Droned.1998.1080p.WEB-DL-DRONE".AsOsAgnostic()); } [Test] public void should_use_dest_dir_if_final_dir_is_null() { GivenQueue(null); GivenHistory(_completed); Subject.GetItems().First().OutputPath.Should().Be(_completed.DestDir); } [Test] public void should_use_dest_dir_if_final_dir_is_not_set() { _completed.FinalDir = string.Empty; GivenQueue(null); GivenHistory(_completed); Subject.GetItems().First().OutputPath.Should().Be(_completed.DestDir); } [Test] public void should_report_deletestatus_manual_with_markstatus_bad_as_failed() { _completed.DeleteStatus = "MANUAL"; _completed.MarkStatus = "BAD"; GivenQueue(null); GivenHistory(_completed); var result = Subject.GetItems().Single(); result.Status.Should().Be(DownloadItemStatus.Failed); } [Test] public void should_ignore_deletestatus_manual_without_markstatus() { _completed.DeleteStatus = "MANUAL"; GivenQueue(null); GivenHistory(_completed); Subject.GetItems().Should().BeEmpty(); } [Test] public void should_use_final_dir_when_set_instead_of_dest_dir() { _completed.FinalDir = "/remote/mount/tv2/Droned.S01E01.Pilot.1080p.WEB-DL-DRONE"; GivenQueue(null); GivenHistory(_completed); Subject.GetItems().First().OutputPath.Should().Be(_completed.FinalDir); } [TestCase("11.0", false)] [TestCase("12.0", true)] [TestCase("11.0-b30ef0134", false)] [TestCase("13.0-b30ef0134", true)] public void should_test_version(string version, bool expected) { Mocker.GetMock() .Setup(v => v.GetVersion(It.IsAny())) .Returns(version); var error = Subject.Test(); error.IsValid.Should().Be(expected); } [TestCase("0", false)] [TestCase("1", true)] [TestCase(" 7", false)] [TestCase("5000000", false)] public void should_test_keephistory(string keephistory, bool expected) { _configItems["KeepHistory"] = keephistory; var error = Subject.Test(); error.IsValid.Should().Be(expected); } } }