SeasonProvider Added to handle ignoring of Seasons.

This commit is contained in:
Mark McDowall 2012-02-20 19:25:19 -08:00
parent d27f14d7aa
commit 969f8ae5e2
10 changed files with 265 additions and 186 deletions

View File

@ -26,7 +26,7 @@ namespace NzbDrone.Core.Test.JobTests
Mocker.GetMock<EpisodeProvider>() Mocker.GetMock<EpisodeProvider>()
.Setup(c => c.GetSeasons(1)).Returns(seasons); .Setup(c => c.GetSeasons(1)).Returns(seasons);
Mocker.GetMock<EpisodeProvider>() Mocker.GetMock<SeasonProvider>()
.Setup(c => c.IsIgnored(It.IsAny<int>(), It.IsAny<int>())).Returns(false); .Setup(c => c.IsIgnored(It.IsAny<int>(), It.IsAny<int>())).Returns(false);
Mocker.GetMock<SeasonSearchJob>() Mocker.GetMock<SeasonSearchJob>()

View File

@ -115,6 +115,7 @@
<Compile Include="JobTests\RecentBacklogSearchJobTest.cs" /> <Compile Include="JobTests\RecentBacklogSearchJobTest.cs" />
<Compile Include="ProviderTests\AnalyticsProviderTests\AnalyticsProviderFixture.cs" /> <Compile Include="ProviderTests\AnalyticsProviderTests\AnalyticsProviderFixture.cs" />
<Compile Include="ProviderTests\ConfigProviderTests\ConfigCachingFixture.cs" /> <Compile Include="ProviderTests\ConfigProviderTests\ConfigCachingFixture.cs" />
<Compile Include="ProviderTests\SeasonProviderTest.cs" />
<Compile Include="ProviderTests\DecisionEngineTests\RetentionSpecificationFixture.cs" /> <Compile Include="ProviderTests\DecisionEngineTests\RetentionSpecificationFixture.cs" />
<Compile Include="ProviderTests\DecisionEngineTests\QualityAllowedByProfileSpecificationFixtrue.cs" /> <Compile Include="ProviderTests\DecisionEngineTests\QualityAllowedByProfileSpecificationFixtrue.cs" />
<Compile Include="ProviderTests\DecisionEngineTests\UpgradeHistorySpecificationFixtrue.cs" /> <Compile Include="ProviderTests\DecisionEngineTests\UpgradeHistorySpecificationFixtrue.cs" />

View File

