diff --git a/NzbDrone.Common/PathExtentions.cs b/NzbDrone.Common/PathExtentions.cs index d18f81304..3bef6b7d0 100644 --- a/NzbDrone.Common/PathExtentions.cs +++ b/NzbDrone.Common/PathExtentions.cs @@ -97,7 +97,7 @@ namespace NzbDrone.Common return Path.Combine(enviromentProvider.GetMediaCoverPath(), "Banners"); } - public static string GetFanArthPath(this EnviromentProvider enviromentProvider) + public static string GetFanArtPath(this EnviromentProvider enviromentProvider) { return Path.Combine(enviromentProvider.GetMediaCoverPath(), "Fanarts"); } diff --git a/NzbDrone.Core.Test/JobTests/BannerDownloadJobTest.cs b/NzbDrone.Core.Test/JobTests/BannerDownloadJobTest.cs index 1efa075c5..c7199f708 100644 --- a/NzbDrone.Core.Test/JobTests/BannerDownloadJobTest.cs +++ b/NzbDrone.Core.Test/JobTests/BannerDownloadJobTest.cs @@ -18,199 +18,79 @@ namespace NzbDrone.Core.Test.JobTests // ReSharper disable InconsistentNaming public class BannerDownloadJobTest : CoreTest { + private ProgressNotification _notification; [SetUp] public void Setup() { - WithStrictMocker(); + _notification = new ProgressNotification("Test"); WithTempAsAppPath(); } - [Test] - public void BannerDownload_all() + private void WithSuccessfulDownload() { - //Setup - var fakeSeries = Builder.CreateListOfSize(10) - .Build(); - - var notification = new ProgressNotification("Banner Download"); - - Mocker.GetMock() - .Setup(c => c.GetAllSeries()) - .Returns(fakeSeries); - - Mocker.GetMock() - .Setup(s => s.DownloadFile(It.IsAny(), It.IsAny())); - - Mocker.GetMock() - .Setup(S => S.CreateDirectory(It.IsAny())) - .Returns(""); - - //Act - Mocker.Resolve().Start(notification, 0, 0); - - //Assert - Mocker.VerifyAllMocks(); - Mocker.GetMock().Verify(s => s.DownloadFile(It.IsAny(), It.IsAny()), - Times.Exactly(fakeSeries.Count)); + Mocker.GetMock() + .Setup(s => s.Download(It.IsAny(), It.IsAny())) + .Returns(true); } - [Test] - public void BannerDownload_some_null_BannerUrl() + private void WithFailedDownload() { - //Setup - var fakeSeries = Builder.CreateListOfSize(10) - .Random(2) - .With(s => s.BannerUrl = null) - .Build(); - - var notification = new ProgressNotification("Banner Download"); - - Mocker.GetMock() - .Setup(c => c.GetAllSeries()) - .Returns(fakeSeries); - - Mocker.GetMock() - .Setup(s => s.DownloadFile(It.IsAny(), It.IsAny())); - - Mocker.GetMock() - .Setup(S => S.CreateDirectory(It.IsAny())) - .Returns(""); - - //Act - Mocker.Resolve().Start(notification, 0, 0); - - //Assert - Mocker.VerifyAllMocks(); - Mocker.GetMock().Verify(s => s.DownloadFile(It.IsAny(), It.IsAny()), - Times.Exactly(8)); + Mocker.GetMock() + .Setup(s => s.Download(It.IsAny(), It.IsAny())) + .Returns(false); } - [Test] - public void BannerDownload_some_failed_download() + private void VerifyDownloadMock(int times) { - //Setup - var fakeSeries = Builder.CreateListOfSize(4) - .Build(); - - - var bannerPath = Mocker.GetMock().Object.GetBannerPath(); - - var notification = new ProgressNotification("Banner Download"); - - Mocker.GetMock() - .Setup(c => c.GetAllSeries()) - .Returns(fakeSeries); - - Mocker.GetMock() - .Setup(s => s.DownloadFile(It.IsAny(), Path.Combine(bannerPath, "1.jpg"))) - .Throws(new WebException()); - - Mocker.GetMock() - .Setup(s => s.DownloadFile(It.IsAny(), Path.Combine(bannerPath, "2.jpg"))); - - Mocker.GetMock() - .Setup(s => s.DownloadFile(It.IsAny(), Path.Combine(bannerPath, "3.jpg"))) - .Throws(new WebException()); - - Mocker.GetMock() - .Setup(s => s.DownloadFile(It.IsAny(), Path.Combine(bannerPath, "4.jpg"))); - - Mocker.GetMock() - .Setup(S => S.CreateDirectory(It.IsAny())) - .Returns(""); - - //Act - Mocker.Resolve().Start(notification, 0, 0); - - //Assert - Mocker.VerifyAllMocks(); - Mocker.GetMock().Verify(s => s.DownloadFile(It.IsAny(), It.IsAny()), - Times.Exactly(fakeSeries.Count)); + Mocker.GetMock().Verify(v => v.Download(_notification, It.IsAny()), Times.Exactly(times)); } [Test] - public void BannerDownload_all_failed_download() + public void Start_should_download_banners_for_all_series_when_no_targetId_is_passed_in() { - //Setup - var fakeSeries = Builder.CreateListOfSize(10) - .Build(); - - var notification = new ProgressNotification("Banner Download"); - - Mocker.GetMock() - .Setup(c => c.GetAllSeries()) - .Returns(fakeSeries); - - Mocker.GetMock() - .Setup(s => s.DownloadFile(It.IsAny(), It.IsAny())) - .Throws(new WebException()); + WithSuccessfulDownload(); - Mocker.GetMock() - .Setup(S => S.CreateDirectory(It.IsAny())) - .Returns(""); + var series = Builder.CreateListOfSize(5) + .Build(); - //Act - Mocker.Resolve().Start(notification, 0, 0); + Mocker.GetMock().Setup(s => s.GetAllSeries()) + .Returns(series); - //Assert - Mocker.VerifyAllMocks(); - Mocker.GetMock().Verify(s => s.DownloadFile(It.IsAny(), It.IsAny()), - Times.Exactly(fakeSeries.Count)); + Mocker.Resolve().Start(_notification, 0, 0); + VerifyDownloadMock(series.Count); } [Test] - public void BannerDownload_single_banner() + public void Start_should_only_attempt_to_download_for_series_with_banner_url() { - //Setup - var fakeSeries = Builder.CreateNew() - .With(s => s.SeriesId = 1) - .Build(); + WithSuccessfulDownload(); - var notification = new ProgressNotification("Banner Download"); + var series = Builder.CreateListOfSize(5) + .TheFirst(2) + .With(s => s.BannerUrl = null) + .Build(); - Mocker.GetMock() - .Setup(c => c.GetSeries(1)) - .Returns(fakeSeries); + Mocker.GetMock().Setup(s => s.GetAllSeries()) + .Returns(series); - Mocker.GetMock() - .Setup(s => s.DownloadFile(It.IsAny(), It.IsAny())) - .Throws(new WebException()); - - Mocker.GetMock() - .Setup(S => S.CreateDirectory(It.IsAny())) - .Returns(""); - - //Act - Mocker.Resolve().Start(notification, 1, 0); - - //Assert - Mocker.VerifyAllMocks(); - Mocker.GetMock().Verify(s => s.DownloadFile(It.IsAny(), It.IsAny()), - Times.Once()); + Mocker.Resolve().Start(_notification, 0, 0); + VerifyDownloadMock(3); } [Test] - public void Download_Banner() + public void Start_should_download_single_banner_when_seriesId_is_passed_in() { - //Setup - var fakeSeries = Builder.CreateNew() - .With(s => s.SeriesId = 1) - .Build(); - - var notification = new ProgressNotification("Banner Download"); + WithSuccessfulDownload(); - Mocker.GetMock() - .Setup(s => s.DownloadFile(It.IsAny(), It.IsAny())) - .Throws(new WebException()); + var series = Builder.CreateNew() + .Build(); - //Act - Mocker.Resolve().DownloadBanner(notification, fakeSeries); + Mocker.GetMock().Setup(s => s.GetSeries(series.SeriesId)) + .Returns(series); - //Assert - Mocker.VerifyAllMocks(); - Mocker.GetMock().Verify(s => s.DownloadFile(It.IsAny(), It.IsAny()), - Times.Once()); + Mocker.Resolve().Start(_notification, 1, 0); + VerifyDownloadMock(1); } } } \ No newline at end of file diff --git a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj index dbdf1a558..e58966c77 100644 --- a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj +++ b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj @@ -111,6 +111,7 @@ + diff --git a/NzbDrone.Core.Test/ProviderTests/BannerProviderTest.cs b/NzbDrone.Core.Test/ProviderTests/BannerProviderTest.cs new file mode 100644 index 000000000..b0d8e741f --- /dev/null +++ b/NzbDrone.Core.Test/ProviderTests/BannerProviderTest.cs @@ -0,0 +1,102 @@ +using System; +using System.IO; +using System.Linq; +using System.Net; +using FizzWare.NBuilder; +using FluentAssertions; +using Moq; +using NUnit.Framework; +using NzbDrone.Common; +using NzbDrone.Core.Model.Notification; +using NzbDrone.Core.Providers; +using NzbDrone.Core.Repository; +using NzbDrone.Core.Repository.Quality; +using NzbDrone.Core.Test.Framework; +using NzbDrone.Test.Common.AutoMoq; + +namespace NzbDrone.Core.Test.ProviderTests +{ + [TestFixture] + // ReSharper disable InconsistentNaming + public class BannerProviderTest : CoreTest + { + private Series _series; + private ProgressNotification _notification; + + [SetUp] + public void Setup() + { + _series = Builder.CreateNew() + .With(s => s.SeriesId = 12345) + .Build(); + + _notification = new ProgressNotification("Test"); + + var path = @"C:\Windows\Temp"; + + Mocker.GetMock().Setup(s => s.CreateDirectory(path)); + } + + private void WithSuccessfulDownload() + { + Mocker.GetMock().Setup(s => s.DownloadFile(It.IsAny(), It.IsAny())); + } + + private void WithFailedDownload() + { + Mocker.GetMock().Setup(s => s.DownloadFile(It.IsAny(), It.IsAny())) + .Throws(new WebException("Failed to download file (Mocked)")); + } + + [Test] + public void Download_should_return_true_when_banner_is_downloaded_successfully() + { + WithSuccessfulDownload(); + var result = Mocker.Resolve().Download(_notification, _series); + result.Should().BeTrue(); + } + + [Test] + public void Download_should_return_false_when_banner_download_fails() + { + WithFailedDownload(); + var result = Mocker.Resolve().Download(_notification, _series); + result.Should().BeFalse(); + } + + [Test] + public void Delete_should_delete_banner_file_when_it_exists() + { + Mocker.GetMock().Setup(s => s.FileExists(It.IsAny())) + .Returns(true); + + Mocker.GetMock().Setup(s => s.DeleteFile(It.IsAny())); + + var result = Mocker.Resolve().Delete(1); + result.Should().BeTrue(); + } + + [Test] + public void Delete_should_return_true_even_when_file_sint_deleted() + { + Mocker.GetMock().Setup(s => s.FileExists(It.IsAny())) + .Returns(false); + + var result = Mocker.Resolve().Delete(1); + result.Should().BeTrue(); + } + + [Test] + public void Delete_should_return_false_when_file_fails_to_delete() + { + Mocker.GetMock().Setup(s => s.FileExists(It.IsAny())) + .Returns(true); + + Mocker.GetMock().Setup(s => s.DeleteFile(It.IsAny())) + .Throws(new SystemException("File not found.")); + + var result = Mocker.Resolve().Delete(1); + result.Should().BeFalse(); + } + } +} \ No newline at end of file diff --git a/NzbDrone.Core/Jobs/BannerDownloadJob.cs b/NzbDrone.Core/Jobs/BannerDownloadJob.cs index 23b357abc..7b1980be2 100644 --- a/NzbDrone.Core/Jobs/BannerDownloadJob.cs +++ b/NzbDrone.Core/Jobs/BannerDownloadJob.cs @@ -14,21 +14,16 @@ namespace NzbDrone.Core.Jobs public class BannerDownloadJob : IJob { private readonly SeriesProvider _seriesProvider; - private readonly HttpProvider _httpProvider; - private readonly DiskProvider _diskProvider; - private readonly EnviromentProvider _enviromentProvider; + private readonly BannerProvider _bannerProvider; private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - private const string _bannerUrlPrefix = "http://www.thetvdb.com/banners/"; + private const string BANNER_URL_PREFIX = "http://www.thetvdb.com/banners/"; [Inject] - public BannerDownloadJob(SeriesProvider seriesProvider, HttpProvider httpProvider, DiskProvider diskProvider, - EnviromentProvider enviromentProvider) + public BannerDownloadJob(SeriesProvider seriesProvider, BannerProvider bannerProvider) { _seriesProvider = seriesProvider; - _httpProvider = httpProvider; - _diskProvider = diskProvider; - _enviromentProvider = enviromentProvider; + _bannerProvider = bannerProvider; } public BannerDownloadJob() @@ -49,15 +44,12 @@ namespace NzbDrone.Core.Jobs { Logger.Debug("Starting banner download job"); - - _diskProvider.CreateDirectory(_enviromentProvider.GetBannerPath()); - if (targetId > 0) { var series = _seriesProvider.GetSeries(targetId); if (series != null && !String.IsNullOrEmpty(series.BannerUrl)) - DownloadBanner(notification, series); + _bannerProvider.Download(notification, series); return; } @@ -66,28 +58,10 @@ namespace NzbDrone.Core.Jobs foreach (var series in seriesInDb.Where(s => !String.IsNullOrEmpty(s.BannerUrl))) { - DownloadBanner(notification, series); + _bannerProvider.Download(notification, series); } Logger.Debug("Finished banner download job"); } - - public virtual void DownloadBanner(ProgressNotification notification, Series series) - { - var bannerFilename = Path.Combine(_enviromentProvider.GetBannerPath(), series.SeriesId.ToString()) + ".jpg"; - - notification.CurrentMessage = string.Format("Downloading banner for '{0}'", series.Title); - - try - { - _httpProvider.DownloadFile(_bannerUrlPrefix + series.BannerUrl, bannerFilename); - notification.CurrentMessage = string.Format("Successfully download banner for '{0}'", series.Title); - } - catch (Exception) - { - Logger.Debug("Failed to download banner for '{0}'", series.Title); - notification.CurrentMessage = string.Format("Failed to download banner for '{0}'", series.Title); - } - } } } diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index ba04cb773..77e606eb4 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -271,6 +271,7 @@ + diff --git a/NzbDrone.Core/Providers/BannerProvider.cs b/NzbDrone.Core/Providers/BannerProvider.cs new file mode 100644 index 000000000..0c14f0f2e --- /dev/null +++ b/NzbDrone.Core/Providers/BannerProvider.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using NLog; +using NzbDrone.Common; +using NzbDrone.Core.Model.Notification; +using NzbDrone.Core.Repository; + +namespace NzbDrone.Core.Providers +{ + public class BannerProvider + { + private readonly HttpProvider _httpProvider; + private readonly EnviromentProvider _enviromentProvider; + private readonly DiskProvider _diskProvider; + private static readonly Logger logger = LogManager.GetCurrentClassLogger(); + + private const string BANNER_URL_PREFIX = "http://www.thetvdb.com/banners/"; + + public BannerProvider(HttpProvider httpProvider, EnviromentProvider enviromentProvider, + DiskProvider diskProvider) + { + _httpProvider = httpProvider; + _enviromentProvider = enviromentProvider; + _diskProvider = diskProvider; + } + + public BannerProvider() + { + + } + + public virtual bool Download(ProgressNotification notification, Series series) + { + var bannerPath = _enviromentProvider.GetBannerPath(); + + logger.Trace("Ensuring Banner Folder exists: ", bannerPath); + _diskProvider.CreateDirectory(bannerPath); + + var bannerFilename = Path.Combine(bannerPath, series.SeriesId.ToString()) + ".jpg"; + + notification.CurrentMessage = string.Format("Downloading banner for '{0}'", series.Title); + logger.Trace("Downloading banner for '{0}'", series.Title); + + try + { + _httpProvider.DownloadFile(BANNER_URL_PREFIX + series.BannerUrl, bannerFilename); + notification.CurrentMessage = string.Format("Successfully download banner for '{0}'", series.Title); + logger.Trace("Successfully download banner for '{0}'", series.Title); + } + catch (Exception) + { + logger.Debug("Failed to download banner for '{0}'", series.Title); + notification.CurrentMessage = string.Format("Failed to download banner for '{0}'", series.Title); + return false; + } + + return true; + } + + public virtual bool Delete(int seriesId) + { + var bannerPath = _enviromentProvider.GetBannerPath(); + var bannerFilename = Path.Combine(bannerPath, seriesId.ToString()) + ".jpg"; + + try + { + logger.Trace("Checking if banner exists: {0}", bannerFilename); + + if (_diskProvider.FileExists(bannerFilename)) + { + logger.Trace("Deleting existing banner: {0}", bannerFilename); + _diskProvider.DeleteFile(bannerFilename); + } + } + catch(Exception ex) + { + logger.WarnException("Failed to delete banner: " + bannerFilename, ex); + return false; + } + return true; + } + } +} diff --git a/NzbDrone.Core/Providers/SeriesProvider.cs b/NzbDrone.Core/Providers/SeriesProvider.cs index 78e7a9538..7466da7a7 100644 --- a/NzbDrone.Core/Providers/SeriesProvider.cs +++ b/NzbDrone.Core/Providers/SeriesProvider.cs @@ -19,15 +19,18 @@ namespace NzbDrone.Core.Providers private readonly TvDbProvider _tvDbProvider; private readonly IDatabase _database; private readonly SceneMappingProvider _sceneNameMappingProvider; + private readonly BannerProvider _bannerProvider; private static readonly Regex TimeRegex = new Regex(@"^(?