From 0ed898b6db9b88b6ba2dfddef1cc1a5753062fd4 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Fri, 22 Jul 2011 17:57:52 -0700 Subject: [PATCH] IsIgnored will now be checked when adding new episodes to the DB, it will: - ignore new episodes of a season if that season was already ignored - ignore new seasons if the previous was ignored - ignore specials (when a new series is added), if a user chooses to download specials, all new specials will not be ignored Added tests for IsIgnored and AddEpisode changes. --- NzbDrone.Core.Test/EpisodeProviderTest.cs | 225 ++++++++++++++++++++- NzbDrone.Core/Datastore/CustomeMapper.cs | 4 + NzbDrone.Core/Providers/EpisodeProvider.cs | 35 +++- 3 files changed, 248 insertions(+), 16 deletions(-) diff --git a/NzbDrone.Core.Test/EpisodeProviderTest.cs b/NzbDrone.Core.Test/EpisodeProviderTest.cs index 2a0398fba..03e12b013 100644 --- a/NzbDrone.Core.Test/EpisodeProviderTest.cs +++ b/NzbDrone.Core.Test/EpisodeProviderTest.cs @@ -47,7 +47,6 @@ namespace NzbDrone.Core.Test episode.Series.ShouldHave().AllProperties().EqualTo(fakeSeries); } - [Test] public void GetEpisodes_by_season_episode_exists() { @@ -336,8 +335,9 @@ namespace NzbDrone.Core.Test var currentEpisodes = new List(); - var mocker = new AutoMoqer(); + var db = MockLib.GetEmptyDatabase(); + mocker.SetConstant(db); mocker.GetMock(MockBehavior.Strict) .Setup(c => c.GetSeries(seriesId, true)) @@ -586,19 +586,125 @@ namespace NzbDrone.Core.Test } [Test] - public void IsSeasonIgnored_should_return_true_if_invalid_series() + public void IsSeasonIgnored_should_return_false_if_zero_episodes_in_db_for_season() { var db = MockLib.GetEmptyDatabase(); var mocker = new AutoMoqer(MockBehavior.Strict); mocker.SetConstant(db); + var episodes = Builder.CreateListOfSize(4) + .WhereAll() + .Have(c => c.SeriesId = 10) + .Have(c => c.SeasonNumber = 3) + .Have(c => c.Ignored = true) + .Build(); + + episodes.ToList().ForEach(c => db.Insert(c)); + //Act var result = mocker.Resolve().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() + { + var db = MockLib.GetEmptyDatabase(); + var mocker = new AutoMoqer(MockBehavior.Strict); + mocker.SetConstant(db); + + var episodes = Builder.CreateListOfSize(4) + .WhereAll() + .Have(c => c.SeriesId = 10) + .Have(c => c.SeasonNumber = 3) + .Have(c => c.Ignored = true) + .Build(); + + episodes.ToList().ForEach(c => db.Insert(c)); + + //Act + var result = mocker.Resolve().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() + { + var db = MockLib.GetEmptyDatabase(); + var mocker = new AutoMoqer(MockBehavior.Strict); + mocker.SetConstant(db); + + var episodes = Builder.CreateListOfSize(4) + .WhereAll() + .Have(c => c.SeriesId = 10) + .Have(c => c.SeasonNumber = 3) + .Have(c => c.Ignored = false) + .Build(); + + episodes.ToList().ForEach(c => db.Insert(c)); + + //Act + var result = mocker.Resolve().IsIgnored(10, 4); + + //Assert + result.Should().BeFalse(); + } + + [Test] + public void IsSeasonIgnored_should_return_false_if_zero_episodes_in_db_for_season_one() + { + var db = MockLib.GetEmptyDatabase(); + var mocker = new AutoMoqer(MockBehavior.Strict); + mocker.SetConstant(db); + + //Act + var result = mocker.Resolve().IsIgnored(10, 1); + + //Assert + result.Should().BeFalse(); + } + + [Test] + public void IsSeasonIgnored_should_return_true_if_zero_episodes_in_db_for_season_zero() + { + var db = MockLib.GetEmptyDatabase(); + var mocker = new AutoMoqer(MockBehavior.Strict); + mocker.SetConstant(db); + + //Act + var result = mocker.Resolve().IsIgnored(10, 0); + + //Assert + result.Should().BeTrue(); + } + + [Test] + public void IsSeasonIgnored_should_return_false_if_season_zero_is_not_ignored() + { + var db = MockLib.GetEmptyDatabase(); + var mocker = new AutoMoqer(MockBehavior.Strict); + mocker.SetConstant(db); + + var episodes = Builder.CreateListOfSize(4) + .WhereAll() + .Have(c => c.SeriesId = 10) + .Have(c => c.SeasonNumber = 0) + .Have(c => c.Ignored = false) + .Build(); + + episodes.ToList().ForEach(c => db.Insert(c)); + + //Act + var result = mocker.Resolve().IsIgnored(10, 0); + + //Assert + result.Should().BeFalse(); + } + [Test] [Explicit] public void Add_daily_show_episodes() @@ -643,7 +749,6 @@ namespace NzbDrone.Core.Test episode.Should().BeNull(); } - [Test] public void GetEpisode_by_Season_Episode_with_EpisodeFile() { @@ -672,8 +777,6 @@ namespace NzbDrone.Core.Test episode.EpisodeFile.Should().NotBeNull(); } - - [Test] public void GetEpisode_by_Season_Episode_without_EpisodeFile() { @@ -700,9 +803,6 @@ namespace NzbDrone.Core.Test episode.EpisodeFile.Should().BeNull(); } - - - [Test] public void GetEpisode_by_AirDate_with_EpisodeFile() { @@ -781,8 +881,115 @@ namespace NzbDrone.Core.Test episodes.Where(e => e.GrabDate == null).Should().HaveCount(4); } + [Test] + public void AddEpisode_episode_is_ignored_when_full_season_is_ignored() + { + var db = MockLib.GetEmptyDatabase(); + var mocker = new AutoMoqer(); + mocker.SetConstant(db); + + var episodes = Builder.CreateListOfSize(4) + .WhereAll() + .Have(c => c.SeriesId = 10) + .Have(c => c.SeasonNumber = 1) + .Have(c => c.Ignored = true) + .Build().ToList(); + + episodes.ForEach(c => db.Insert(c)); + + var newEpisode = Builder.CreateNew() + .With(e => e.SeriesId = 10) + .With(e => e.SeasonNumber = 1) + .With(e => e.EpisodeNumber = 8) + .With(e => e.SeasonNumber = 1) + .With(e => e.Ignored = false) + .Build(); + + //Act + mocker.Resolve().AddEpisode(newEpisode); + + //Assert + var episodesInDb = db.Fetch(@"SELECT * FROM Episodes"); + + episodesInDb.Should().HaveCount(5); + episodesInDb.Should().OnlyContain(e => e.Ignored); + + mocker.VerifyAllMocks(); + } + + [Test] + public void AddEpisode_episode_is_not_ignored_when_full_season_is_not_ignored() + { + var db = MockLib.GetEmptyDatabase(); + var mocker = new AutoMoqer(); + mocker.SetConstant(db); + var episodes = Builder.CreateListOfSize(4) + .WhereAll() + .Have(c => c.SeriesId = 10) + .Have(c => c.SeasonNumber = 1) + .Have(c => c.Ignored = false) + .Build().ToList(); + episodes.ForEach(c => db.Insert(c)); + + var newEpisode = Builder.CreateNew() + .With(e => e.SeriesId = 10) + .With(e => e.SeasonNumber = 1) + .With(e => e.EpisodeNumber = 8) + .With(e => e.SeasonNumber = 1) + .With(e => e.Ignored = false) + .Build(); + //Act + mocker.Resolve().AddEpisode(newEpisode); + + //Assert + var episodesInDb = db.Fetch(@"SELECT * FROM Episodes"); + + episodesInDb.Should().HaveCount(5); + episodesInDb.Should().OnlyContain(e => e.Ignored == false); + + mocker.VerifyAllMocks(); + } + + [Test] + public void AddEpisode_episode_is_not_ignored_when_not_full_season_is_not_ignored() + { + var db = MockLib.GetEmptyDatabase(); + var mocker = new AutoMoqer(); + mocker.SetConstant(db); + + var episodes = Builder.CreateListOfSize(4) + .WhereAll() + .Have(c => c.SeriesId = 10) + .Have(c => c.SeasonNumber = 1) + .WhereTheFirst(2) + .Have(c => c.Ignored = false) + .AndTheRemaining() + .Have(c => c.Ignored = true) + .Build().ToList(); + + episodes.ForEach(c => db.Insert(c)); + + var newEpisode = Builder.CreateNew() + .With(e => e.SeriesId = 10) + .With(e => e.SeasonNumber = 1) + .With(e => e.EpisodeNumber = 8) + .With(e => e.SeasonNumber = 1) + .With(e => e.Ignored = false) + .Build(); + + //Act + mocker.Resolve().AddEpisode(newEpisode); + + //Assert + var episodesInDb = db.Fetch(@"SELECT * FROM Episodes"); + + episodesInDb.Should().HaveCount(5); + episodesInDb.Where(e => e.EpisodeNumber == 8 && !e.Ignored).Should().HaveCount(1); + + mocker.VerifyAllMocks(); + } } } \ No newline at end of file diff --git a/NzbDrone.Core/Datastore/CustomeMapper.cs b/NzbDrone.Core/Datastore/CustomeMapper.cs index 14979cbe4..74b322450 100644 --- a/NzbDrone.Core/Datastore/CustomeMapper.cs +++ b/NzbDrone.Core/Datastore/CustomeMapper.cs @@ -36,6 +36,10 @@ namespace NzbDrone.Core.Datastore public override Func GetFromDbConverter(PropertyInfo propertyInfo, Type sourceType) { + //Only needed if using dynamic as the return type from DB, not implemented currently as it has no use right now + //if (propertyInfo == null) + // return null; + return GetFromDbConverter(propertyInfo.PropertyType, sourceType); } } diff --git a/NzbDrone.Core/Providers/EpisodeProvider.cs b/NzbDrone.Core/Providers/EpisodeProvider.cs index 8759d6c2e..a3284ed86 100644 --- a/NzbDrone.Core/Providers/EpisodeProvider.cs +++ b/NzbDrone.Core/Providers/EpisodeProvider.cs @@ -30,6 +30,10 @@ namespace NzbDrone.Core.Providers public virtual void AddEpisode(Episode episode) { + //If Season is ignored ignore this episode + if (IsIgnored(episode.SeriesId, episode.SeasonNumber)) + episode.Ignored = true; + _database.Insert(episode); } @@ -105,14 +109,12 @@ namespace NzbDrone.Core.Providers return episodes; } - public virtual void MarkEpisodeAsFetched(int episodeId) { Logger.Trace("Marking episode {0} as fetched.", episodeId); _database.Execute("UPDATE Episodes SET GrabDate=@0 WHERE EpisodeId=@1", DateTime.Now, episodeId); } - public virtual IList GetEpisodesByParseResult(EpisodeParseResult parseResult, Boolean autoAddNew = false) { var result = new List(); @@ -238,7 +240,7 @@ namespace NzbDrone.Core.Providers using (var tran = _database.GetTransaction()) { - newList.ForEach(episode => _database.Insert(episode)); + newList.ForEach(AddEpisode); updateList.ForEach(episode => _database.Update(episode)); //Shouldn't run if Database is a mock since transaction will be null @@ -246,7 +248,6 @@ namespace NzbDrone.Core.Providers { tran.Complete(); } - } Logger.Info("Finished episode refresh for series: {0}. Successful: {1} - Failed: {2} ", @@ -260,11 +261,31 @@ namespace NzbDrone.Core.Providers public virtual bool IsIgnored(int seriesId, int seasonNumber) { + var episodes =_database.Fetch(@"SELECT * FROM Episodes WHERE SeriesId=@0 AND SeasonNumber=@1", seriesId, seasonNumber); + + if (episodes == null || episodes.Count == 0) + { + if (seasonNumber == 0) + return true; + + //Don't check for a previous season if season is 1 + if (seasonNumber == 1) + return false; + + //else + var lastSeasonsEpisodes =_database.Fetch(@"SELECT * FROM Episodes + WHERE SeriesId=@0 AND SeasonNumber=@1", seriesId, seasonNumber - 1); + + if (lastSeasonsEpisodes !=null && lastSeasonsEpisodes.Count > 0 && lastSeasonsEpisodes.Count == lastSeasonsEpisodes.Where(e => e.Ignored).Count()) + return true; + + return false; + } - var unIgnoredCount = _database.ExecuteScalar( - "SELECT COUNT (*) FROM Episodes WHERE SeriesId=@0 AND SeasonNumber=@1 AND Ignored='0'", seriesId, seasonNumber); + if (episodes.Count == episodes.Where(e => e.Ignored).Count()) + return true; - return unIgnoredCount == 0; + return false; } public virtual IList GetSeasons(int seriesId)