@ -439,7 +439,6 @@ namespace NzbDrone.Core.Test.ProviderTests
result.Should().HaveSameCount(fakeEpisodes.Episodes); result.Should().HaveSameCount(fakeEpisodes.Episodes);
} }
[Test] [Test]
public void RefreshEpisodeInfo_ignore_season_zero() public void RefreshEpisodeInfo_ignore_season_zero()
{ {
@ -466,6 +465,10 @@ namespace NzbDrone.Core.Test.ProviderTests
.Setup(c => c.GetSeries(seriesId, true)) .Setup(c => c.GetSeries(seriesId, true))
.Returns(fakeEpisodes); .Returns(fakeEpisodes);
Mocker.GetMock<SeasonProvider>()
.Setup(s => s.IsIgnored(seriesId, 0))
.Returns(true);
//Act //Act
Mocker.Resolve<EpisodeProvider>().RefreshEpisodeInfo(fakeSeries); Mocker.Resolve<EpisodeProvider>().RefreshEpisodeInfo(fakeSeries);
@ -694,6 +697,10 @@ namespace NzbDrone.Core.Test.ProviderTests
.Setup(c => c.GetSeries(seriesId, true)) .Setup(c => c.GetSeries(seriesId, true))
.Returns(tvdbSeries); .Returns(tvdbSeries);
Mocker.GetMock<SeasonProvider>()
.Setup(s => s.IsIgnored(seriesId, It.IsAny<int>()))
.Returns(true);
//Act //Act
Mocker.Resolve<EpisodeProvider>().RefreshEpisodeInfo(fakeSeries); Mocker.Resolve<EpisodeProvider>().RefreshEpisodeInfo(fakeSeries);
@ -704,180 +711,6 @@ namespace NzbDrone.Core.Test.ProviderTests
result.Where(e => e.Ignored).Should().HaveCount(episodeCount); result.Where(e => e.Ignored).Should().HaveCount(episodeCount);
} }
[Test]
public void IsSeasonIgnored_should_return_true_if_all_episodes_ignored()
{
WithRealDb();
var episodes = Builder<Episode>.CreateListOfSize(4)
.All()
.With(c => c.Ignored = true)
.With(c => c.SeriesId = 10)
.With(c => c.SeasonNumber = 2)
.Build();
episodes.ToList().ForEach(c => Db.Insert(c));
//Act
var result = Mocker.Resolve<EpisodeProvider>().IsIgnored(10, 2);
//Assert
result.Should().BeTrue();
}
[Test]
public void IsSeasonIgnored_should_return_false_if_none_of_episodes_are_ignored()
{
WithRealDb();
var episodes = Builder<Episode>.CreateListOfSize(4)
.All()
.With(c => c.Ignored = false)
.With(c => c.SeriesId = 10)
.With(c => c.SeasonNumber = 2)
.Build();
episodes.ToList().ForEach(c => Db.Insert(c));
//Act
var result = Mocker.Resolve<EpisodeProvider>().IsIgnored(10, 2);
//Assert
result.Should().BeFalse();
}
[Test]
public void IsSeasonIgnored_should_return_false_if_some_of_episodes_are_ignored()
{
WithRealDb();
var episodes = Builder<Episode>.CreateListOfSize(4)
.All()
.With(c => c.SeriesId = 10)
.With(c => c.SeasonNumber = 2)
.With(c => c.Ignored = true)
.Build();
episodes[2].Ignored = false;
episodes.ToList().ForEach(c => Db.Insert(c));
//Act
var result = Mocker.Resolve<EpisodeProvider>().IsIgnored(10, 2);
//Assert
result.Should().BeFalse();
}
[Test]
public void IsSeasonIgnored_should_return_false_if_zero_episodes_in_db_for_season()
{
WithRealDb();
var episodes = Builder<Episode>.CreateListOfSize(4)
.All()
.With(c => c.SeriesId = 10)
.With(c => c.SeasonNumber = 3)
.With(c => c.Ignored = true)
.Build();
episodes.ToList().ForEach(c => Db.Insert(c));
//Act
var result = Mocker.Resolve<EpisodeProvider>().IsIgnored(10, 2);
//Assert
result.Should().BeFalse();
}
[Test]
public void IsSeasonIgnored_should_return_true_if_zero_episodes_in_db_for_season_and_previous_is_ignored()
{
WithRealDb();
var episodes = Builder<Episode>.CreateListOfSize(4)
.All()
.With(c => c.SeriesId = 10)
.With(c => c.SeasonNumber = 3)
.With(c => c.Ignored = true)
.Build();
episodes.ToList().ForEach(c => Db.Insert(c));
//Act
var result = Mocker.Resolve<EpisodeProvider>().IsIgnored(10, 4);
//Assert
result.Should().BeTrue();
}
[Test]
public void IsSeasonIgnored_should_return_false_if_zero_episodes_in_db_for_season_and_previous_is_not_ignored()
{
WithRealDb();
var episodes = Builder<Episode>.CreateListOfSize(4)
.All()
.With(c => c.SeriesId = 10)
.With(c => c.SeasonNumber = 3)
.With(c => c.Ignored = false)
.Build();
episodes.ToList().ForEach(c => Db.Insert(c));
//Act
var result = Mocker.Resolve<EpisodeProvider>().IsIgnored(10, 4);
//Assert
result.Should().BeFalse();
}
[Test]
public void IsSeasonIgnored_should_return_false_if_zero_episodes_in_db_for_season_one()
{
WithRealDb();
//Act
var result = Mocker.Resolve<EpisodeProvider>().IsIgnored(10, 1);
//Assert
result.Should().BeFalse();
}
[Test]
public void IsSeasonIgnored_should_return_true_if_zero_episodes_in_db_for_season_zero()
{
WithRealDb();
//Act
var result = Mocker.Resolve<EpisodeProvider>().IsIgnored(10, 0);
//Assert
result.Should().BeTrue();
}
[Test]
public void IsSeasonIgnored_should_return_false_if_season_zero_is_not_ignored()
{
WithRealDb();
var episodes = Builder<Episode>.CreateListOfSize(4)
.All()
.With(c => c.SeriesId = 10)
.With(c => c.SeasonNumber = 0)
.With(c => c.Ignored = false)
.Build();
episodes.ToList().ForEach(c => Db.Insert(c));
//Act
var result = Mocker.Resolve<EpisodeProvider>().IsIgnored(10, 0);
//Assert
result.Should().BeFalse();
}
[Test] [Test]
[Explicit] [Explicit]
public void Add_daily_show_episodes() public void Add_daily_show_episodes()
@ -1049,6 +882,10 @@ namespace NzbDrone.Core.Test.ProviderTests
.With(e => e.Ignored = false) .With(e => e.Ignored = false)
.Build(); .Build();
Mocker.GetMock<SeasonProvider>()
.Setup(s => s.IsIgnored(newEpisode.SeriesId, newEpisode.SeasonNumber))
.Returns(true);
//Act //Act
Mocker.Resolve<EpisodeProvider>().AddEpisode(newEpisode); Mocker.Resolve<EpisodeProvider>().AddEpisode(newEpisode);

