More EpisodeSearchJob fixes/tests

This commit is contained in:
kay.one 2011-05-26 20:54:28 -07:00
parent 5a812801b7
commit ac2d33443b
4 changed files with 205 additions and 29 deletions

View File

@ -1,16 +1,14 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using AutoMoq;
using FizzWare.NBuilder;
using Gallio.Framework;
using MbUnit.Framework;
using MbUnit.Framework.ContractVerifiers;
using Moq;
using NzbDrone.Core.Model;
using NzbDrone.Core.Model.Notification;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Providers.Indexer;
using NzbDrone.Core.Providers.Jobs;
using NzbDrone.Core.Repository;
using NzbDrone.Core.Repository.Quality;
@ -33,17 +31,20 @@ namespace NzbDrone.Core.Test
var mocker = new AutoMoqer(MockBehavior.Strict);
mocker.GetMock<InventoryProvider>()
.Setup(c => c.IsNeeded(It.IsAny<EpisodeParseResult>())).Returns(true)
.AtMostOnce();
.Setup(c => c.IsNeeded(It.IsAny<EpisodeParseResult>())).Returns(true);
mocker.GetMock<DownloadProvider>()
.Setup(c => c.DownloadReport(It.IsAny<EpisodeParseResult>())).Returns(true)
.AtMostOnce();
.Setup(c => c.DownloadReport(It.IsAny<EpisodeParseResult>())).Returns(true);
//Act
mocker.Resolve<EpisodeSearchJob>().ProcessResults(new ProgressNotification("Test"), episode, parseResults);
//Assert
mocker.VerifyAllMocks();
mocker.GetMock<InventoryProvider>().Verify(c => c.IsNeeded(It.IsAny<EpisodeParseResult>()), Times.Once());
mocker.GetMock<DownloadProvider>().Verify(c => c.DownloadReport(It.IsAny<EpisodeParseResult>()), Times.Once());
}
@ -60,17 +61,18 @@ namespace NzbDrone.Core.Test
var mocker = new AutoMoqer(MockBehavior.Strict);
mocker.GetMock<InventoryProvider>()
.Setup(c => c.IsNeeded(parseResults[0])).Returns(true)
.AtMostOnce();
.Setup(c => c.IsNeeded(parseResults[0])).Returns(true);
mocker.GetMock<DownloadProvider>()
.Setup(c => c.DownloadReport(parseResults[0])).Returns(true)
.AtMostOnce();
.Setup(c => c.DownloadReport(parseResults[0])).Returns(true);
//Act
mocker.Resolve<EpisodeSearchJob>().ProcessResults(new ProgressNotification("Test"), episode, parseResults);
//Assert
mocker.VerifyAllMocks();
mocker.GetMock<InventoryProvider>().Verify(c => c.IsNeeded(parseResults[0]), Times.Once());
mocker.GetMock<DownloadProvider>().Verify(c => c.DownloadReport(parseResults[0]), Times.Once());
}
@ -90,17 +92,19 @@ namespace NzbDrone.Core.Test
var mocker = new AutoMoqer(MockBehavior.Strict);
mocker.GetMock<InventoryProvider>()
.Setup(c => c.IsNeeded(It.Is<EpisodeParseResult>(p => p.Proper))).Returns(true)
.AtMostOnce();
.Setup(c => c.IsNeeded(It.Is<EpisodeParseResult>(p => p.Proper))).Returns(true);
mocker.GetMock<DownloadProvider>()
.Setup(c => c.DownloadReport(It.Is<EpisodeParseResult>(p => p.Proper))).Returns(true)
.AtMostOnce();
.Setup(c => c.DownloadReport(It.Is<EpisodeParseResult>(p => p.Proper))).Returns(true);
//Act
mocker.Resolve<EpisodeSearchJob>().ProcessResults(new ProgressNotification("Test"), episode, parseResults);
//Assert
mocker.VerifyAllMocks();
mocker.GetMock<InventoryProvider>().Verify(c => c.IsNeeded(It.Is<EpisodeParseResult>(p => p.Proper)), Times.Once());
mocker.GetMock<DownloadProvider>().Verify(c => c.DownloadReport(It.Is<EpisodeParseResult>(p => p.Proper)), Times.Once());
}
@ -117,18 +121,18 @@ namespace NzbDrone.Core.Test
mocker.GetMock<InventoryProvider>()
.Setup(c => c.IsNeeded(It.IsAny<EpisodeParseResult>())).Returns(false);
//Act
mocker.Resolve<EpisodeSearchJob>().ProcessResults(new ProgressNotification("Test"), episode, parseResults);
//Assert
mocker.VerifyAllMocks();
mocker.GetMock<InventoryProvider>().Verify(c => c.IsNeeded(It.IsAny<EpisodeParseResult>()), Times.Exactly(4));
ExceptionVerification.ExcpectedWarns(1);
}
[Test]
public void failed_is_neede_should_check_the_rest()
public void failed_IsNeeded_should_check_the_rest()
{
var parseResults = Builder<EpisodeParseResult>.CreateListOfSize(4)
.Build();
@ -140,14 +144,152 @@ namespace NzbDrone.Core.Test
mocker.GetMock<InventoryProvider>()
.Setup(c => c.IsNeeded(It.IsAny<EpisodeParseResult>())).Throws(new Exception());
//Act
mocker.Resolve<EpisodeSearchJob>().ProcessResults(new ProgressNotification("Test"), episode, parseResults);
//Assert
mocker.VerifyAllMocks();
mocker.GetMock<InventoryProvider>().Verify(c => c.IsNeeded(It.IsAny<EpisodeParseResult>()), Times.Exactly(4));
ExceptionVerification.ExcpectedErrors(4);
ExceptionVerification.ExcpectedWarns(1);
}
[Test]
[Row(0)]
[Row(-1)]
[Row(-100)]
[ExpectedException(typeof(ArgumentOutOfRangeException))]
public void target_id_less_than_0_throws_exception(int target)
{
var mocker = new AutoMoqer(MockBehavior.Strict);
mocker.Resolve<EpisodeSearchJob>().Start(new ProgressNotification("Test"), target);
}
[Test]
public void should_search_all_providers()
{
var parseResults = Builder<EpisodeParseResult>.CreateListOfSize(4)
.Build();
var episode = Builder<Episode>.CreateNew()
.With(c => c.Series = Builder<Series>.CreateNew().Build())
.With(c => c.SeasonNumber = 12)
.Build();
var mocker = new AutoMoqer(MockBehavior.Strict);
mocker.GetMock<EpisodeProvider>()
.Setup(c => c.GetEpisode(episode.EpisodeId))
.Returns(episode);
var indexer1 = new Mock<IndexerBase>();
indexer1.Setup(c => c.FetchEpisode(episode.Series.Title, episode.SeasonNumber, episode.EpisodeNumber))
.Returns(parseResults).Verifiable();
var indexer2 = new Mock<IndexerBase>();
indexer2.Setup(c => c.FetchEpisode(episode.Series.Title, episode.SeasonNumber, episode.EpisodeNumber))
.Returns(parseResults).Verifiable();
var indexers = new List<IndexerBase> { indexer1.Object, indexer2.Object };
mocker.GetMock<IndexerProvider>()
.Setup(c => c.GetEnabledIndexers())
.Returns(indexers);
mocker.GetMock<InventoryProvider>()
.Setup(c => c.IsNeeded(It.IsAny<EpisodeParseResult>())).Returns(false);
//Act
mocker.Resolve<EpisodeSearchJob>().Start(new ProgressNotification("Test"), episode.EpisodeId);
//Assert
mocker.VerifyAllMocks();
mocker.GetMock<InventoryProvider>().Verify(c => c.IsNeeded(It.IsAny<EpisodeParseResult>()), Times.Exactly(8));
ExceptionVerification.ExcpectedWarns(1);
indexer1.VerifyAll();
indexer2.VerifyAll();
}
[Test]
public void failed_indexer_should_not_break_job()
{
var parseResults = Builder<EpisodeParseResult>.CreateListOfSize(4)
.Build();
var episode = Builder<Episode>.CreateNew()
.With(c => c.Series = Builder<Series>.CreateNew().Build())
.With(c => c.SeasonNumber = 12)
.Build();
var mocker = new AutoMoqer(MockBehavior.Strict);
mocker.GetMock<EpisodeProvider>()
.Setup(c => c.GetEpisode(episode.EpisodeId))
.Returns(episode);
var indexer1 = new Mock<IndexerBase>();
indexer1.Setup(c => c.FetchEpisode(episode.Series.Title, episode.SeasonNumber, episode.EpisodeNumber))
.Returns(parseResults).Verifiable();
var indexer2 = new Mock<IndexerBase>();
indexer2.Setup(c => c.FetchEpisode(episode.Series.Title, episode.SeasonNumber, episode.EpisodeNumber))
.Throws(new Exception()).Verifiable();
var indexer3 = new Mock<IndexerBase>();
indexer2.Setup(c => c.FetchEpisode(episode.Series.Title, episode.SeasonNumber, episode.EpisodeNumber))
.Returns(parseResults).Verifiable();
var indexers = new List<IndexerBase> { indexer1.Object, indexer2.Object, indexer3.Object };
mocker.GetMock<IndexerProvider>()
.Setup(c => c.GetEnabledIndexers())
.Returns(indexers);
mocker.GetMock<InventoryProvider>()
.Setup(c => c.IsNeeded(It.IsAny<EpisodeParseResult>())).Returns(false);
//Act
mocker.Resolve<EpisodeSearchJob>().Start(new ProgressNotification("Test"), episode.EpisodeId);
//Assert
mocker.VerifyAllMocks();
mocker.GetMock<InventoryProvider>().Verify(c => c.IsNeeded(It.IsAny<EpisodeParseResult>()), Times.Exactly(8));
ExceptionVerification.ExcpectedWarns(1);
ExceptionVerification.ExcpectedErrors(1);
indexer1.VerifyAll();
indexer2.VerifyAll();
indexer3.VerifyAll();
}
[Test]
public void no_episode_found_should_return_with_error_logged()
{
var mocker = new AutoMoqer(MockBehavior.Strict);
mocker.GetMock<EpisodeProvider>()
.Setup(c => c.GetEpisode(It.IsAny<long>()))
.Returns<Episode>(null);
//Act
mocker.Resolve<EpisodeSearchJob>().Start(new ProgressNotification("Test"), 12);
//Assert
mocker.VerifyAllMocks();
ExceptionVerification.ExcpectedErrors(1);
}
}
}

