using System.Collections.Generic; using System.IO; using System.Linq; using FizzWare.NBuilder; using FluentAssertions; using Moq; using NUnit.Framework; using NzbDrone.Core.Books; using NzbDrone.Core.DecisionEngine; using NzbDrone.Core.Download; using NzbDrone.Core.MediaFiles; using NzbDrone.Core.MediaFiles.BookImport; using NzbDrone.Core.MediaFiles.Events; using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Profiles.Qualities; using NzbDrone.Core.Qualities; using NzbDrone.Core.RootFolders; using NzbDrone.Core.Test.Framework; using NzbDrone.Test.Common; namespace NzbDrone.Core.Test.MediaFiles { [TestFixture] public class ImportApprovedTracksFixture : CoreTest { private List> _rejectedDecisions; private List> _approvedDecisions; private DownloadClientItem _downloadClientItem; private DownloadClientItemClientInfo _clientInfo; [SetUp] public void Setup() { _rejectedDecisions = new List>(); _approvedDecisions = new List>(); var author = Builder.CreateNew() .With(e => e.QualityProfile = new QualityProfile { Items = Qualities.QualityFixture.GetDefaultQualities() }) .With(s => s.Path = @"C:\Test\Music\Alien Ant Farm".AsOsAgnostic()) .Build(); var book = Builder.CreateNew() .With(e => e.Author = author) .Build(); var edition = Builder.CreateNew() .With(e => e.Book = book) .With(e => e.Monitored = true) .Build(); book.Editions = new List { edition }; var rootFolder = Builder.CreateNew() .With(r => r.IsCalibreLibrary = false) .Build(); _rejectedDecisions.Add(new ImportDecision(new LocalBook(), new Rejection("Rejected!"))); _rejectedDecisions.Add(new ImportDecision(new LocalBook(), new Rejection("Rejected!"))); _rejectedDecisions.Add(new ImportDecision(new LocalBook(), new Rejection("Rejected!"))); _approvedDecisions.Add(new ImportDecision( new LocalBook { Author = author, Book = book, Edition = edition, Path = Path.Combine(author.Path, "Alien Ant Farm - 01 - Pilot.mp3"), Quality = new QualityModel(Quality.MP3), FileTrackInfo = new ParsedTrackInfo { ReleaseGroup = "DRONE" } })); Mocker.GetMock() .Setup(s => s.UpgradeBookFile(It.IsAny(), It.IsAny(), It.IsAny())) .Returns(new BookFileMoveResult()); _clientInfo = Builder.CreateNew().Build(); _downloadClientItem = Builder.CreateNew().With(x => x.DownloadClientInfo = _clientInfo).Build(); Mocker.GetMock() .Setup(s => s.GetFilesByBook(It.IsAny())) .Returns(new List()); Mocker.GetMock() .Setup(s => s.GetBestRootFolder(It.IsAny())) .Returns(rootFolder); Mocker.GetMock() .Setup(s => s.SetMonitored(edition)) .Returns(new List { edition }); } [Test] public void should_not_import_any_if_there_are_no_approved_decisions() { Subject.Import(_rejectedDecisions, false).Where(i => i.Result == ImportResultType.Imported).Should().BeEmpty(); Mocker.GetMock().Verify(v => v.Add(It.IsAny()), Times.Never()); } [Test] public void should_import_each_approved() { Subject.Import(_approvedDecisions, false).Should().HaveCount(1); } [Test] public void should_only_import_approved() { var all = new List>(); all.AddRange(_rejectedDecisions); all.AddRange(_approvedDecisions); var result = Subject.Import(all, false); result.Should().HaveCount(all.Count); result.Where(i => i.Result == ImportResultType.Imported).Should().HaveCount(_approvedDecisions.Count); } [Test] public void should_only_import_each_track_once() { var all = new List>(); all.AddRange(_approvedDecisions); all.Add(new ImportDecision(_approvedDecisions.First().Item)); var result = Subject.Import(all, false); result.Where(i => i.Result == ImportResultType.Imported).Should().HaveCount(_approvedDecisions.Count); } [Test] public void should_move_new_downloads() { Subject.Import(new List> { _approvedDecisions.First() }, true); Mocker.GetMock() .Verify(v => v.UpgradeBookFile(It.IsAny(), _approvedDecisions.First().Item, false), Times.Once()); } [Test] public void should_publish_TrackImportedEvent_for_new_downloads() { Subject.Import(new List> { _approvedDecisions.First() }, true); Mocker.GetMock() .Verify(v => v.PublishEvent(It.IsAny()), Times.Once()); } [Test] public void should_not_move_existing_files() { var track = _approvedDecisions.First(); track.Item.ExistingFile = true; Subject.Import(new List> { track }, false); Mocker.GetMock() .Verify(v => v.UpgradeBookFile(It.IsAny(), _approvedDecisions.First().Item, false), Times.Never()); } [Test] public void should_import_higher_quality_files_first() { var lqDecision = _approvedDecisions.First(); lqDecision.Item.Quality = new QualityModel(Quality.MOBI); lqDecision.Item.Size = 10.Megabytes(); var hqDecision = new ImportDecision( new LocalBook { Author = lqDecision.Item.Author, Book = lqDecision.Item.Book, Edition = lqDecision.Item.Edition, Path = @"C:\Test\Music\Alien Ant Farm\Alien Ant Farm - 01 - Pilot.mp3".AsOsAgnostic(), Quality = new QualityModel(Quality.AZW3), Size = 1.Megabytes(), FileTrackInfo = new ParsedTrackInfo { ReleaseGroup = "DRONE" } }); var all = new List>(); all.Add(lqDecision); all.Add(hqDecision); var results = Subject.Import(all, false); results.Should().HaveCount(all.Count); results.Should().ContainSingle(d => d.Result == ImportResultType.Imported); results.Should().ContainSingle(d => d.Result == ImportResultType.Imported && d.ImportDecision.Item.Size == hqDecision.Item.Size); } [Test] public void should_import_larger_files_for_same_quality_first() { var fileDecision = _approvedDecisions.First(); fileDecision.Item.Size = 1.Gigabytes(); var sampleDecision = new ImportDecision( new LocalBook { Author = fileDecision.Item.Author, Book = fileDecision.Item.Book, Edition = fileDecision.Item.Edition, Path = @"C:\Test\Music\Alien Ant Farm\Alien Ant Farm - 01 - Pilot.mp3".AsOsAgnostic(), Quality = new QualityModel(Quality.MP3), Size = 80.Megabytes() }); var all = new List>(); all.Add(fileDecision); all.Add(sampleDecision); var results = Subject.Import(all, false); results.Should().HaveCount(all.Count); results.Should().ContainSingle(d => d.Result == ImportResultType.Imported); results.Should().ContainSingle(d => d.Result == ImportResultType.Imported && d.ImportDecision.Item.Size == fileDecision.Item.Size); } [Test] public void should_copy_when_cannot_move_files_downloads() { Subject.Import(new List> { _approvedDecisions.First() }, true, new DownloadClientItem { Title = "Alien.Ant.Farm-Truant", CanMoveFiles = false, DownloadClientInfo = _clientInfo }); Mocker.GetMock() .Verify(v => v.UpgradeBookFile(It.IsAny(), _approvedDecisions.First().Item, true), Times.Once()); } [Test] public void should_use_override_importmode() { Subject.Import(new List> { _approvedDecisions.First() }, true, new DownloadClientItem { Title = "Alien.Ant.Farm-Truant", CanMoveFiles = false, DownloadClientInfo = _clientInfo }, ImportMode.Move); Mocker.GetMock() .Verify(v => v.UpgradeBookFile(It.IsAny(), _approvedDecisions.First().Item, false), Times.Once()); } [Test] public void should_delete_existing_trackfiles_with_the_same_path() { Mocker.GetMock() .Setup(s => s.GetFileWithPath(It.IsAny())) .Returns(Builder.CreateNew().Build()); var track = _approvedDecisions.First(); track.Item.ExistingFile = true; Subject.Import(new List> { track }, false); Mocker.GetMock() .Verify(v => v.Delete(It.IsAny(), DeleteMediaFileReason.ManualOverride), Times.Once()); } } }