View File

@ -0,0 +1,193 @@
// ReSharper disable RedundantUsingDirective
using System;
using System.Collections.Generic;
using System.Linq;
using FizzWare.NBuilder;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Common;
using NzbDrone.Core.Model;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Repository;
using NzbDrone.Core.Repository.Quality;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common.AutoMoq;
using PetaPoco;
using TvdbLib.Data;
namespace NzbDrone.Core.Test.ProviderTests
{
[TestFixture]
// ReSharper disable InconsistentNaming
public class SeasonProviderTest : CoreTest
{
[Test]
public void AddSeason_should_insert_season_to_database_with_ignored_false()
{
WithRealDb();
var seriesId = 10;
var seasonNumber = 50;
//Act
Mocker.Resolve<SeasonProvider>().Add(seriesId, seasonNumber);
//Assert
var result = Db.Fetch<Season>();
result.Should().HaveCount(1);
result.First().SeriesId.Should().Be(seriesId);
result.First().SeasonNumber.Should().Be(seasonNumber);
result.First().Ignored.Should().BeFalse();
}
[TestCase(true)]
[TestCase(false)]
public void AddSeason_should_insert_season_to_database_with_preset_ignored_status(bool isIgnored)
{
WithRealDb();
var seriesId = 10;
var seasonNumber = 50;
//Act
Mocker.Resolve<SeasonProvider>().Add(seriesId, seasonNumber, isIgnored);
//Assert
var result = Db.Fetch<Season>();
result.Should().HaveCount(1);
result.First().SeriesId.Should().Be(seriesId);
result.First().SeasonNumber.Should().Be(seasonNumber);
result.First().Ignored.Should().Be(isIgnored);
}
[Test]
public void DeleteSeason_should_remove_season_from_database()
{
WithRealDb();
var fakeSeason = Builder<Season>.CreateNew().Build();
Db.Insert(fakeSeason);
//Act
Mocker.Resolve<SeasonProvider>().Delete(fakeSeason.SeriesId, fakeSeason.SeasonNumber);
//Assert
var result = Db.Fetch<Season>();
result.Should().BeEmpty();
}
[Test]
public void SetIgnore_should_update_ignored_status()
{
WithRealDb();
var fakeSeason = Builder<Season>.CreateNew()
.With(s => s.Ignored = false)
.Build();
var id = Db.Insert(fakeSeason);
//Act
Mocker.Resolve<SeasonProvider>().SetIgnore(fakeSeason.SeriesId, fakeSeason.SeasonNumber, true);
//Assert
var result = Db.SingleOrDefault<Season>(id);
result.Ignored.Should().BeTrue();
}
[Test]
public void IsIgnored_should_return_ignored_status_of_season()
{
//Setup
var fakeSeason = Builder<Season>.CreateNew()
.With(s => s.Ignored = false)
.Build();
Db.Insert(fakeSeason);
//Act
var result = Mocker.Resolve<SeasonProvider>().IsIgnored(fakeSeason.SeriesId, fakeSeason.SeasonNumber);
//Assert
result.Should().Be(fakeSeason.Ignored);
Db.Fetch<Season>().Count.Should().Be(1);
}
[Test]
public void IsIgnored_should_return_true_if_not_in_db_and_is_season_zero()
{
//Setup
WithRealDb();
//Act
var result = Mocker.Resolve<SeasonProvider>().IsIgnored(10, 0);
//Assert
result.Should().BeTrue();
Db.Fetch<Season>().Should().HaveCount(1);
}
[Test]
public void IsIgnored_should_return_false_if_not_in_db_and_is_season_one()
{
//Setup
WithRealDb();
//Act
var result = Mocker.Resolve<SeasonProvider>().IsIgnored(10, 1);
//Assert
result.Should().BeFalse();
Db.Fetch<Season>().Should().HaveCount(1);
}
[Test]
public void IsIgnored_should_return_false_if_not_in_db_and_previous_season_is_not_ignored()
{
//Setup
WithRealDb();
var lastSeason = Builder<Season>.CreateNew()
.With(s => s.SeriesId = 10)
.With(s => s.SeasonNumber = 4)
.With(s => s.Ignored = true)
.Build();
Db.Insert(lastSeason);
//Act
var result = Mocker.Resolve<SeasonProvider>().IsIgnored(10, 5);
//Assert
result.Should().BeFalse();
Db.Fetch<Season>().Should().HaveCount(2);
}
[Test]
public void IsIgnored_should_return_true_if_not_in_db_and_previous_season_is_ignored()
{
//Setup
WithRealDb();
var lastSeason = Builder<Season>.CreateNew()
.With(s => s.SeriesId = 10)
.With(s => s.SeasonNumber = 4)
.With(s => s.Ignored = true)
.Build();
Db.Insert(lastSeason);
//Act
var result = Mocker.Resolve<SeasonProvider>().IsIgnored(10, 5);
//Assert
result.Should().BeTrue();
Db.Fetch<Season>().Should().HaveCount(2);
}
}
}

