using System.Collections.Generic; using System.Linq; using FizzWare.NBuilder; using FluentAssertions; using Moq; using NUnit.Framework; using NzbDrone.Core.Jobs; using NzbDrone.Core.Model; using NzbDrone.Core.Model.Notification; using NzbDrone.Core.Providers; using NzbDrone.Core.Providers.Core; using NzbDrone.Core.Repository; using NzbDrone.Core.Test.Framework; using NzbDrone.Test.Common.AutoMoq; namespace NzbDrone.Core.Test.JobTests { [TestFixture] public class BacklogSearchJobTest : CoreTest { private void WithEnableBacklogSearching() { Mocker.GetMock().SetupGet(s => s.EnableBacklogSearching).Returns(true); } [Test] public void no_missing_epsiodes_should_not_trigger_any_search() { //Setup var notification = new ProgressNotification("Backlog Search Job Test"); var episodes = new List(); WithStrictMocker(); WithEnableBacklogSearching(); Mocker.GetMock() .Setup(s => s.EpisodesWithoutFiles(true)).Returns(episodes); //Act Mocker.Resolve().Start(notification, null); //Assert Mocker.GetMock().Verify(c => c.Start(notification, new { SeriesId = It.IsAny(), SeasonNumber = It.IsAny() }), Times.Never()); Mocker.GetMock().Verify(c => c.Start(notification, new { SeriesId = It.IsAny(), SeasonNumber = 0 }), Times.Never()); } [Test] public void individual_missing_episode() { //Setup var notification = new ProgressNotification("Backlog Search Job Test"); var series = Builder.CreateNew() .With(s => s.Monitored = true) .With(s => s.BacklogSetting = BacklogSettingType.Enable) .Build(); var episodes = Builder.CreateListOfSize(1) .All() .With(e => e.Series = series) .Build(); WithStrictMocker(); WithEnableBacklogSearching(); Mocker.GetMock() .Setup(s => s.EpisodesWithoutFiles(true)).Returns(episodes); Mocker.GetMock() .Setup(s => s.Start(notification, new { EpisodeId = 1 })); //Act Mocker.Resolve().Start(notification, null); //Assert Mocker.GetMock().Verify(c => c.Start(notification, new { SeriesId = It.IsAny(), SeasonNumber = It.IsAny() }), Times.Never()); Mocker.GetMock().Verify(c => c.Start(notification, new { EpisodeId = It.IsAny() }), Times.Once()); } [Test] public void individual_missing_episodes_only() { //Setup var notification = new ProgressNotification("Backlog Search Job Test"); var series = Builder.CreateNew() .With(s => s.Monitored = true) .With(s => s.BacklogSetting = BacklogSettingType.Enable) .Build(); var episodes = Builder.CreateListOfSize(5) .All() .With(e => e.Series = series) .Build(); WithStrictMocker(); WithEnableBacklogSearching(); Mocker.GetMock() .Setup(s => s.EpisodesWithoutFiles(true)).Returns(episodes); Mocker.GetMock() .Setup(s => s.Start(notification, new { EpisodeId = It.IsAny()})).Verifiable(); //Act Mocker.Resolve().Start(notification, null); //Assert Mocker.GetMock().Verify(c => c.Start(notification, new { SeriesId = It.IsAny(), SeasonNumber = It.IsAny() }), Times.Never()); Mocker.GetMock().Verify(c => c.Start(notification, new { SeriesId = It.IsAny(), SeasonNumber = 0 }), Times.Exactly(episodes.Count)); } [Test] public void series_season_missing_episodes_only_mismatch_count() { //Setup var notification = new ProgressNotification("Backlog Search Job Test"); var series = Builder.CreateNew() .With(s => s.Monitored = true) .With(s => s.BacklogSetting = BacklogSettingType.Enable) .Build(); var episodes = Builder.CreateListOfSize(5) .All() .With(e => e.Series = series) .With(e => e.SeasonNumber = 1) .Build(); WithStrictMocker(); WithEnableBacklogSearching(); Mocker.GetMock() .Setup(s => s.EpisodesWithoutFiles(true)).Returns(episodes); Mocker.GetMock() .Setup(s => s.Start(notification, new { EpisodeId = It.IsAny() })).Verifiable(); Mocker.GetMock() .Setup(s => s.GetEpisodeNumbersBySeason(1, 1)).Returns(new List { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); //Act Mocker.Resolve().Start(notification, null); //Assert Mocker.GetMock().Verify(c => c.Start(notification, new { SeriesId = It.IsAny(), SeasonNumber = It.IsAny() }), Times.Never()); Mocker.GetMock().Verify(c => c.Start(notification, new { EpisodeId = It.IsAny() }), Times.Exactly(episodes.Count)); } [Test] public void series_season_missing_episodes_only() { //Setup var notification = new ProgressNotification("Backlog Search Job Test"); var series = Builder.CreateNew() .With(s => s.Monitored = true) .With(s => s.BacklogSetting = BacklogSettingType.Enable) .Build(); var episodes = Builder.CreateListOfSize(5) .All() .With(e => e.Series = series) .With(e => e.SeriesId = series.SeriesId) .With(e => e.SeasonNumber = 1) .Build(); WithStrictMocker(); WithEnableBacklogSearching(); Mocker.GetMock() .Setup(s => s.EpisodesWithoutFiles(true)).Returns(episodes); Mocker.GetMock() .Setup(s => s.Start(notification, new { SeriesId = It.IsAny(), SeasonNumber = It.IsAny() })).Verifiable(); Mocker.GetMock() .Setup(s => s.GetEpisodeNumbersBySeason(1, 1)).Returns(episodes.Select(e => e.EpisodeNumber).ToList()); //Act Mocker.Resolve().Start(notification, null); //Assert Mocker.GetMock().Verify(c => c.Start(notification, new { SeriesId = It.IsAny(), SeasonNumber = It.IsAny() }), Times.Once()); Mocker.GetMock().Verify(c => c.Start(notification, new { EpisodeId = It.IsAny() }), Times.Never()); } [Test] public void multiple_missing_episodes() { //Setup var notification = new ProgressNotification("Backlog Search Job Test"); var series = Builder.CreateNew() .With(s => s.Monitored = true) .With(s => s.BacklogSetting = BacklogSettingType.Enable) .Build(); var series2 = Builder.CreateNew() .With(s => s.Monitored = true) .With(s => s.BacklogSetting = BacklogSettingType.Enable) .Build(); var episodes = Builder.CreateListOfSize(10) .TheFirst(5) .With(e => e.Series = series) .With(e => e.SeriesId = series.SeriesId) .With(e => e.SeasonNumber = 1) .TheNext(5) .With(e => e.Series = series2) .Build(); WithStrictMocker(); WithEnableBacklogSearching(); Mocker.GetMock() .Setup(s => s.EpisodesWithoutFiles(true)).Returns(episodes); Mocker.GetMock() .Setup(s => s.Start(notification, new { SeriesId = It.IsAny(), SeasonNumber = It.IsAny() })).Verifiable(); Mocker.GetMock() .Setup(s => s.Start(notification, new { EpisodeId = It.IsAny() })).Verifiable(); Mocker.GetMock() .Setup(s => s.GetEpisodeNumbersBySeason(1, 1)).Returns(new List { 1, 2, 3, 4, 5 }); //Act Mocker.Resolve().Start(notification, null); //Assert Mocker.GetMock().Verify(c => c.Start(notification, new { SeriesId = It.IsAny(), SeasonNumber = It.IsAny() }), Times.Once()); Mocker.GetMock().Verify(c => c.Start(notification, new { EpisodeId = It.IsAny() }), Times.Exactly(5)); } [Test] public void GetMissingForEnabledSeries_should_only_return_episodes_for_monitored_series() { //Setup var series = Builder.CreateListOfSize(2) .TheFirst(1) .With(s => s.Monitored = false) .With(s => s.BacklogSetting = BacklogSettingType.Enable) .TheNext(1) .With(s => s.Monitored = true) .With(s => s.BacklogSetting = BacklogSettingType.Enable) .Build(); var episodes = Builder.CreateListOfSize(11) .TheFirst(5) .With(e => e.Series = series[0]) .With(e => e.SeasonNumber = 1) .TheLast(6) .With(e => e.Series = series[1]) .Build(); WithEnableBacklogSearching(); Mocker.GetMock() .Setup(s => s.EpisodesWithoutFiles(true)).Returns(episodes); //Act var result = Mocker.Resolve().GetMissingForEnabledSeries(); //Assert result.Should().NotBeEmpty(); result.Should().Contain(s => s.Series.Monitored); result.Should().NotContain(s => !s.Series.Monitored); } [Test] public void GetMissingForEnabledSeries_should_only_return_explicity_enabled_series_when_backlog_searching_is_ignored() { //Setup var series = Builder.CreateListOfSize(3) .TheFirst(1) .With(s => s.Monitored = true) .With(s => s.BacklogSetting = BacklogSettingType.Disable) .TheNext(1) .With(s => s.Monitored = true) .With(s => s.BacklogSetting = BacklogSettingType.Enable) .TheNext(1) .With(s => s.Monitored = true) .With(s => s.BacklogSetting = BacklogSettingType.Inherit) .Build(); var episodes = Builder.CreateListOfSize(12) .TheFirst(3) .With(e => e.Series = series[0]) .TheNext(4) .With(e => e.Series = series[1]) .TheNext(5) .With(e => e.Series = series[2]) .Build(); //WithEnableBacklogSearching(); Mocker.GetMock() .Setup(s => s.EpisodesWithoutFiles(true)).Returns(episodes); //Act var result = Mocker.Resolve().GetMissingForEnabledSeries(); //Assert result.Should().NotBeEmpty(); result.Should().Contain(s => s.Series.BacklogSetting == BacklogSettingType.Enable); result.Should().NotContain(s => s.Series.BacklogSetting == BacklogSettingType.Disable); result.Should().NotContain(s => s.Series.BacklogSetting == BacklogSettingType.Inherit); } [Test] public void GetMissingForEnabledSeries_should_return_explicity_enabled_and_inherit_series_when_backlog_searching_is_enabled() { //Setup var series = Builder.CreateListOfSize(3) .TheFirst(1) .With(s => s.Monitored = true) .With(s => s.BacklogSetting = BacklogSettingType.Disable) .TheNext(1) .With(s => s.Monitored = true) .With(s => s.BacklogSetting = BacklogSettingType.Enable) .TheNext(1) .With(s => s.Monitored = true) .With(s => s.BacklogSetting = BacklogSettingType.Inherit) .Build(); var episodes = Builder.CreateListOfSize(12) .TheFirst(3) .With(e => e.Series = series[0]) .TheNext(4) .With(e => e.Series = series[1]) .TheNext(5) .With(e => e.Series = series[2]) .Build(); WithEnableBacklogSearching(); Mocker.GetMock() .Setup(s => s.EpisodesWithoutFiles(true)).Returns(episodes); //Act var result = Mocker.Resolve().GetMissingForEnabledSeries(); //Assert result.Should().NotBeEmpty(); result.Should().Contain(s => s.Series.BacklogSetting == BacklogSettingType.Enable); result.Should().NotContain(s => s.Series.BacklogSetting == BacklogSettingType.Disable); result.Should().Contain(s => s.Series.BacklogSetting == BacklogSettingType.Inherit); } } }