You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
535 lines
19 KiB
535 lines
19 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using FizzWare.NBuilder;
|
|
using Moq;
|
|
using NUnit.Framework;
|
|
using NzbDrone.Core.Configuration;
|
|
using NzbDrone.Core.ImportLists;
|
|
using NzbDrone.Core.ImportLists.Exclusions;
|
|
using NzbDrone.Core.ImportLists.ImportListItems;
|
|
using NzbDrone.Core.MetadataSource;
|
|
using NzbDrone.Core.Parser.Model;
|
|
using NzbDrone.Core.Test.Framework;
|
|
using NzbDrone.Core.Tv;
|
|
|
|
namespace NzbDrone.Core.Test.ImportListTests
|
|
{
|
|
public class ImportListSyncServiceFixture : CoreTest<ImportListSyncService>
|
|
{
|
|
private ImportListFetchResult _importListFetch;
|
|
private List<ImportListItemInfo> _list1Series;
|
|
private List<ImportListItemInfo> _list2Series;
|
|
|
|
private List<Series> _existingSeries;
|
|
private List<IImportList> _importLists;
|
|
private ImportListSyncCommand _commandAll;
|
|
private ImportListSyncCommand _commandSingle;
|
|
|
|
[SetUp]
|
|
public void SetUp()
|
|
{
|
|
_importLists = new List<IImportList>();
|
|
|
|
var item1 = new ImportListItemInfo()
|
|
{
|
|
Title = "Breaking Bad"
|
|
};
|
|
|
|
_list1Series = new List<ImportListItemInfo>() { item1 };
|
|
|
|
_existingSeries = Builder<Series>.CreateListOfSize(3)
|
|
.TheFirst(1)
|
|
.With(s => s.TvdbId = 6)
|
|
.With(s => s.ImdbId = "6")
|
|
.TheNext(1)
|
|
.With(s => s.TvdbId = 7)
|
|
.With(s => s.ImdbId = "7")
|
|
.TheNext(1)
|
|
.With(s => s.TvdbId = 8)
|
|
.With(s => s.ImdbId = "8")
|
|
.Build().ToList();
|
|
|
|
_list2Series = Builder<ImportListItemInfo>.CreateListOfSize(3)
|
|
.TheFirst(1)
|
|
.With(s => s.TvdbId = 6)
|
|
.With(s => s.ImdbId = "6")
|
|
.TheNext(1)
|
|
.With(s => s.TvdbId = 7)
|
|
.With(s => s.ImdbId = "7")
|
|
.TheNext(1)
|
|
.With(s => s.TvdbId = 8)
|
|
.With(s => s.ImdbId = "8")
|
|
.Build().ToList();
|
|
|
|
_importListFetch = new ImportListFetchResult(_list1Series, false);
|
|
|
|
_commandAll = new ImportListSyncCommand
|
|
{
|
|
};
|
|
|
|
_commandSingle = new ImportListSyncCommand
|
|
{
|
|
DefinitionId = 1
|
|
};
|
|
|
|
var mockImportList = new Mock<IImportList>();
|
|
|
|
Mocker.GetMock<ISeriesService>()
|
|
.Setup(v => v.AllSeriesTvdbIds())
|
|
.Returns(new List<int>());
|
|
|
|
Mocker.GetMock<ISeriesService>()
|
|
.Setup(v => v.GetAllSeries())
|
|
.Returns(_existingSeries);
|
|
|
|
Mocker.GetMock<ISearchForNewSeries>()
|
|
.Setup(v => v.SearchForNewSeries(It.IsAny<string>()))
|
|
.Returns(new List<Series>());
|
|
|
|
Mocker.GetMock<ISearchForNewSeries>()
|
|
.Setup(v => v.SearchForNewSeriesByImdbId(It.IsAny<string>()))
|
|
.Returns(new List<Series>());
|
|
|
|
Mocker.GetMock<IImportListFactory>()
|
|
.Setup(v => v.All())
|
|
.Returns(() => _importLists.Select(x => x.Definition as ImportListDefinition).ToList());
|
|
|
|
Mocker.GetMock<IImportListFactory>()
|
|
.Setup(v => v.GetAvailableProviders())
|
|
.Returns(_importLists);
|
|
|
|
Mocker.GetMock<IImportListFactory>()
|
|
.Setup(v => v.AutomaticAddEnabled(It.IsAny<bool>()))
|
|
.Returns(() => _importLists.Where(x => (x.Definition as ImportListDefinition).EnableAutomaticAdd).ToList());
|
|
|
|
Mocker.GetMock<IFetchAndParseImportList>()
|
|
.Setup(v => v.Fetch())
|
|
.Returns(_importListFetch);
|
|
|
|
Mocker.GetMock<IImportListExclusionService>()
|
|
.Setup(v => v.All())
|
|
.Returns(new List<ImportListExclusion>());
|
|
}
|
|
|
|
private void WithTvdbId()
|
|
{
|
|
_list1Series.First().TvdbId = 81189;
|
|
}
|
|
|
|
private void WithImdbId()
|
|
{
|
|
_list1Series.First().ImdbId = "tt0496424";
|
|
|
|
Mocker.GetMock<ISearchForNewSeries>()
|
|
.Setup(s => s.SearchForNewSeriesByImdbId(_list1Series.First().ImdbId))
|
|
.Returns(
|
|
Builder<Series>
|
|
.CreateListOfSize(1)
|
|
.All()
|
|
.With(s => s.Title = "Breaking Bad")
|
|
.With(s => s.TvdbId = 81189)
|
|
.Build()
|
|
.ToList());
|
|
}
|
|
|
|
private void WithExistingSeries()
|
|
{
|
|
Mocker.GetMock<ISeriesService>()
|
|
.Setup(v => v.AllSeriesTvdbIds())
|
|
.Returns(new List<int> { _list1Series.First().TvdbId });
|
|
}
|
|
|
|
private void WithExcludedSeries()
|
|
{
|
|
Mocker.GetMock<IImportListExclusionService>()
|
|
.Setup(v => v.All())
|
|
.Returns(new List<ImportListExclusion>
|
|
{
|
|
new ImportListExclusion
|
|
{
|
|
TvdbId = _list1Series.First().TvdbId
|
|
}
|
|
});
|
|
}
|
|
|
|
private void WithMonitorType(MonitorTypes monitor)
|
|
{
|
|
_importLists.ForEach(li => (li.Definition as ImportListDefinition).ShouldMonitor = monitor);
|
|
}
|
|
|
|
private void WithCleanLevel(ListSyncLevelType cleanLevel, int? tagId = null)
|
|
{
|
|
Mocker.GetMock<IConfigService>()
|
|
.SetupGet(v => v.ListSyncLevel)
|
|
.Returns(cleanLevel);
|
|
if (tagId.HasValue)
|
|
{
|
|
Mocker.GetMock<IConfigService>()
|
|
.SetupGet(v => v.ListSyncTag)
|
|
.Returns(tagId.Value);
|
|
}
|
|
}
|
|
|
|
private void WithList(int id, bool enabledAuto, int lastSyncHoursOffset = 0, bool pendingRemovals = true, DateTime? disabledTill = null)
|
|
{
|
|
var importListDefinition = new ImportListDefinition { Id = id, EnableAutomaticAdd = enabledAuto };
|
|
|
|
Mocker.GetMock<IImportListFactory>()
|
|
.Setup(v => v.Get(id))
|
|
.Returns(importListDefinition);
|
|
|
|
var mockImportList = new Mock<IImportList>();
|
|
mockImportList.SetupGet(s => s.Definition).Returns(importListDefinition);
|
|
mockImportList.SetupGet(s => s.MinRefreshInterval).Returns(TimeSpan.FromHours(12));
|
|
|
|
var status = new ImportListStatus()
|
|
{
|
|
LastInfoSync = DateTime.UtcNow.AddHours(lastSyncHoursOffset),
|
|
HasRemovedItemSinceLastClean = pendingRemovals,
|
|
DisabledTill = disabledTill
|
|
};
|
|
|
|
if (disabledTill.HasValue)
|
|
{
|
|
_importListFetch.AnyFailure = true;
|
|
}
|
|
|
|
Mocker.GetMock<IImportListStatusService>()
|
|
.Setup(v => v.GetListStatus(id))
|
|
.Returns(status);
|
|
|
|
_importLists.Add(mockImportList.Object);
|
|
}
|
|
|
|
private void VerifyDidAddTag(int expectedSeriesCount, int expectedTagId)
|
|
{
|
|
Mocker.GetMock<ISeriesService>()
|
|
.Verify(v => v.UpdateSeries(It.Is<List<Series>>(x => x.Count == expectedSeriesCount && x.All(series => series.Tags.Contains(expectedTagId))), true), Times.Once());
|
|
}
|
|
|
|
[Test]
|
|
public void should_not_clean_library_if_lists_have_not_removed_any_items()
|
|
{
|
|
_importListFetch.Series = _existingSeries.Select(x => new ImportListItemInfo() { TvdbId = x.TvdbId }).ToList();
|
|
_importListFetch.Series.ForEach(m => m.ImportListId = 1);
|
|
WithList(1, true, pendingRemovals: false);
|
|
WithCleanLevel(ListSyncLevelType.KeepAndUnmonitor);
|
|
|
|
Subject.Execute(_commandAll);
|
|
|
|
Mocker.GetMock<ISeriesService>()
|
|
.Verify(v => v.GetAllSeries(), Times.Never());
|
|
|
|
Mocker.GetMock<ISeriesService>()
|
|
.Verify(v => v.UpdateSeries(It.IsAny<List<Series>>(), true), Times.Never());
|
|
}
|
|
|
|
[Test]
|
|
public void should_not_clean_library_if_config_value_disable()
|
|
{
|
|
_importListFetch.Series.ForEach(m => m.ImportListId = 1);
|
|
WithList(1, true);
|
|
WithCleanLevel(ListSyncLevelType.Disabled);
|
|
|
|
Subject.Execute(_commandAll);
|
|
|
|
Mocker.GetMock<ISeriesService>()
|
|
.Verify(v => v.GetAllSeries(), Times.Never());
|
|
|
|
Mocker.GetMock<ISeriesService>()
|
|
.Verify(v => v.UpdateSeries(new List<Series>(), true), Times.Never());
|
|
}
|
|
|
|
[Test]
|
|
public void should_log_only_on_clean_library_if_config_value_logonly()
|
|
{
|
|
_importListFetch.Series.ForEach(m => m.ImportListId = 1);
|
|
WithList(1, true);
|
|
WithCleanLevel(ListSyncLevelType.LogOnly);
|
|
|
|
Subject.Execute(_commandAll);
|
|
|
|
Mocker.GetMock<ISeriesService>()
|
|
.Verify(v => v.GetAllSeries(), Times.Once());
|
|
|
|
Mocker.GetMock<ISeriesService>()
|
|
.Verify(v => v.DeleteSeries(It.IsAny<List<int>>(), It.IsAny<bool>(), It.IsAny<bool>()), Times.Never());
|
|
|
|
Mocker.GetMock<ISeriesService>()
|
|
.Verify(v => v.UpdateSeries(new List<Series>(), true), Times.Once());
|
|
}
|
|
|
|
[Test]
|
|
public void should_unmonitor_on_clean_library_if_config_value_keepAndUnmonitor()
|
|
{
|
|
_importListFetch.Series.ForEach(m => m.ImportListId = 1);
|
|
WithList(1, true);
|
|
WithCleanLevel(ListSyncLevelType.KeepAndUnmonitor);
|
|
var monitored = _existingSeries.Count(x => x.Monitored);
|
|
|
|
Subject.Execute(_commandAll);
|
|
|
|
Mocker.GetMock<ISeriesService>()
|
|
.Verify(v => v.GetAllSeries(), Times.Once());
|
|
|
|
Mocker.GetMock<ISeriesService>()
|
|
.Verify(v => v.DeleteSeries(It.IsAny<List<int>>(), It.IsAny<bool>(), It.IsAny<bool>()), Times.Never());
|
|
|
|
Mocker.GetMock<ISeriesService>()
|
|
.Verify(v => v.UpdateSeries(It.Is<List<Series>>(s => s.Count == monitored && s.All(m => !m.Monitored)), true), Times.Once());
|
|
}
|
|
|
|
[Test]
|
|
public void should_not_clean_on_clean_library_if_tvdb_match()
|
|
{
|
|
WithList(1, true);
|
|
WithCleanLevel(ListSyncLevelType.KeepAndUnmonitor);
|
|
_importListFetch.Series.ForEach(m => m.ImportListId = 1);
|
|
|
|
Mocker.GetMock<IImportListItemService>()
|
|
.Setup(v => v.Exists(6, It.IsAny<string>()))
|
|
.Returns(true);
|
|
|
|
Subject.Execute(_commandAll);
|
|
|
|
Mocker.GetMock<ISeriesService>()
|
|
.Verify(v => v.UpdateSeries(It.Is<List<Series>>(s => s.Count > 0 && s.All(m => !m.Monitored)), true), Times.Once());
|
|
}
|
|
|
|
[Test]
|
|
public void should_not_clean_on_clean_library_if_imdb_match()
|
|
{
|
|
WithList(1, true);
|
|
WithCleanLevel(ListSyncLevelType.KeepAndUnmonitor);
|
|
_importListFetch.Series.ForEach(m => m.ImportListId = 1);
|
|
|
|
var x = _importLists;
|
|
|
|
Mocker.GetMock<IImportListItemService>()
|
|
.Setup(v => v.Exists(It.IsAny<int>(), "6"))
|
|
.Returns(true);
|
|
|
|
Subject.Execute(_commandAll);
|
|
|
|
Mocker.GetMock<ISeriesService>()
|
|
.Verify(v => v.UpdateSeries(It.Is<List<Series>>(s => s.Count > 0 && s.All(m => !m.Monitored)), true), Times.Once());
|
|
}
|
|
|
|
[Test]
|
|
public void should_tag_series_on_clean_library_if_config_value_keepAndTag()
|
|
{
|
|
_importListFetch.Series.ForEach(m => m.ImportListId = 1);
|
|
WithList(1, true);
|
|
WithCleanLevel(ListSyncLevelType.KeepAndTag, 1);
|
|
|
|
Subject.Execute(_commandAll);
|
|
|
|
Mocker.GetMock<ISeriesService>()
|
|
.Verify(v => v.GetAllSeries(), Times.Once());
|
|
|
|
VerifyDidAddTag(_existingSeries.Count, 1);
|
|
}
|
|
|
|
[Test]
|
|
public void should_not_clean_if_list_failures()
|
|
{
|
|
_importListFetch.Series.ForEach(m => m.ImportListId = 1);
|
|
WithList(1, true, disabledTill: DateTime.UtcNow.AddHours(1));
|
|
WithCleanLevel(ListSyncLevelType.LogOnly);
|
|
|
|
Subject.Execute(_commandAll);
|
|
|
|
Mocker.GetMock<ISeriesService>()
|
|
.Verify(v => v.GetAllSeries(), Times.Never());
|
|
|
|
Mocker.GetMock<ISeriesService>()
|
|
.Verify(v => v.UpdateSeries(It.IsAny<List<Series>>(), It.IsAny<bool>()), Times.Never());
|
|
Mocker.GetMock<ISeriesService>()
|
|
.Verify(v => v.DeleteSeries(It.IsAny<List<int>>(), It.IsAny<bool>(), It.IsAny<bool>()), Times.Never());
|
|
}
|
|
|
|
[Test]
|
|
public void should_add_new_series_from_single_list_to_library()
|
|
{
|
|
_importListFetch.Series.ForEach(m => m.ImportListId = 1);
|
|
WithTvdbId();
|
|
WithList(1, true);
|
|
WithCleanLevel(ListSyncLevelType.Disabled);
|
|
|
|
Subject.Execute(_commandAll);
|
|
|
|
Mocker.GetMock<IAddSeriesService>()
|
|
.Verify(v => v.AddSeries(It.Is<List<Series>>(s => s.Count == 1), true), Times.Once());
|
|
}
|
|
|
|
[Test]
|
|
public void should_add_new_series_from_multiple_list_to_library()
|
|
{
|
|
_list2Series.ForEach(m => m.ImportListId = 2);
|
|
_importListFetch.Series.ForEach(m => m.ImportListId = 1);
|
|
_importListFetch.Series.AddRange(_list2Series);
|
|
|
|
WithTvdbId();
|
|
WithList(1, true);
|
|
WithList(2, true);
|
|
|
|
WithCleanLevel(ListSyncLevelType.Disabled);
|
|
|
|
Subject.Execute(_commandAll);
|
|
|
|
Mocker.GetMock<IAddSeriesService>()
|
|
.Verify(v => v.AddSeries(It.Is<List<Series>>(s => s.Count == 4), true), Times.Once());
|
|
}
|
|
|
|
[Test]
|
|
public void should_add_new_series_to_library_only_from_enabled_lists()
|
|
{
|
|
_list2Series.ForEach(m => m.ImportListId = 2);
|
|
_importListFetch.Series.ForEach(m => m.ImportListId = 1);
|
|
_importListFetch.Series.AddRange(_list2Series);
|
|
|
|
WithTvdbId();
|
|
WithList(1, true);
|
|
WithList(2, false);
|
|
|
|
WithCleanLevel(ListSyncLevelType.Disabled);
|
|
|
|
Subject.Execute(_commandAll);
|
|
|
|
Mocker.GetMock<IAddSeriesService>()
|
|
.Verify(v => v.AddSeries(It.Is<List<Series>>(s => s.Count == 1), true), Times.Once());
|
|
}
|
|
|
|
[Test]
|
|
public void should_not_add_duplicate_series_from_seperate_lists()
|
|
{
|
|
_list2Series.ForEach(m => m.ImportListId = 2);
|
|
_importListFetch.Series.ForEach(m => m.ImportListId = 1);
|
|
_importListFetch.Series.AddRange(_list2Series);
|
|
_importListFetch.Series[0].TvdbId = 6;
|
|
|
|
WithList(1, true);
|
|
WithList(2, true);
|
|
|
|
WithCleanLevel(ListSyncLevelType.Disabled);
|
|
|
|
Subject.Execute(_commandAll);
|
|
|
|
Mocker.GetMock<IAddSeriesService>()
|
|
.Verify(v => v.AddSeries(It.Is<List<Series>>(s => s.Count == 3), true), Times.Once());
|
|
}
|
|
|
|
[Test]
|
|
public void should_not_search_if_series_title_and_series_id()
|
|
{
|
|
_importListFetch.Series.ForEach(m => m.ImportListId = 1);
|
|
WithList(1, true);
|
|
WithTvdbId();
|
|
Subject.Execute(_commandAll);
|
|
|
|
Mocker.GetMock<ISearchForNewSeries>()
|
|
.Verify(v => v.SearchForNewSeries(It.IsAny<string>()), Times.Never());
|
|
}
|
|
|
|
[Test]
|
|
public void should_search_by_imdb_if_series_title_and_series_imdb()
|
|
{
|
|
_importListFetch.Series.ForEach(m => m.ImportListId = 1);
|
|
|
|
WithList(1, true);
|
|
WithImdbId();
|
|
|
|
Subject.Execute(_commandAll);
|
|
|
|
Mocker.GetMock<ISearchForNewSeries>()
|
|
.Verify(v => v.SearchForNewSeriesByImdbId(It.IsAny<string>()), Times.Once());
|
|
|
|
Mocker.GetMock<IAddSeriesService>()
|
|
.Verify(v => v.AddSeries(It.Is<List<Series>>(t => t.Count == 1), It.IsAny<bool>()));
|
|
}
|
|
|
|
[Test]
|
|
public void should_not_add_if_existing_series()
|
|
{
|
|
_importListFetch.Series.ForEach(m => m.ImportListId = 1);
|
|
WithList(1, true);
|
|
WithTvdbId();
|
|
WithExistingSeries();
|
|
|
|
Subject.Execute(_commandAll);
|
|
|
|
Mocker.GetMock<IAddSeriesService>()
|
|
.Verify(v => v.AddSeries(It.Is<List<Series>>(t => t.Count == 0), It.IsAny<bool>()));
|
|
}
|
|
|
|
[TestCase(MonitorTypes.None, false)]
|
|
[TestCase(MonitorTypes.All, true)]
|
|
public void should_add_if_not_existing_series(MonitorTypes monitor, bool expectedSeriesMonitored)
|
|
{
|
|
_importListFetch.Series.ForEach(m => m.ImportListId = 1);
|
|
WithList(1, true);
|
|
WithTvdbId();
|
|
WithMonitorType(monitor);
|
|
|
|
Subject.Execute(_commandAll);
|
|
|
|
Mocker.GetMock<IAddSeriesService>()
|
|
.Verify(v => v.AddSeries(It.Is<List<Series>>(t => t.Count == 1 && t.First().Monitored == expectedSeriesMonitored), It.IsAny<bool>()));
|
|
}
|
|
|
|
[Test]
|
|
public void should_not_add_if_excluded_series()
|
|
{
|
|
_importListFetch.Series.ForEach(m => m.ImportListId = 1);
|
|
WithList(1, true);
|
|
WithTvdbId();
|
|
WithExcludedSeries();
|
|
|
|
Subject.Execute(_commandAll);
|
|
|
|
Mocker.GetMock<IAddSeriesService>()
|
|
.Verify(v => v.AddSeries(It.Is<List<Series>>(t => t.Count == 0), It.IsAny<bool>()));
|
|
}
|
|
|
|
[Test]
|
|
public void should_not_fetch_if_no_lists_are_enabled()
|
|
{
|
|
Mocker.GetMock<IImportListFactory>()
|
|
.Setup(v => v.AutomaticAddEnabled(It.IsAny<bool>()))
|
|
.Returns(new List<IImportList>());
|
|
|
|
Subject.Execute(new ImportListSyncCommand());
|
|
|
|
Mocker.GetMock<IFetchAndParseImportList>()
|
|
.Verify(v => v.Fetch(), Times.Never);
|
|
}
|
|
|
|
[Test]
|
|
public void should_not_process_if_no_items_are_returned()
|
|
{
|
|
Mocker.GetMock<IFetchAndParseImportList>()
|
|
.Setup(v => v.Fetch())
|
|
.Returns(new ImportListFetchResult());
|
|
|
|
Subject.Execute(new ImportListSyncCommand());
|
|
|
|
Mocker.GetMock<IImportListExclusionService>()
|
|
.Verify(v => v.All(), Times.Never);
|
|
}
|
|
|
|
[Test]
|
|
public void should_not_add_if_tvdbid_is_0()
|
|
{
|
|
_importListFetch.Series.ForEach(m => m.ImportListId = 1);
|
|
WithList(1, true);
|
|
WithExcludedSeries();
|
|
|
|
Subject.Execute(_commandAll);
|
|
|
|
Mocker.GetMock<IAddSeriesService>()
|
|
.Verify(v => v.AddSeries(It.Is<List<Series>>(t => t.Count == 0), It.IsAny<bool>()));
|
|
}
|
|
}
|
|
}
|