View File

@ -0,0 +1,22 @@
using System;
using System.Data;
using Migrator.Framework;
namespace NzbDrone.Core.Datastore.Migrations
{
[Migration(20120220)]
public class Migration20120220 : NzbDroneMigration
{
protected override void MainDbUpgrade()
{
Database.AddTable("Seasons", new[]
{
new Column("SeasonId", DbType.Int32, ColumnProperty.PrimaryKeyWithIdentity),
new Column("SeriesId", DbType.Int32, ColumnProperty.NotNull),
new Column("SeasonNumber", DbType.Int32, ColumnProperty.NotNull),
new Column("Ignored", DbType.Boolean, ColumnProperty.NotNull)
});
}
}
}

View File

@ -8,15 +8,16 @@ namespace NzbDrone.Core.Jobs
{ {
public class SeriesSearchJob : IJob public class SeriesSearchJob : IJob
{ {
private readonly EpisodeProvider _episodeProvider;
private readonly SeasonSearchJob _seasonSearchJob; private readonly SeasonSearchJob _seasonSearchJob;
private readonly SeasonProvider _seasonProvider;
private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
public SeriesSearchJob(EpisodeProvider episodeProvider, SeasonSearchJob seasonSearchJob) public SeriesSearchJob(SeasonSearchJob seasonSearchJob,
SeasonProvider seasonProvider)
{ {
_episodeProvider = episodeProvider;
_seasonSearchJob = seasonSearchJob; _seasonSearchJob = seasonSearchJob;
_seasonProvider = seasonProvider;
} }
public string Name public string Name
@ -35,12 +36,12 @@ namespace NzbDrone.Core.Jobs
throw new ArgumentOutOfRangeException("targetId"); throw new ArgumentOutOfRangeException("targetId");
Logger.Debug("Getting seasons from database for series: {0}", targetId); Logger.Debug("Getting seasons from database for series: {0}", targetId);
var seasons = _episodeProvider.GetSeasons(targetId).Where(s => s > 0); var seasons = _seasonProvider.GetSeasons(targetId).Where(s => s > 0);
foreach (var season in seasons) foreach (var season in seasons)
{ {
//Skip ignored seasons //Skip ignored seasons
if (_episodeProvider.IsIgnored(targetId, season)) if (_seasonProvider.IsIgnored(targetId, season))
continue; continue;
_seasonSearchJob.Start(notification, targetId, season); _seasonSearchJob.Start(notification, targetId, season);

View File

@ -222,6 +222,7 @@
<Compile Include="Datastore\MigrationLogger.cs" /> <Compile Include="Datastore\MigrationLogger.cs" />
<Compile Include="Datastore\MigrationsHelper.cs" /> <Compile Include="Datastore\MigrationsHelper.cs" />
<Compile Include="Datastore\CustomeMapper.cs" /> <Compile Include="Datastore\CustomeMapper.cs" />
<Compile Include="Datastore\Migrations\Migration20120220.cs" />
<Compile Include="Datastore\Migrations\Migration20120123.cs" /> <Compile Include="Datastore\Migrations\Migration20120123.cs" />
<Compile Include="Datastore\Migrations\Migration20120118.cs" /> <Compile Include="Datastore\Migrations\Migration20120118.cs" />
<Compile Include="Datastore\Migrations\Migration20111125.cs" /> <Compile Include="Datastore\Migrations\Migration20111125.cs" />
@ -269,6 +270,7 @@
<Compile Include="Model\Xbmc\ErrorResult.cs" /> <Compile Include="Model\Xbmc\ErrorResult.cs" />
<Compile Include="Model\Xbmc\IconType.cs" /> <Compile Include="Model\Xbmc\IconType.cs" />
<Compile Include="Providers\BackupProvider.cs" /> <Compile Include="Providers\BackupProvider.cs" />
<Compile Include="Providers\SeasonProvider.cs" />
<Compile Include="Providers\DecisionEngine\AlreadyInQueueSpecification.cs" /> <Compile Include="Providers\DecisionEngine\AlreadyInQueueSpecification.cs" />
<Compile Include="Providers\DecisionEngine\RetentionSpecification.cs" /> <Compile Include="Providers\DecisionEngine\RetentionSpecification.cs" />
<Compile Include="Providers\DownloadClients\BlackholeProvider.cs" /> <Compile Include="Providers\DownloadClients\BlackholeProvider.cs" />
@ -337,6 +339,7 @@
<Compile Include="Jobs\UpdateInfoJob.cs" /> <Compile Include="Jobs\UpdateInfoJob.cs" />
<Compile Include="Providers\SceneMappingProvider.cs" /> <Compile Include="Providers\SceneMappingProvider.cs" />
<Compile Include="Providers\Xbmc\EventClientProvider.cs" /> <Compile Include="Providers\Xbmc\EventClientProvider.cs" />
<Compile Include="Repository\Season.cs" />
<Compile Include="Repository\NewznabDefinition.cs" /> <Compile Include="Repository\NewznabDefinition.cs" />
<Compile Include="Repository\ExternalNotificationDefinition.cs" /> <Compile Include="Repository\ExternalNotificationDefinition.cs" />
<Compile Include="Repository\JobDefinition.cs" /> <Compile Include="Repository\JobDefinition.cs" />

View File

@ -20,13 +20,16 @@ namespace NzbDrone.Core.Providers
private static readonly Regex multiPartCleanupRegex = new Regex(@"\(\d+\)$", RegexOptions.Compiled); private static readonly Regex multiPartCleanupRegex = new Regex(@"\(\d+\)$", RegexOptions.Compiled);
private readonly TvDbProvider _tvDbProvider; private readonly TvDbProvider _tvDbProvider;
private readonly SeasonProvider _seasonProvider;
private readonly IDatabase _database; private readonly IDatabase _database;
private readonly SeriesProvider _seriesProvider; private readonly SeriesProvider _seriesProvider;
[Inject] [Inject]
public EpisodeProvider(IDatabase database, SeriesProvider seriesProvider, TvDbProvider tvDbProviderProvider) public EpisodeProvider(IDatabase database, SeriesProvider seriesProvider,
TvDbProvider tvDbProviderProvider, SeasonProvider seasonProvider)
{ {
_tvDbProvider = tvDbProviderProvider; _tvDbProvider = tvDbProviderProvider;
_seasonProvider = seasonProvider;
_database = database; _database = database;
_seriesProvider = seriesProvider; _seriesProvider = seriesProvider;
} }
@ -38,8 +41,7 @@ namespace NzbDrone.Core.Providers
public virtual void AddEpisode(Episode episode) public virtual void AddEpisode(Episode episode)
{ {
//If Season is ignored ignore this episode //If Season is ignored ignore this episode
if (IsIgnored(episode.SeriesId, episode.SeasonNumber)) episode.Ignored = _seasonProvider.IsIgnored(episode.SeriesId, episode.SeasonNumber);
episode.Ignored = true;
_database.Insert(episode); _database.Insert(episode);
} }
@ -312,7 +314,7 @@ namespace NzbDrone.Core.Providers
//Else we need to check if this episode should be ignored based on IsIgnored rules //Else we need to check if this episode should be ignored based on IsIgnored rules
else else
{ {
episodeToUpdate.Ignored = IsIgnored(series.SeriesId, episode.SeasonNumber); episodeToUpdate.Ignored = _seasonProvider.IsIgnored(series.SeriesId, episode.SeasonNumber);
} }
} }
else else
@ -396,10 +398,14 @@ namespace NzbDrone.Core.Providers
return _database.Fetch<int>("SELECT EpisodeNumber FROM Episodes WHERE SeriesId=@0 AND SeasonNumber=@1", seriesId, seasonNumber).OrderBy(c => c).ToList(); return _database.Fetch<int>("SELECT EpisodeNumber FROM Episodes WHERE SeriesId=@0 AND SeasonNumber=@1", seriesId, seasonNumber).OrderBy(c => c).ToList();
} }
public virtual void SetSeasonIgnore(long seriesId, int seasonNumber, bool isIgnored) public virtual void SetSeasonIgnore(int seriesId, int seasonNumber, bool isIgnored)
{ {
logger.Info("Setting ignore flag on Series:{0} Season:{1} to {2}", seriesId, seasonNumber, isIgnored); logger.Info("Setting ignore flag on Series:{0} Season:{1} to {2}", seriesId, seasonNumber, isIgnored);
//Set the SeasonIgnore
_seasonProvider.SetIgnore(seriesId, seasonNumber, isIgnored);
//Ignore all the episodes in the season
_database.Execute(@"UPDATE Episodes SET Ignored = @0 _database.Execute(@"UPDATE Episodes SET Ignored = @0
WHERE SeriesId = @1 AND SeasonNumber = @2 AND Ignored = @3", WHERE SeriesId = @1 AND SeasonNumber = @2 AND Ignored = @3",
isIgnored, seriesId, seasonNumber, !isIgnored); isIgnored, seriesId, seasonNumber, !isIgnored);

Binary file not shown.

View File

@ -0,0 +1,16 @@
using System;
using NzbDrone.Core.Model;
using PetaPoco;
namespace NzbDrone.Core.Repository
{
[TableName("Seasons")]
[PrimaryKey("SeasonId", autoIncrement = true)]
public class Season
{
public int SeasonId { get; set; }
public int SeriesId { get; set; }
public int SeasonNumber { get; set; }
public Boolean Ignored { get; set; }
}
}