View File

@ -23,6 +23,11 @@ namespace NzbDrone.Core.Providers.Indexer
_logger = LogManager.GetLogger(GetType().ToString());
}
public IndexerBase()
{
}
/// <summary>
/// Gets the name for the feed
/// </summary>
@ -73,7 +78,7 @@ namespace NzbDrone.Core.Providers.Indexer
/// <summary>
/// Fetches RSS feed and process each news item.
/// </summary>
public IList<EpisodeParseResult> FetchRss()
public virtual IList<EpisodeParseResult> FetchRss()
{
_logger.Debug("Fetching feeds from " + Name);
@ -89,7 +94,7 @@ namespace NzbDrone.Core.Providers.Indexer
}
public IList<EpisodeParseResult> FetchEpisode(string seriesTitle, int seasonNumber, int episodeNumber)
public virtual IList<EpisodeParseResult> FetchEpisode(string seriesTitle, int seasonNumber, int episodeNumber)
{
_logger.Debug("Searching {0} for {1}-S{2}E{3:00}", Name, seriesTitle, seasonNumber, episodeNumber);

View File

@ -39,16 +39,37 @@ namespace NzbDrone.Core.Providers.Jobs
public void Start(ProgressNotification notification, int targetId)
{
var reports = new List<EpisodeParseResult>();
if (targetId <= 0)
throw new ArgumentOutOfRangeException("targetId");
var episode = _episodeProvider.GetEpisode(targetId);
if (episode == null)
{
Logger.Error("Unbale to find an episode {0} in database", targetId);
return;
}
var indexers = _indexerProvider.GetEnabledIndexers();
var reports = new List<EpisodeParseResult>();
foreach (var indexer in indexers)
{
try
{
notification.CurrentMessage = String.Format("Searching for {0} in {1}", episode, indexer.Name);
reports.AddRange(indexer.FetchRss());
IList<EpisodeParseResult> indexerResults = new List<EpisodeParseResult>();
if (episode.IsDailyEpisode)
{
//TODO:Add support for daily episodes
}
else
{
indexerResults = indexer.FetchEpisode(episode.Series.Title, episode.SeasonNumber, episode.EpisodeNumber);
}
reports.AddRange(indexerResults);
}
catch (Exception e)
{
@ -80,7 +101,7 @@ namespace NzbDrone.Core.Providers.Jobs
Logger.ErrorException("An error has occurred while processing parse result items from " + episodeParseResult, e);
}
}
Logger.Warn("Unable to find {0} in any of indexers.", episode);
}
}

View File

@ -25,6 +25,14 @@ namespace NzbDrone.Core.Repository
public Boolean Ignored { get; set; }
[SubSonicIgnore]
public Boolean IsDailyEpisode
{
get
{
return EpisodeNumber == 0;
}
}
/// <summary>
/// Gets or sets the grab date.
@ -74,7 +82,7 @@ namespace NzbDrone.Core.Repository
{
var seriesTitle = Series == null ? "[NULL]" : Series.Title;
if (EpisodeNumber == 0)
if (IsDailyEpisode)
return string.Format("{0} - {1}", seriesTitle, AirDate.Date);
return string.Format("{0} - S{1:00}E{2}", seriesTitle, SeasonNumber, EpisodeNumber);