diff --git a/src/NzbDrone.Core.Test/MediaFiles/TrackImport/Specifications/AlreadyImportedSpecificationFixture.cs b/src/NzbDrone.Core.Test/MediaFiles/TrackImport/Specifications/AlreadyImportedSpecificationFixture.cs new file mode 100644 index 000000000..cfe88c6d1 --- /dev/null +++ b/src/NzbDrone.Core.Test/MediaFiles/TrackImport/Specifications/AlreadyImportedSpecificationFixture.cs @@ -0,0 +1,147 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using FizzWare.NBuilder; +using FluentAssertions; +using Moq; +using NUnit.Framework; +using NzbDrone.Core.Download; +using NzbDrone.Core.History; +using NzbDrone.Core.MediaFiles.TrackImport.Specifications; +using NzbDrone.Core.Music; +using NzbDrone.Core.Parser.Model; +using NzbDrone.Core.Test.Framework; +using NzbDrone.Test.Common; + +namespace NzbDrone.Core.Test.MediaFiles.TrackImport.Specifications +{ + [TestFixture] + public class AlreadyImportedSpecificationFixture : CoreTest + { + private Artist _artist; + private Album _album; + private AlbumRelease _albumRelease; + private Track _track; + private LocalTrack _localTrack; + private LocalAlbumRelease _localAlbumRelease; + private DownloadClientItem _downloadClientItem; + + [SetUp] + public void Setup() + { + _artist = Builder.CreateNew() + .With(s => s.Path = @"C:\Test\Music\30 Rock".AsOsAgnostic()) + .Build(); + + _album = Builder.CreateNew() + .With(x => x.Artist = _artist) + .With(e => e.ReleaseDate = DateTime.UtcNow) + .Build(); + + _track = Builder.CreateNew() + .With(e => e.TrackNumber = "1") + .Build(); + + _albumRelease = Builder.CreateNew() + .With(x => x.Album = _album) + .With(x => x.Tracks = new List { _track }) + .Build(); + + _localTrack = new LocalTrack + { + Album = _album, + Artist = _artist, + Tracks = new List { _track }, + Path = @"C:\Test\Unsorted\30 Rock\30.rock.track1.mp3".AsOsAgnostic(), + }; + + _localAlbumRelease = new LocalAlbumRelease + { + AlbumRelease = _albumRelease, + LocalTracks = new List { _localTrack } + }; + + _downloadClientItem = Builder.CreateNew() + .Build(); + } + + private void GivenHistory(List history) + { + Mocker.GetMock() + .Setup(s => s.GetByAlbum(It.IsAny(), It.IsAny())) + .Returns(history); + } + + [Test] + public void should_accepted_if_download_client_item_is_null() + { + Subject.IsSatisfiedBy(_localAlbumRelease, null).Accepted.Should().BeTrue(); + } + + [Test] + public void should_accept_if_episode_does_not_have_file() + { + _albumRelease.Tracks.Value.ForEach(x => x.TrackFileId = 0); + + Subject.IsSatisfiedBy(_localAlbumRelease, _downloadClientItem).Accepted.Should().BeTrue(); + } + + [Test] + public void should_accept_if_episode_has_not_been_imported() + { + var history = Builder.CreateListOfSize(1) + .All() + .With(h => h.AlbumId = _album.Id) + .With(h => h.EventType = EntityHistoryEventType.Grabbed) + .Build() + .ToList(); + + GivenHistory(history); + + Subject.IsSatisfiedBy(_localAlbumRelease, _downloadClientItem).Accepted.Should().BeTrue(); + } + + [Test] + public void should_accept_if_episode_was_grabbed_after_being_imported() + { + var history = Builder.CreateListOfSize(3) + .All() + .With(h => h.AlbumId = _album.Id) + .TheFirst(1) + .With(h => h.EventType = EntityHistoryEventType.Grabbed) + .With(h => h.Date = DateTime.UtcNow) + .TheNext(1) + .With(h => h.EventType = EntityHistoryEventType.DownloadImported) + .With(h => h.Date = DateTime.UtcNow.AddDays(-1)) + .TheNext(1) + .With(h => h.EventType = EntityHistoryEventType.Grabbed) + .With(h => h.Date = DateTime.UtcNow.AddDays(-2)) + .Build() + .ToList(); + + GivenHistory(history); + + Subject.IsSatisfiedBy(_localAlbumRelease, _downloadClientItem).Accepted.Should().BeTrue(); + } + + [Test] + public void should_reject_if_episode_imported_after_being_grabbed() + { + var history = Builder.CreateListOfSize(2) + .All() + .With(h => h.AlbumId = _album.Id) + .TheFirst(1) + .With(h => h.EventType = EntityHistoryEventType.DownloadImported) + .With(h => h.Date = DateTime.UtcNow.AddDays(-1)) + .TheNext(1) + .With(h => h.EventType = EntityHistoryEventType.Grabbed) + .With(h => h.Date = DateTime.UtcNow.AddDays(-2)) + .Build() + .ToList(); + + GivenHistory(history); + + Subject.IsSatisfiedBy(_localAlbumRelease, _downloadClientItem).Accepted.Should().BeTrue(); + } + } +} diff --git a/src/NzbDrone.Core/MediaFiles/TrackImport/Specifications/AlreadyImportedSpecification.cs b/src/NzbDrone.Core/MediaFiles/TrackImport/Specifications/AlreadyImportedSpecification.cs index a433bf601..754f61521 100644 --- a/src/NzbDrone.Core/MediaFiles/TrackImport/Specifications/AlreadyImportedSpecification.cs +++ b/src/NzbDrone.Core/MediaFiles/TrackImport/Specifications/AlreadyImportedSpecification.cs @@ -39,25 +39,33 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Specifications } var albumHistory = _historyService.GetByAlbum(albumRelease.AlbumId, null); - var lastImported = albumHistory.FirstOrDefault(h => h.EventType == EntityHistoryEventType.DownloadImported); - var lastGrabbed = albumHistory.FirstOrDefault(h => h.EventType == EntityHistoryEventType.Grabbed); + var lastImported = albumHistory.FirstOrDefault(h => + h.DownloadId == downloadClientItem.DownloadId && + h.EventType == EntityHistoryEventType.DownloadImported); + var lastGrabbed = albumHistory.FirstOrDefault(h => + h.DownloadId == downloadClientItem.DownloadId && h.EventType == EntityHistoryEventType.Grabbed); if (lastImported == null) { - _logger.Trace("Track file has not been imported"); + _logger.Trace("Album has not been imported"); return Decision.Accept(); } - if (lastGrabbed != null && lastGrabbed.Date.After(lastImported.Date)) + if (lastGrabbed != null) { - _logger.Trace("Track file was grabbed again after importing"); - return Decision.Accept(); - } + // If the release was grabbed again after importing don't reject it + if (lastGrabbed.Date.After(lastImported.Date)) + { + _logger.Trace("Album was grabbed again after importing"); + return Decision.Accept(); + } - if (lastImported.DownloadId == downloadClientItem.DownloadId) - { - _logger.Debug("Album previously imported at {0}", lastImported.Date); - return Decision.Reject("Album already imported at {0}", lastImported.Date.ToLocalTime()); + // If the release was imported after the last grab reject it + if (lastImported.Date.After(lastGrabbed.Date)) + { + _logger.Debug("Album previously imported at {0}", lastImported.Date); + return Decision.Reject("Album already imported at {0}", lastImported.Date.ToLocalTime()); + } } return Decision.Accept();