Implement Release Parsing, Decision Engine, and Downloading (#35)

* Implement Parsing, Decision Engine, and Downloading
pull/38/head
Qstick 7 years ago committed by GitHub
parent 5556989324
commit 1e4d9480e9

@ -18,6 +18,7 @@ namespace NzbDrone.Api.Albums
public bool Monitored { get; set; }
public string Path { get; set; }
public int ProfileId { get; set; }
public int Duration { get; set; }
public Ratings Ratings { get; set; }
public DateTime? ReleaseDate { get; set; }
public List<string> Genres { get; set; }
@ -46,8 +47,7 @@ namespace NzbDrone.Api.Albums
Title = model.Title,
Images = model.Images,
Ratings = model.Ratings,
//Genres = model.Genres,
//ArtworkUrl = model.ArtworkUrl
Duration = model.Duration,
};
}
@ -68,8 +68,6 @@ namespace NzbDrone.Api.Albums
Title = resource.Title,
Images = resource.Images,
Ratings = resource.Ratings,
//Genres = resource.Genres,
//ArtworkUrl = resource.ArtworkUrl
};
}

@ -1,8 +1,10 @@
using System;
using Nancy;
using NzbDrone.Api.Episodes;
using NzbDrone.Api.Albums;
using NzbDrone.Api.Extensions;
using NzbDrone.Api.Series;
using NzbDrone.Api.Music;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.DecisionEngine;
using NzbDrone.Core.Download;
@ -32,12 +34,12 @@ namespace NzbDrone.Api.History
{
var resource = model.ToResource();
resource.Series = model.Series.ToResource();
resource.Episode = model.Episode.ToResource();
resource.Artist = model.Artist.ToResource();
resource.Album = model.Album.ToResource();
if (model.Series != null)
if (model.Artist != null)
{
resource.QualityCutoffNotMet = _qualityUpgradableSpecification.CutoffNotMet(model.Series.Profile.Value, model.Quality);
resource.QualityCutoffNotMet = _qualityUpgradableSpecification.CutoffNotMet(model.Artist.Profile.Value, model.Quality);
}
return resource;
@ -45,7 +47,7 @@ namespace NzbDrone.Api.History
private PagingResource<HistoryResource> GetHistory(PagingResource<HistoryResource> pagingResource)
{
var episodeId = Request.Query.EpisodeId;
var albumId = Request.Query.AlbumId;
var pagingSpec = pagingResource.MapToPagingSpec<HistoryResource, Core.History.History>("date", SortDirection.Descending);
@ -55,10 +57,10 @@ namespace NzbDrone.Api.History
pagingSpec.FilterExpression = v => v.EventType == filterValue;
}
if (episodeId.HasValue)
if (albumId.HasValue)
{
int i = (int)episodeId;
pagingSpec.FilterExpression = h => h.EpisodeId == i;
int i = (int)albumId;
pagingSpec.FilterExpression = h => h.AlbumId == i;
}
return ApplyToPage(_historyService.Paged, pagingSpec, MapToResource);

@ -1,8 +1,10 @@
using System;
using System.Collections.Generic;
using NzbDrone.Api.Episodes;
using NzbDrone.Api.Albums;
using NzbDrone.Api.REST;
using NzbDrone.Api.Series;
using NzbDrone.Api.Music;
using NzbDrone.Core.History;
using NzbDrone.Core.Qualities;
@ -11,8 +13,8 @@ namespace NzbDrone.Api.History
{
public class HistoryResource : RestResource
{
public int EpisodeId { get; set; }
public int SeriesId { get; set; }
public int ArtistId { get; set; }
public int AlbumId { get; set; }
public string SourceTitle { get; set; }
public QualityModel Quality { get; set; }
public bool QualityCutoffNotMet { get; set; }
@ -23,8 +25,8 @@ namespace NzbDrone.Api.History
public Dictionary<string, string> Data { get; set; }
public EpisodeResource Episode { get; set; }
public SeriesResource Series { get; set; }
public AlbumResource Album { get; set; }
public ArtistResource Artist { get; set; }
}
public static class HistoryResourceMapper
@ -37,8 +39,8 @@ namespace NzbDrone.Api.History
{
Id = model.Id,
EpisodeId = model.EpisodeId,
SeriesId = model.SeriesId,
AlbumId = model.AlbumId,
ArtistId = model.ArtistId,
SourceTitle = model.SourceTitle,
Quality = model.Quality,
//QualityCutoffNotMet

@ -25,7 +25,7 @@ namespace NzbDrone.Api.Indexers
private readonly IDownloadService _downloadService;
private readonly Logger _logger;
private readonly ICached<RemoteEpisode> _remoteEpisodeCache;
private readonly ICached<RemoteAlbum> _remoteAlbumCache;
public ReleaseModule(IFetchAndParseRss rssFetcherAndParser,
ISearchForNzb nzbSearchService,
@ -48,14 +48,14 @@ namespace NzbDrone.Api.Indexers
PostValidator.RuleFor(s => s.DownloadAllowed).Equal(true);
PostValidator.RuleFor(s => s.Guid).NotEmpty();
_remoteEpisodeCache = cacheManager.GetCache<RemoteEpisode>(GetType(), "remoteEpisodes");
_remoteAlbumCache = cacheManager.GetCache<RemoteAlbum>(GetType(), "remoteAlbums");
}
private Response DownloadRelease(ReleaseResource release)
{
var remoteEpisode = _remoteEpisodeCache.Find(release.Guid);
var remoteAlbum = _remoteAlbumCache.Find(release.Guid);
if (remoteEpisode == null)
if (remoteAlbum == null)
{
_logger.Debug("Couldn't find requested release in cache, cache timeout probably expired.");
@ -64,7 +64,7 @@ namespace NzbDrone.Api.Indexers
try
{
_downloadService.DownloadReport(remoteEpisode);
_downloadService.DownloadReport(remoteAlbum);
}
catch (ReleaseDownloadException ex)
{
@ -113,7 +113,7 @@ namespace NzbDrone.Api.Indexers
protected override ReleaseResource MapDecision(DownloadDecision decision, int initialWeight)
{
_remoteEpisodeCache.Set(decision.RemoteEpisode.Release.Guid, decision.RemoteEpisode, TimeSpan.FromMinutes(30));
_remoteAlbumCache.Set(decision.RemoteAlbum.Release.Guid, decision.RemoteAlbum, TimeSpan.FromMinutes(30));
return base.MapDecision(decision, initialWeight);
}
}

@ -25,9 +25,9 @@ namespace NzbDrone.Api.Indexers
release.ReleaseWeight = initialWeight;
if (decision.RemoteEpisode.Series != null)
if (decision.RemoteAlbum.Artist != null)
{
release.QualityWeight = decision.RemoteEpisode.Series
release.QualityWeight = decision.RemoteAlbum.Artist
.Profile.Value
.Items.FindIndex(v => v.Quality == release.Quality.Quality) * 100;
}

@ -25,18 +25,13 @@ namespace NzbDrone.Api.Indexers
public string ReleaseGroup { get; set; }
public string ReleaseHash { get; set; }
public string Title { get; set; }
public bool FullSeason { get; set; }
public int SeasonNumber { get; set; }
public Language Language { get; set; }
public string AirDate { get; set; }
public string SeriesTitle { get; set; }
public int[] EpisodeNumbers { get; set; }
public int[] AbsoluteEpisodeNumbers { get; set; }
public string ReleaseDate { get; set; }
public string ArtistName { get; set; }
public string AlbumTitle { get; set; }
public bool Approved { get; set; }
public bool TemporarilyRejected { get; set; }
public bool Rejected { get; set; }
public int TvdbId { get; set; }
public int TvRageId { get; set; }
public IEnumerable<string> Rejections { get; set; }
public DateTime PublishDate { get; set; }
public string CommentUrl { get; set; }
@ -82,16 +77,16 @@ namespace NzbDrone.Api.Indexers
{
public static ReleaseResource ToResource(this DownloadDecision model)
{
var releaseInfo = model.RemoteEpisode.Release;
var parsedEpisodeInfo = model.RemoteEpisode.ParsedEpisodeInfo;
var remoteEpisode = model.RemoteEpisode;
var torrentInfo = (model.RemoteEpisode.Release as TorrentInfo) ?? new TorrentInfo();
var releaseInfo = model.RemoteAlbum.Release;
var parsedAlbumInfo = model.RemoteAlbum.ParsedAlbumInfo;
var remoteAlbum = model.RemoteAlbum;
var torrentInfo = (model.RemoteAlbum.Release as TorrentInfo) ?? new TorrentInfo();
// TODO: Clean this mess up. don't mix data from multiple classes, use sub-resources instead? (Got a huge Deja Vu, didn't we talk about this already once?)
return new ReleaseResource
{
Guid = releaseInfo.Guid,
Quality = parsedEpisodeInfo.Quality,
Quality = parsedAlbumInfo.Quality,
//QualityWeight
Age = releaseInfo.Age,
AgeHours = releaseInfo.AgeHours,
@ -99,27 +94,22 @@ namespace NzbDrone.Api.Indexers
Size = releaseInfo.Size,
IndexerId = releaseInfo.IndexerId,
Indexer = releaseInfo.Indexer,
ReleaseGroup = parsedEpisodeInfo.ReleaseGroup,
ReleaseHash = parsedEpisodeInfo.ReleaseHash,
ReleaseGroup = parsedAlbumInfo.ReleaseGroup,
ReleaseHash = parsedAlbumInfo.ReleaseHash,
Title = releaseInfo.Title,
FullSeason = parsedEpisodeInfo.FullSeason,
SeasonNumber = parsedEpisodeInfo.SeasonNumber,
Language = parsedEpisodeInfo.Language,
AirDate = parsedEpisodeInfo.AirDate,
SeriesTitle = parsedEpisodeInfo.SeriesTitle,
EpisodeNumbers = parsedEpisodeInfo.EpisodeNumbers,
AbsoluteEpisodeNumbers = parsedEpisodeInfo.AbsoluteEpisodeNumbers,
Language = parsedAlbumInfo.Language,
ReleaseDate = parsedAlbumInfo.ReleaseDate,
ArtistName = parsedAlbumInfo.ArtistName,
AlbumTitle = parsedAlbumInfo.AlbumTitle,
Approved = model.Approved,
TemporarilyRejected = model.TemporarilyRejected,
Rejected = model.Rejected,
TvdbId = releaseInfo.TvdbId,
TvRageId = releaseInfo.TvRageId,
Rejections = model.Rejections.Select(r => r.Reason).ToList(),
PublishDate = releaseInfo.PublishDate,
CommentUrl = releaseInfo.CommentUrl,
DownloadUrl = releaseInfo.DownloadUrl,
InfoUrl = releaseInfo.InfoUrl,
DownloadAllowed = remoteEpisode.DownloadAllowed,
DownloadAllowed = remoteAlbum.DownloadAllowed,
//ReleaseWeight
MagnetUrl = torrentInfo.MagnetUrl,
@ -127,11 +117,6 @@ namespace NzbDrone.Api.Indexers
Seeders = torrentInfo.Seeders,
Leechers = (torrentInfo.Peers.HasValue && torrentInfo.Seeders.HasValue) ? (torrentInfo.Peers.Value - torrentInfo.Seeders.Value) : (int?)null,
Protocol = releaseInfo.DownloadProtocol,
IsDaily = parsedEpisodeInfo.IsDaily,
IsAbsoluteNumbering = parsedEpisodeInfo.IsAbsoluteNumbering,
IsPossibleSpecialEpisode = parsedEpisodeInfo.IsPossibleSpecialEpisode,
Special = parsedEpisodeInfo.Special,
};
}
@ -164,8 +149,6 @@ namespace NzbDrone.Api.Indexers
model.IndexerId = resource.IndexerId;
model.Indexer = resource.Indexer;
model.DownloadProtocol = resource.DownloadProtocol;
model.TvdbId = resource.TvdbId;
model.TvRageId = resource.TvRageId;
model.PublishDate = resource.PublishDate;
return model;

@ -53,6 +53,7 @@ namespace NzbDrone.Api.Music
//public string Certification { get; set; }
public List<string> Genres { get; set; }
public string CleanName { get; set; }
public string SortName { get; set; }
public HashSet<int> Tags { get; set; }
public DateTime Added { get; set; }
public AddArtistOptions AddOptions { get; set; }
@ -75,8 +76,9 @@ namespace NzbDrone.Api.Music
AllMusicId = model.AMId,
Name = model.Name,
CleanName = model.CleanName,
//AlternateTitles
//SortTitle = resource.SortTitle,
SortName = model.SortName,
//TotalTrackCount
//TrackCount
@ -130,7 +132,7 @@ namespace NzbDrone.Api.Music
Name = resource.Name,
CleanName = resource.CleanName,
//AlternateTitles
//SortTitle = resource.SortTitle,
SortName = resource.SortName,
MBId = resource.MBId,
TADBId = resource.TADBId,
DiscogsId = resource.DiscogsId,

@ -1,5 +1,5 @@
using NzbDrone.Api.Episodes;
using NzbDrone.Api.Series;
using NzbDrone.Api.Albums;
using NzbDrone.Api.Music;
using NzbDrone.Core.Parser;
namespace NzbDrone.Api.Parse
@ -18,23 +18,23 @@ namespace NzbDrone.Api.Parse
private ParseResource Parse()
{
var title = Request.Query.Title.Value as string;
var parsedEpisodeInfo = Parser.ParseTitle(title);
var parsedAlbumInfo = Parser.ParseAlbumTitle(title);
if (parsedEpisodeInfo == null)
if (parsedAlbumInfo == null)
{
return null;
}
var remoteEpisode = _parsingService.Map(parsedEpisodeInfo, 0, 0);
var remoteAlbum = _parsingService.Map(parsedAlbumInfo);
if (remoteEpisode != null)
if (remoteAlbum != null)
{
return new ParseResource
{
Title = title,
ParsedEpisodeInfo = remoteEpisode.ParsedEpisodeInfo,
Series = remoteEpisode.Series.ToResource(),
Episodes = remoteEpisode.Episodes.ToResource()
ParsedAlbumInfo = remoteAlbum.ParsedAlbumInfo,
Artist = remoteAlbum.Artist.ToResource(),
Albums = remoteAlbum.Albums.ToResource()
};
}
else
@ -42,7 +42,7 @@ namespace NzbDrone.Api.Parse
return new ParseResource
{
Title = title,
ParsedEpisodeInfo = parsedEpisodeInfo
ParsedAlbumInfo = parsedAlbumInfo
};
}
}

@ -1,7 +1,7 @@
using System.Collections.Generic;
using NzbDrone.Api.Episodes;
using NzbDrone.Api.REST;
using NzbDrone.Api.Series;
using NzbDrone.Api.Music;
using NzbDrone.Api.Albums;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Api.Parse
@ -9,8 +9,8 @@ namespace NzbDrone.Api.Parse
public class ParseResource : RestResource
{
public string Title { get; set; }
public ParsedEpisodeInfo ParsedEpisodeInfo { get; set; }
public SeriesResource Series { get; set; }
public List<EpisodeResource> Episodes { get; set; }
public ParsedAlbumInfo ParsedAlbumInfo { get; set; }
public ArtistResource Artist { get; set; }
public List<AlbumResource> Albums { get; set; }
}
}

@ -105,7 +105,7 @@ namespace NzbDrone.Api.Queue
throw new NotFoundException();
}
_downloadService.DownloadReport(pendingRelease.RemoteEpisode);
_downloadService.DownloadReport(pendingRelease.RemoteAlbum);
return resource.AsResponse();
}

@ -4,6 +4,8 @@ using NzbDrone.Api.REST;
using NzbDrone.Core.Qualities;
using NzbDrone.Api.Series;
using NzbDrone.Api.Episodes;
using NzbDrone.Api.Music;
using NzbDrone.Api.Albums;
using NzbDrone.Core.Download.TrackedDownloads;
using NzbDrone.Core.Indexers;
using System.Linq;
@ -12,8 +14,8 @@ namespace NzbDrone.Api.Queue
{
public class QueueResource : RestResource
{
public SeriesResource Series { get; set; }
public EpisodeResource Episode { get; set; }
public ArtistResource Artist { get; set; }
public AlbumResource Album { get; set; }
public QualityModel Quality { get; set; }
public decimal Size { get; set; }
public string Title { get; set; }
@ -37,8 +39,8 @@ namespace NzbDrone.Api.Queue
{
Id = model.Id,
Series = model.Series.ToResource(),
Episode = model.Episode.ToResource(),
Artist = model.Artist.ToResource(),
Album = model.Album.ToResource(),
Quality = model.Quality,
Size = model.Size,
Title = model.Title,

@ -17,18 +17,11 @@ namespace NzbDrone.Api.Tracks
public bool Explicit { get; set; }
public int TrackNumber { get; set; }
public string Title { get; set; }
//public string AirDate { get; set; }
//public DateTime? AirDateUtc { get; set; }
//public string Overview { get; set; }
public int Duration { get; set; }
public TrackFileResource TrackFile { get; set; }
public bool HasFile { get; set; }
public bool Monitored { get; set; }
//public int? AbsoluteEpisodeNumber { get; set; }
//public int? SceneAbsoluteEpisodeNumber { get; set; }
//public int? SceneEpisodeNumber { get; set; }
//public int? SceneSeasonNumber { get; set; }
//public bool UnverifiedSceneNumbering { get; set; }
//public string SeriesTitle { get; set; }
public ArtistResource Artist { get; set; }
public Ratings Ratings { get; set; }
@ -54,19 +47,12 @@ namespace NzbDrone.Api.Tracks
Explicit = model.Explicit,
TrackNumber = model.TrackNumber,
Title = model.Title,
//AirDate = model.AirDate,
//AirDateUtc = model.AirDateUtc,
//Overview = model.Overview,
Duration = model.Duration,
//EpisodeFile
HasFile = model.HasFile,
Monitored = model.Monitored,
Ratings = model.Ratings,
//AbsoluteEpisodeNumber = model.AbsoluteEpisodeNumber,
//SceneAbsoluteEpisodeNumber = model.SceneAbsoluteEpisodeNumber,
//SceneEpisodeNumber = model.SceneEpisodeNumber,
//SceneSeasonNumber = model.SceneSeasonNumber,
//UnverifiedSceneNumbering = model.UnverifiedSceneNumbering,
//SeriesTitle = model.SeriesTitle,
//Series = model.Series.MapToResource(),
};

@ -8,7 +8,7 @@ using NzbDrone.Core.DecisionEngine.Specifications;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Music;
namespace NzbDrone.Core.Test.DecisionEngineTests
{
@ -16,40 +16,40 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
public class AcceptableSizeSpecificationFixture : CoreTest<AcceptableSizeSpecification>
{
private RemoteEpisode parseResultMultiSet;
private RemoteEpisode parseResultMulti;
private RemoteEpisode parseResultSingle;
private Series series;
private RemoteAlbum parseResultMultiSet;
private RemoteAlbum parseResultMulti;
private RemoteAlbum parseResultSingle;
private Artist artist;
private QualityDefinition qualityType;
[SetUp]
public void Setup()
{
series = Builder<Series>.CreateNew()
artist = Builder<Artist>.CreateNew()
.Build();
parseResultMultiSet = new RemoteEpisode
parseResultMultiSet = new RemoteAlbum
{
Series = series,
Artist = artist,
Release = new ReleaseInfo(),
ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.MP3_192, new Revision(version: 2)) },
Episodes = new List<Episode> { new Episode(), new Episode(), new Episode(), new Episode(), new Episode(), new Episode() }
ParsedAlbumInfo = new ParsedAlbumInfo { Quality = new QualityModel(Quality.MP3_192, new Revision(version: 2)) },
Albums = new List<Album> { new Album(), new Album(), new Album(), new Album(), new Album(), new Album() }
};
parseResultMulti = new RemoteEpisode
parseResultMulti = new RemoteAlbum
{
Series = series,
Artist = artist,
Release = new ReleaseInfo(),
ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.MP3_192, new Revision(version: 2)) },
Episodes = new List<Episode> { new Episode(), new Episode() }
ParsedAlbumInfo = new ParsedAlbumInfo { Quality = new QualityModel(Quality.MP3_192, new Revision(version: 2)) },
Albums = new List<Album> { new Album(), new Album() }
};
parseResultSingle = new RemoteEpisode
parseResultSingle = new RemoteAlbum
{
Series = series,
Artist = artist,
Release = new ReleaseInfo(),
ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.MP3_192, new Revision(version: 2)) },
Episodes = new List<Episode> { new Episode() { Id = 2 } }
ParsedAlbumInfo = new ParsedAlbumInfo { Quality = new QualityModel(Quality.MP3_192, new Revision(version: 2)) },
Albums = new List<Album> { new Album { Id = 2 } }
};
@ -59,83 +59,68 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
qualityType = Builder<QualityDefinition>.CreateNew()
.With(q => q.MinSize = 2)
.With(q => q.MaxSize = 10)
.With(q => q.MaxSize = 6)
.With(q => q.Quality = Quality.MP3_192)
.Build();
Mocker.GetMock<IQualityDefinitionService>().Setup(s => s.Get(Quality.MP3_192)).Returns(qualityType);
Mocker.GetMock<IEpisodeService>().Setup(
s => s.GetEpisodesBySeason(It.IsAny<int>(), It.IsAny<int>()))
.Returns(new List<Episode>() {
new Episode(), new Episode(), new Episode(), new Episode(), new Episode(),
new Episode(), new Episode(), new Episode(), new Episode() { Id = 2 }, new Episode() });
Mocker.GetMock<IAlbumService>().Setup(
s => s.GetAlbumsByArtist(It.IsAny<int>()))
.Returns(new List<Album>() {
new Album(), new Album(), new Album(), new Album(), new Album(),
new Album(), new Album(), new Album(), new Album { Id = 2 }, new Album() });
}
private void GivenLastEpisode()
private void GivenLastAlbum()
{
Mocker.GetMock<IEpisodeService>().Setup(
s => s.GetEpisodesBySeason(It.IsAny<int>(), It.IsAny<int>()))
.Returns(new List<Episode>() {
new Episode(), new Episode(), new Episode(), new Episode(), new Episode(),
new Episode(), new Episode(), new Episode(), new Episode(), new Episode() { Id = 2 } });
Mocker.GetMock<IAlbumService>().Setup(
s => s.GetAlbumsByArtist(It.IsAny<int>()))
.Returns(new List<Album> {
new Album(), new Album(), new Album(), new Album(), new Album(),
new Album(), new Album(), new Album(), new Album(), new Album { Id = 2 } });
}
[TestCase(30, 50, false)]
[TestCase(30, 250, true)]
[TestCase(30, 500, false)]
[TestCase(60, 100, false)]
[TestCase(60, 500, true)]
[TestCase(60, 1000, false)]
public void single_episode(int runtime, int sizeInMegaBytes, bool expectedResult)
[TestCase(1800000, 50, false)]
[TestCase(1800000, 150, true)]
[TestCase(1800000, 300, false)]
[TestCase(3600000, 100, false)]
[TestCase(3600000, 300, true)]
[TestCase(3600000, 600, false)]
public void single_album(int runtime, int sizeInMegaBytes, bool expectedResult)
{
series.Runtime = runtime;
parseResultSingle.Series = series;
parseResultSingle.Albums.Select(c => { c.Duration = runtime; return c; }).ToList();
parseResultSingle.Artist = artist;
parseResultSingle.Release.Size = sizeInMegaBytes.Megabytes();
Subject.IsSatisfiedBy(parseResultSingle, null).Accepted.Should().Be(expectedResult);
}
[TestCase(30, 500, true)]
[TestCase(30, 1000, false)]
[TestCase(60, 1000, true)]
[TestCase(60, 2000, false)]
public void single_episode_first_or_last(int runtime, int sizeInMegaBytes, bool expectedResult)
[TestCase(1800000, 50 * 2, false)]
[TestCase(1800000, 150 * 2, true)]
[TestCase(1800000, 300 * 2, false)]
[TestCase(3600000, 100 * 2, false)]
[TestCase(3600000, 300 * 2, true)]
[TestCase(3600000, 600 * 2, false)]
public void multi_album(int runtime, int sizeInMegaBytes, bool expectedResult)
{
GivenLastEpisode();
series.Runtime = runtime;
parseResultSingle.Series = series;
parseResultSingle.Release.Size = sizeInMegaBytes.Megabytes();
Subject.IsSatisfiedBy(parseResultSingle, null).Accepted.Should().Be(expectedResult);
}
[TestCase(30, 50 * 2, false)]
[TestCase(30, 250 * 2, true)]
[TestCase(30, 500 * 2, false)]
[TestCase(60, 100 * 2, false)]
[TestCase(60, 500 * 2, true)]
[TestCase(60, 1000 * 2, false)]
public void multi_episode(int runtime, int sizeInMegaBytes, bool expectedResult)
{
series.Runtime = runtime;
parseResultMulti.Series = series;
parseResultMulti.Albums.Select(c => { c.Duration = runtime; return c; }).ToList();
parseResultMulti.Artist = artist;
parseResultMulti.Release.Size = sizeInMegaBytes.Megabytes();
Subject.IsSatisfiedBy(parseResultMulti, null).Accepted.Should().Be(expectedResult);
}
[TestCase(30, 50 * 6, false)]
[TestCase(30, 250 * 6, true)]
[TestCase(30, 500 * 6, false)]
[TestCase(60, 100 * 6, false)]
[TestCase(60, 500 * 6, true)]
[TestCase(60, 1000 * 6, false)]
public void multiset_episode(int runtime, int sizeInMegaBytes, bool expectedResult)
[TestCase(1800000, 50 * 6, false)]
[TestCase(1800000, 150 * 6, true)]
[TestCase(1800000, 300 * 6, false)]
[TestCase(3600000, 100 * 6, false)]
[TestCase(3600000, 300 * 6, true)]
[TestCase(3600000, 600 * 6, false)]
public void multiset_album(int runtime, int sizeInMegaBytes, bool expectedResult)
{
series.Runtime = runtime;
parseResultMultiSet.Series = series;
parseResultMultiSet.Albums.Select(c => { c.Duration = runtime; return c; }).ToList();
parseResultMultiSet.Artist = artist;
parseResultMultiSet.Release.Size = sizeInMegaBytes.Megabytes();
Subject.IsSatisfiedBy(parseResultMultiSet, null).Accepted.Should().Be(expectedResult);
@ -144,10 +129,9 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
[Test]
public void should_return_true_if_size_is_zero()
{
GivenLastEpisode();
series.Runtime = 30;
parseResultSingle.Series = series;
GivenLastAlbum();
parseResultSingle.Albums.Select(c => { c.Duration = 1800000; return c; }).ToList();
parseResultSingle.Artist = artist;
parseResultSingle.Release.Size = 0;
qualityType.MinSize = 10;
qualityType.MaxSize = 20;
@ -158,10 +142,9 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
[Test]
public void should_return_true_if_unlimited_30_minute()
{
GivenLastEpisode();
series.Runtime = 30;
parseResultSingle.Series = series;
GivenLastAlbum();
parseResultSingle.Albums.Select(c => { c.Duration = 1800000; return c; }).ToList();
parseResultSingle.Artist = artist;
parseResultSingle.Release.Size = 18457280000;
qualityType.MaxSize = null;
@ -171,50 +154,14 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
[Test]
public void should_return_true_if_unlimited_60_minute()
{
GivenLastEpisode();
series.Runtime = 60;
parseResultSingle.Series = series;
GivenLastAlbum();
parseResultSingle.Albums.Select(c => { c.Duration = 3600000; return c; }).ToList();
parseResultSingle.Artist = artist;
parseResultSingle.Release.Size = 36857280000;
qualityType.MaxSize = null;
Subject.IsSatisfiedBy(parseResultSingle, null).Accepted.Should().BeTrue();
}
[Test]
public void should_treat_daily_series_as_single_episode()
{
GivenLastEpisode();
series.Runtime = 60;
parseResultSingle.Series = series;
parseResultSingle.Series.SeriesType = SeriesTypes.Daily;
parseResultSingle.Release.Size = 300.Megabytes();
qualityType.MaxSize = 10;
Subject.IsSatisfiedBy(parseResultSingle, null).Accepted.Should().BeTrue();
}
[Test]
public void should_return_true_if_RAWHD()
{
parseResultSingle.ParsedEpisodeInfo.Quality = new QualityModel(Quality.FLAC);
series.Runtime = 45;
parseResultSingle.Series = series;
parseResultSingle.Series.SeriesType = SeriesTypes.Daily;
parseResultSingle.Release.Size = 8000.Megabytes();
Subject.IsSatisfiedBy(parseResultSingle, null).Accepted.Should().BeTrue();
}
[Test]
public void should_return_true_for_special()
{
parseResultSingle.ParsedEpisodeInfo.Special = true;
Subject.IsSatisfiedBy(parseResultSingle, null).Accepted.Should().BeTrue();
}
}
}

@ -1,110 +0,0 @@
using System.Linq;
using FizzWare.NBuilder;
using FluentAssertions;
using Marr.Data;
using NUnit.Framework;
using NzbDrone.Core.DecisionEngine;
using NzbDrone.Core.DecisionEngine.Specifications;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.DecisionEngineTests
{
[TestFixture]
public class AnimeVersionUpgradeSpecificationFixture : CoreTest<AnimeVersionUpgradeSpecification>
{
private AnimeVersionUpgradeSpecification _subject;
private RemoteEpisode _remoteEpisode;
private EpisodeFile _episodeFile;
[SetUp]
public void Setup()
{
Mocker.Resolve<QualityUpgradableSpecification>();
_subject = Mocker.Resolve<AnimeVersionUpgradeSpecification>();
_episodeFile = new EpisodeFile
{
Quality = new QualityModel(Quality.MP3_256, new Revision()),
ReleaseGroup = "DRONE2"
};
_remoteEpisode = new RemoteEpisode();
_remoteEpisode.Series = new Series { SeriesType = SeriesTypes.Anime };
_remoteEpisode.ParsedEpisodeInfo = new ParsedEpisodeInfo
{
Quality = new QualityModel(Quality.MP3_256, new Revision(2)),
ReleaseGroup = "DRONE"
};
_remoteEpisode.Episodes = Builder<Episode>.CreateListOfSize(1)
.All()
.With(e => e.EpisodeFile = new LazyLoaded<EpisodeFile>(_episodeFile))
.Build()
.ToList();
}
private void GivenStandardSeries()
{
_remoteEpisode.Series.SeriesType = SeriesTypes.Standard;
}
private void GivenNoVersionUpgrade()
{
_remoteEpisode.ParsedEpisodeInfo.Quality.Revision = new Revision();
}
[Test]
public void should_be_true_when_no_existing_file()
{
_remoteEpisode.Episodes.First().EpisodeFileId = 0;
_subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
}
[Test]
public void should_be_true_if_series_is_not_anime()
{
GivenStandardSeries();
_subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
}
[Test]
public void should_be_true_if_is_not_a_version_upgrade_for_existing_file()
{
GivenNoVersionUpgrade();
_subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
}
[Test]
public void should_be_true_when_release_group_matches()
{
_episodeFile.ReleaseGroup = _remoteEpisode.ParsedEpisodeInfo.ReleaseGroup;
_subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
}
[Test]
public void should_be_false_when_existing_file_doesnt_have_a_release_group()
{
_episodeFile.ReleaseGroup = string.Empty;
_subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
}
[Test]
public void should_should_be_false_when_release_doesnt_have_a_release_group()
{
_remoteEpisode.ParsedEpisodeInfo.ReleaseGroup = string.Empty;
_subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
}
[Test]
public void should_be_false_when_release_group_does_not_match()
{
_subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
}
}
}

@ -11,28 +11,28 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
public class CutoffSpecificationFixture : CoreTest<QualityUpgradableSpecification>
{
[Test]
public void should_return_true_if_current_episode_is_less_than_cutoff()
public void should_return_true_if_current_album_is_less_than_cutoff()
{
Subject.CutoffNotMet(new Profile { Cutoff = Quality.MP3_512, Items = Qualities.QualityFixture.GetDefaultQualities() },
new QualityModel(Quality.MP3_192, new Revision(version: 2))).Should().BeTrue();
}
[Test]
public void should_return_false_if_current_episode_is_equal_to_cutoff()
public void should_return_false_if_current_album_is_equal_to_cutoff()
{
Subject.CutoffNotMet(new Profile { Cutoff = Quality.MP3_256, Items = Qualities.QualityFixture.GetDefaultQualities() },
new QualityModel(Quality.MP3_256, new Revision(version: 2))).Should().BeFalse();
}
[Test]
public void should_return_false_if_current_episode_is_greater_than_cutoff()
public void should_return_false_if_current_album_is_greater_than_cutoff()
{
Subject.CutoffNotMet(new Profile { Cutoff = Quality.MP3_256, Items = Qualities.QualityFixture.GetDefaultQualities() },
new QualityModel(Quality.MP3_512, new Revision(version: 2))).Should().BeFalse();
}
[Test]
public void should_return_true_when_new_episode_is_proper_but_existing_is_not()
public void should_return_true_when_new_album_is_proper_but_existing_is_not()
{
Subject.CutoffNotMet(new Profile { Cutoff = Quality.MP3_256, Items = Qualities.QualityFixture.GetDefaultQualities() },
new QualityModel(Quality.MP3_256, new Revision(version: 1)),

@ -8,7 +8,7 @@ using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Music;
using NzbDrone.Test.Common;
using FizzWare.NBuilder;
@ -18,7 +18,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
public class DownloadDecisionMakerFixture : CoreTest<DownloadDecisionMaker>
{
private List<ReleaseInfo> _reports;
private RemoteEpisode _remoteEpisode;
private RemoteAlbum _remoteAlbum;
private Mock<IDecisionEngineSpecification> _pass1;
private Mock<IDecisionEngineSpecification> _pass2;
@ -39,23 +39,23 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
_fail2 = new Mock<IDecisionEngineSpecification>();
_fail3 = new Mock<IDecisionEngineSpecification>();
_pass1.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>(), null)).Returns(Decision.Accept);
_pass2.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>(), null)).Returns(Decision.Accept);
_pass3.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>(), null)).Returns(Decision.Accept);
_pass1.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteAlbum>(), null)).Returns(Decision.Accept);
_pass2.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteAlbum>(), null)).Returns(Decision.Accept);
_pass3.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteAlbum>(), null)).Returns(Decision.Accept);
_fail1.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>(), null)).Returns(Decision.Reject("fail1"));
_fail2.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>(), null)).Returns(Decision.Reject("fail2"));
_fail3.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>(), null)).Returns(Decision.Reject("fail3"));
_fail1.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteAlbum>(), null)).Returns(Decision.Reject("fail1"));
_fail2.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteAlbum>(), null)).Returns(Decision.Reject("fail2"));
_fail3.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteAlbum>(), null)).Returns(Decision.Reject("fail3"));
_reports = new List<ReleaseInfo> { new ReleaseInfo { Title = "The.Office.S03E115.DVDRip.XviD-OSiTV" } };
_remoteEpisode = new RemoteEpisode {
Series = new Series(),
Episodes = new List<Episode> { new Episode() }
_reports = new List<ReleaseInfo> { new ReleaseInfo { Title = "Coldplay-A Head Full Of Dreams-CD-FLAC-2015-PERFECT" } };
_remoteAlbum = new RemoteAlbum {
Artist = new Artist(),
Albums = new List<Album> { new Album() }
};
Mocker.GetMock<IParsingService>()
.Setup(c => c.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<SearchCriteriaBase>()))
.Returns(_remoteEpisode);
.Setup(c => c.Map(It.IsAny<ParsedAlbumInfo>(), It.IsAny<SearchCriteriaBase>()))
.Returns(_remoteAlbum);
}
private void GivenSpecifications(params Mock<IDecisionEngineSpecification>[] mocks)
@ -70,12 +70,12 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
Subject.GetRssDecision(_reports).ToList();
_fail1.Verify(c => c.IsSatisfiedBy(_remoteEpisode, null), Times.Once());
_fail2.Verify(c => c.IsSatisfiedBy(_remoteEpisode, null), Times.Once());
_fail3.Verify(c => c.IsSatisfiedBy(_remoteEpisode, null), Times.Once());
_pass1.Verify(c => c.IsSatisfiedBy(_remoteEpisode, null), Times.Once());
_pass2.Verify(c => c.IsSatisfiedBy(_remoteEpisode, null), Times.Once());
_pass3.Verify(c => c.IsSatisfiedBy(_remoteEpisode, null), Times.Once());
_fail1.Verify(c => c.IsSatisfiedBy(_remoteAlbum, null), Times.Once());
_fail2.Verify(c => c.IsSatisfiedBy(_remoteAlbum, null), Times.Once());
_fail3.Verify(c => c.IsSatisfiedBy(_remoteAlbum, null), Times.Once());
_pass1.Verify(c => c.IsSatisfiedBy(_remoteAlbum, null), Times.Once());
_pass2.Verify(c => c.IsSatisfiedBy(_remoteAlbum, null), Times.Once());
_pass3.Verify(c => c.IsSatisfiedBy(_remoteAlbum, null), Times.Once());
}
[Test]
@ -118,51 +118,51 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
}
[Test]
public void should_not_attempt_to_map_episode_if_not_parsable()
public void should_not_attempt_to_map_album_if_not_parsable()
{
GivenSpecifications(_pass1, _pass2, _pass3);
_reports[0].Title = "Not parsable";
var results = Subject.GetRssDecision(_reports).ToList();
Mocker.GetMock<IParsingService>().Verify(c => c.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<SearchCriteriaBase>()), Times.Never());
Mocker.GetMock<IParsingService>().Verify(c => c.Map(It.IsAny<ParsedAlbumInfo>(), It.IsAny<SearchCriteriaBase>()), Times.Never());
_pass1.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>(), null), Times.Never());
_pass2.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>(), null), Times.Never());
_pass3.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>(), null), Times.Never());
_pass1.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteAlbum>(), null), Times.Never());
_pass2.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteAlbum>(), null), Times.Never());
_pass3.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteAlbum>(), null), Times.Never());
results.Should().BeEmpty();
}
[Test]
public void should_not_attempt_to_map_episode_series_title_is_blank()
public void should_not_attempt_to_map_album_artist_title_is_blank()
{
GivenSpecifications(_pass1, _pass2, _pass3);
_reports[0].Title = "1937 - Snow White and the Seven Dwarves";
_reports[0].Title = "2013 - Night Visions";
var results = Subject.GetRssDecision(_reports).ToList();
Mocker.GetMock<IParsingService>().Verify(c => c.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<SearchCriteriaBase>()), Times.Never());
Mocker.GetMock<IParsingService>().Verify(c => c.Map(It.IsAny<ParsedAlbumInfo>(), It.IsAny<SearchCriteriaBase>()), Times.Never());
_pass1.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>(), null), Times.Never());
_pass2.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>(), null), Times.Never());
_pass3.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>(), null), Times.Never());
_pass1.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteAlbum>(), null), Times.Never());
_pass2.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteAlbum>(), null), Times.Never());
_pass3.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteAlbum>(), null), Times.Never());
results.Should().BeEmpty();
}
[Test]
public void should_not_attempt_to_make_decision_if_series_is_unknown()
public void should_not_attempt_to_make_decision_if_artist_is_unknown()
{
GivenSpecifications(_pass1, _pass2, _pass3);
_remoteEpisode.Series = null;
_remoteAlbum.Artist = null;
Subject.GetRssDecision(_reports);
_pass1.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>(), null), Times.Never());
_pass2.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>(), null), Times.Never());
_pass3.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>(), null), Times.Never());
_pass1.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteAlbum>(), null), Times.Never());
_pass2.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteAlbum>(), null), Times.Never());
_pass3.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteAlbum>(), null), Times.Never());
}
[Test]
@ -170,29 +170,29 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
{
GivenSpecifications(_pass1);
Mocker.GetMock<IParsingService>().Setup(c => c.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<SearchCriteriaBase>()))
Mocker.GetMock<IParsingService>().Setup(c => c.Map(It.IsAny<ParsedAlbumInfo>(), It.IsAny<SearchCriteriaBase>()))
.Throws<TestException>();
_reports = new List<ReleaseInfo>
{
new ReleaseInfo{Title = "The.Office.S03E115.DVDRip.XviD-OSiTV"},
new ReleaseInfo{Title = "The.Office.S03E115.DVDRip.XviD-OSiTV"},
new ReleaseInfo{Title = "The.Office.S03E115.DVDRip.XviD-OSiTV"}
new ReleaseInfo{Title = "Coldplay-A Head Full Of Dreams-CD-FLAC-2015-PERFECT"},
new ReleaseInfo{Title = "Coldplay-A Head Full Of Dreams-CD-FLAC-2015-PERFECT"},
new ReleaseInfo{Title = "Coldplay-A Head Full Of Dreams-CD-FLAC-2015-PERFECT"}
};
Subject.GetRssDecision(_reports);
Mocker.GetMock<IParsingService>().Verify(c => c.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<SearchCriteriaBase>()), Times.Exactly(_reports.Count));
Mocker.GetMock<IParsingService>().Verify(c => c.Map(It.IsAny<ParsedAlbumInfo>(), It.IsAny<SearchCriteriaBase>()), Times.Exactly(_reports.Count));
ExceptionVerification.ExpectedErrors(3);
}
[Test]
public void should_return_unknown_series_rejection_if_series_is_unknown()
public void should_return_unknown_artist_rejection_if_artist_is_unknown()
{
GivenSpecifications(_pass1, _pass2, _pass3);
_remoteEpisode.Series = null;
_remoteAlbum.Artist = null;
var result = Subject.GetRssDecision(_reports);
@ -200,40 +200,38 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
}
[Test]
public void should_only_include_reports_for_requested_episodes()
public void should_only_include_reports_for_requested_albums()
{
var series = Builder<Series>.CreateNew().Build();
var artist = Builder<Artist>.CreateNew().Build();
var episodes = Builder<Episode>.CreateListOfSize(2)
var albums = Builder<Album>.CreateListOfSize(2)
.All()
.With(v => v.SeriesId, series.Id)
.With(v => v.Series, series)
.With(v => v.SeasonNumber, 1)
.With(v => v.SceneSeasonNumber, 2)
.With(v => v.ArtistId, artist.Id)
.With(v => v.Artist, artist)
.BuildList();
var criteria = new SeasonSearchCriteria { Episodes = episodes.Take(1).ToList(), SeasonNumber = 1 };
var criteria = new ArtistSearchCriteria { Albums = albums.Take(1).ToList()};
var reports = episodes.Select(v =>
var reports = albums.Select(v =>
new ReleaseInfo()
{
Title = string.Format("{0}.S{1:00}E{2:00}.720p.WEB-DL-DRONE", series.Title, v.SceneSeasonNumber, v.SceneEpisodeNumber)
Title = string.Format("{0}-{1}[FLAC][2017][DRONE]", artist.Name, v.Title)
}).ToList();
Mocker.GetMock<IParsingService>()
.Setup(v => v.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<SearchCriteriaBase>()))
.Returns<ParsedEpisodeInfo, int, int, SearchCriteriaBase>((p,tvdbid,tvrageid,c) =>
new RemoteEpisode
.Setup(v => v.Map(It.IsAny<ParsedAlbumInfo>(), It.IsAny<SearchCriteriaBase>()))
.Returns<ParsedAlbumInfo, SearchCriteriaBase>((p,c) =>
new RemoteAlbum
{
DownloadAllowed = true,
ParsedEpisodeInfo = p,
Series = series,
Episodes = episodes.Where(v => v.SceneEpisodeNumber == p.EpisodeNumbers.First()).ToList()
ParsedAlbumInfo = p,
Artist = artist,
Albums = albums.Where(v => v.Title == p.AlbumTitle).ToList()
});
Mocker.SetConstant<IEnumerable<IDecisionEngineSpecification>>(new List<IDecisionEngineSpecification>
{
Mocker.Resolve<NzbDrone.Core.DecisionEngine.Specifications.Search.EpisodeRequestedSpecification>()
Mocker.Resolve<NzbDrone.Core.DecisionEngine.Specifications.Search.AlbumRequestedSpecification>()
});
var decisions = Subject.GetSearchDecision(reports, criteria);
@ -244,31 +242,31 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
}
[Test]
public void should_not_allow_download_if_series_is_unknown()
public void should_not_allow_download_if_artist_is_unknown()
{
GivenSpecifications(_pass1, _pass2, _pass3);
_remoteEpisode.Series = null;
_remoteAlbum.Artist = null;
var result = Subject.GetRssDecision(_reports);
result.Should().HaveCount(1);
result.First().RemoteEpisode.DownloadAllowed.Should().BeFalse();
result.First().RemoteAlbum.DownloadAllowed.Should().BeFalse();
}
[Test]
public void should_not_allow_download_if_no_episodes_found()
public void should_not_allow_download_if_no_albums_found()
{
GivenSpecifications(_pass1, _pass2, _pass3);
_remoteEpisode.Episodes = new List<Episode>();
_remoteAlbum.Albums = new List<Album>();
var result = Subject.GetRssDecision(_reports);
result.Should().HaveCount(1);
result.First().RemoteEpisode.DownloadAllowed.Should().BeFalse();
result.First().RemoteAlbum.DownloadAllowed.Should().BeFalse();
}
[Test]
@ -276,7 +274,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
{
GivenSpecifications(_pass1);
Mocker.GetMock<IParsingService>().Setup(c => c.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<SearchCriteriaBase>()))
Mocker.GetMock<IParsingService>().Setup(c => c.Map(It.IsAny<ParsedAlbumInfo>(), It.IsAny<SearchCriteriaBase>()))
.Throws<TestException>();
_reports = new List<ReleaseInfo>

@ -11,9 +11,8 @@ using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Profiles;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Music;
using NzbDrone.Core.DecisionEngine;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.DecisionEngineTests
@ -23,13 +22,13 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
{
private HistorySpecification _upgradeHistory;
private RemoteEpisode _parseResultMulti;
private RemoteEpisode _parseResultSingle;
private RemoteAlbum _parseResultMulti;
private RemoteAlbum _parseResultSingle;
private QualityModel _upgradableQuality;
private QualityModel _notupgradableQuality;
private Series _fakeSeries;
private const int FIRST_EPISODE_ID = 1;
private const int SECOND_EPISODE_ID = 2;
private Artist _fakeArtist;
private const int FIRST_ALBUM_ID = 1;
private const int SECOND_ALBUM_ID = 2;
[SetUp]
public void Setup()
@ -37,29 +36,29 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
Mocker.Resolve<QualityUpgradableSpecification>();
_upgradeHistory = Mocker.Resolve<HistorySpecification>();
var singleEpisodeList = new List<Episode> { new Episode { Id = FIRST_EPISODE_ID, SeasonNumber = 12, EpisodeNumber = 3 } };
var doubleEpisodeList = new List<Episode> {
new Episode {Id = FIRST_EPISODE_ID, SeasonNumber = 12, EpisodeNumber = 3 },
new Episode {Id = SECOND_EPISODE_ID, SeasonNumber = 12, EpisodeNumber = 4 },
new Episode {Id = 3, SeasonNumber = 12, EpisodeNumber = 5 }
var singleAlbumList = new List<Album> { new Album { Id = FIRST_ALBUM_ID} };
var doubleAlbumList = new List<Album> {
new Album {Id = FIRST_ALBUM_ID },
new Album {Id = SECOND_ALBUM_ID },
new Album {Id = 3 }
};
_fakeSeries = Builder<Series>.CreateNew()
_fakeArtist = Builder<Artist>.CreateNew()
.With(c => c.Profile = new Profile { Cutoff = Quality.MP3_512, Items = Qualities.QualityFixture.GetDefaultQualities() })
.Build();
_parseResultMulti = new RemoteEpisode
_parseResultMulti = new RemoteAlbum
{
Series = _fakeSeries,
ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.MP3_192, new Revision(version: 2)) },
Episodes = doubleEpisodeList
Artist = _fakeArtist,
ParsedAlbumInfo = new ParsedAlbumInfo { Quality = new QualityModel(Quality.MP3_192, new Revision(version: 2)) },
Albums = doubleAlbumList
};
_parseResultSingle = new RemoteEpisode
_parseResultSingle = new RemoteAlbum
{
Series = _fakeSeries,
ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.MP3_192, new Revision(version: 2)) },
Episodes = singleEpisodeList
Artist = _fakeArtist,
ParsedAlbumInfo = new ParsedAlbumInfo { Quality = new QualityModel(Quality.MP3_192, new Revision(version: 2)) },
Albums = singleAlbumList
};
_upgradableQuality = new QualityModel(Quality.MP3_192, new Revision(version: 1));
@ -70,9 +69,9 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
.Returns(true);
}
private void GivenMostRecentForEpisode(int episodeId, string downloadId, QualityModel quality, DateTime date, HistoryEventType eventType)
private void GivenMostRecentForAlbum(int albumId, string downloadId, QualityModel quality, DateTime date, HistoryEventType eventType)
{
Mocker.GetMock<IHistoryService>().Setup(s => s.MostRecentForEpisode(episodeId))
Mocker.GetMock<IHistoryService>().Setup(s => s.MostRecentForAlbum(albumId))
.Returns(new History.History { DownloadId = downloadId, Quality = quality, Date = date, EventType = eventType });
}
@ -92,14 +91,14 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
[Test]
public void should_return_true_if_latest_history_item_is_null()
{
Mocker.GetMock<IHistoryService>().Setup(s => s.MostRecentForEpisode(It.IsAny<int>())).Returns((History.History)null);
Mocker.GetMock<IHistoryService>().Setup(s => s.MostRecentForAlbum(It.IsAny<int>())).Returns((History.History)null);
_upgradeHistory.IsSatisfiedBy(_parseResultMulti, null).Accepted.Should().BeTrue();
}
[Test]
public void should_return_true_if_latest_history_item_is_not_grabbed()
{
GivenMostRecentForEpisode(FIRST_EPISODE_ID, string.Empty, _notupgradableQuality, DateTime.UtcNow, HistoryEventType.DownloadFailed);
GivenMostRecentForAlbum(FIRST_ALBUM_ID, string.Empty, _notupgradableQuality, DateTime.UtcNow, HistoryEventType.DownloadFailed);
_upgradeHistory.IsSatisfiedBy(_parseResultMulti, null).Accepted.Should().BeTrue();
}
@ -113,57 +112,57 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
[Test]
public void should_return_true_if_latest_history_item_is_older_than_twelve_hours()
{
GivenMostRecentForEpisode(FIRST_EPISODE_ID, string.Empty, _notupgradableQuality, DateTime.UtcNow.AddHours(-13), HistoryEventType.Grabbed);
GivenMostRecentForAlbum(FIRST_ALBUM_ID, string.Empty, _notupgradableQuality, DateTime.UtcNow.AddHours(-12).AddMilliseconds(-1), HistoryEventType.Grabbed);
_upgradeHistory.IsSatisfiedBy(_parseResultMulti, null).Accepted.Should().BeTrue();
}
[Test]
public void should_be_upgradable_if_only_episode_is_upgradable()
public void should_be_upgradable_if_only_album_is_upgradable()
{
GivenMostRecentForEpisode(FIRST_EPISODE_ID, string.Empty, _upgradableQuality, DateTime.UtcNow, HistoryEventType.Grabbed);
GivenMostRecentForAlbum(FIRST_ALBUM_ID, string.Empty, _upgradableQuality, DateTime.UtcNow, HistoryEventType.Grabbed);
_upgradeHistory.IsSatisfiedBy(_parseResultSingle, null).Accepted.Should().BeTrue();
}
[Test]
public void should_be_upgradable_if_both_episodes_are_upgradable()
public void should_be_upgradable_if_both_albums_are_upgradable()
{
GivenMostRecentForEpisode(FIRST_EPISODE_ID, string.Empty, _upgradableQuality, DateTime.UtcNow, HistoryEventType.Grabbed);
GivenMostRecentForEpisode(SECOND_EPISODE_ID, string.Empty, _upgradableQuality, DateTime.UtcNow, HistoryEventType.Grabbed);
GivenMostRecentForAlbum(FIRST_ALBUM_ID, string.Empty, _upgradableQuality, DateTime.UtcNow, HistoryEventType.Grabbed);
GivenMostRecentForAlbum(SECOND_ALBUM_ID, string.Empty, _upgradableQuality, DateTime.UtcNow, HistoryEventType.Grabbed);
_upgradeHistory.IsSatisfiedBy(_parseResultMulti, null).Accepted.Should().BeTrue();
}
[Test]
public void should_not_be_upgradable_if_both_episodes_are_not_upgradable()
public void should_not_be_upgradable_if_both_albums_are_not_upgradable()
{
GivenMostRecentForEpisode(FIRST_EPISODE_ID, string.Empty, _notupgradableQuality, DateTime.UtcNow, HistoryEventType.Grabbed);
GivenMostRecentForEpisode(SECOND_EPISODE_ID, string.Empty, _notupgradableQuality, DateTime.UtcNow, HistoryEventType.Grabbed);
GivenMostRecentForAlbum(FIRST_ALBUM_ID, string.Empty, _notupgradableQuality, DateTime.UtcNow, HistoryEventType.Grabbed);
GivenMostRecentForAlbum(SECOND_ALBUM_ID, string.Empty, _notupgradableQuality, DateTime.UtcNow, HistoryEventType.Grabbed);
_upgradeHistory.IsSatisfiedBy(_parseResultMulti, null).Accepted.Should().BeFalse();
}
[Test]
public void should_be_not_upgradable_if_only_first_episodes_is_upgradable()
public void should_be_not_upgradable_if_only_first_albums_is_upgradable()
{
GivenMostRecentForEpisode(FIRST_EPISODE_ID, string.Empty, _upgradableQuality, DateTime.UtcNow, HistoryEventType.Grabbed);
GivenMostRecentForEpisode(FIRST_EPISODE_ID, string.Empty, _notupgradableQuality, DateTime.UtcNow, HistoryEventType.Grabbed);
GivenMostRecentForAlbum(FIRST_ALBUM_ID, string.Empty, _upgradableQuality, DateTime.UtcNow, HistoryEventType.Grabbed);
GivenMostRecentForAlbum(FIRST_ALBUM_ID, string.Empty, _notupgradableQuality, DateTime.UtcNow, HistoryEventType.Grabbed);
_upgradeHistory.IsSatisfiedBy(_parseResultMulti, null).Accepted.Should().BeFalse();
}
[Test]
public void should_be_not_upgradable_if_only_second_episodes_is_upgradable()
public void should_be_not_upgradable_if_only_second_albums_is_upgradable()
{
GivenMostRecentForEpisode(FIRST_EPISODE_ID, string.Empty, _notupgradableQuality, DateTime.UtcNow, HistoryEventType.Grabbed);
GivenMostRecentForEpisode(SECOND_EPISODE_ID, string.Empty, _upgradableQuality, DateTime.UtcNow, HistoryEventType.Grabbed);
GivenMostRecentForAlbum(FIRST_ALBUM_ID, string.Empty, _notupgradableQuality, DateTime.UtcNow, HistoryEventType.Grabbed);
GivenMostRecentForAlbum(SECOND_ALBUM_ID, string.Empty, _upgradableQuality, DateTime.UtcNow, HistoryEventType.Grabbed);
_upgradeHistory.IsSatisfiedBy(_parseResultMulti, null).Accepted.Should().BeFalse();
}
[Test]
public void should_not_be_upgradable_if_episode_is_of_same_quality_as_existing()
public void should_not_be_upgradable_if_album_is_of_same_quality_as_existing()
{
_fakeSeries.Profile = new Profile { Cutoff = Quality.MP3_512, Items = Qualities.QualityFixture.GetDefaultQualities() };
_parseResultSingle.ParsedEpisodeInfo.Quality = new QualityModel(Quality.MP3_512, new Revision(version: 1));
_fakeArtist.Profile = new Profile { Cutoff = Quality.MP3_512, Items = Qualities.QualityFixture.GetDefaultQualities() };
_parseResultSingle.ParsedAlbumInfo.Quality = new QualityModel(Quality.MP3_512, new Revision(version: 1));
_upgradableQuality = new QualityModel(Quality.MP3_512, new Revision(version: 1));
GivenMostRecentForEpisode(FIRST_EPISODE_ID, string.Empty, _upgradableQuality, DateTime.UtcNow, HistoryEventType.Grabbed);
GivenMostRecentForAlbum(FIRST_ALBUM_ID, string.Empty, _upgradableQuality, DateTime.UtcNow, HistoryEventType.Grabbed);
_upgradeHistory.IsSatisfiedBy(_parseResultSingle, null).Accepted.Should().BeFalse();
}
@ -171,11 +170,11 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
[Test]
public void should_not_be_upgradable_if_cutoff_already_met()
{
_fakeSeries.Profile = new Profile { Cutoff = Quality.MP3_512, Items = Qualities.QualityFixture.GetDefaultQualities() };
_parseResultSingle.ParsedEpisodeInfo.Quality = new QualityModel(Quality.MP3_512, new Revision(version: 1));
_fakeArtist.Profile = new Profile { Cutoff = Quality.MP3_512, Items = Qualities.QualityFixture.GetDefaultQualities() };
_parseResultSingle.ParsedAlbumInfo.Quality = new QualityModel(Quality.MP3_512, new Revision(version: 1));
_upgradableQuality = new QualityModel(Quality.MP3_512, new Revision(version: 1));
GivenMostRecentForEpisode(FIRST_EPISODE_ID, string.Empty, _upgradableQuality, DateTime.UtcNow, HistoryEventType.Grabbed);
GivenMostRecentForAlbum(FIRST_ALBUM_ID, string.Empty, _upgradableQuality, DateTime.UtcNow, HistoryEventType.Grabbed);
_upgradeHistory.IsSatisfiedBy(_parseResultSingle, null).Accepted.Should().BeFalse();
}
@ -183,7 +182,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
[Test]
public void should_return_false_if_latest_history_item_is_only_one_hour_old()
{
GivenMostRecentForEpisode(FIRST_EPISODE_ID, string.Empty, _notupgradableQuality, DateTime.UtcNow.AddHours(-1), HistoryEventType.Grabbed);
GivenMostRecentForAlbum(FIRST_ALBUM_ID, string.Empty, _notupgradableQuality, DateTime.UtcNow.AddHours(-1), HistoryEventType.Grabbed);
_upgradeHistory.IsSatisfiedBy(_parseResultMulti, null).Accepted.Should().BeFalse();
}
@ -191,7 +190,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
public void should_return_false_if_latest_history_has_a_download_id_and_cdh_is_disabled()
{
GivenCdhDisabled();
GivenMostRecentForEpisode(FIRST_EPISODE_ID, "test", _upgradableQuality, DateTime.UtcNow.AddDays(-100), HistoryEventType.Grabbed);
GivenMostRecentForAlbum(FIRST_ALBUM_ID, "test", _upgradableQuality, DateTime.UtcNow.AddDays(-100), HistoryEventType.Grabbed);
_upgradeHistory.IsSatisfiedBy(_parseResultMulti, null).Accepted.Should().BeTrue();
}
@ -199,20 +198,20 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
public void should_return_false_if_cutoff_already_met_and_cdh_is_disabled()
{
GivenCdhDisabled();
_fakeSeries.Profile = new Profile { Cutoff = Quality.MP3_512, Items = Qualities.QualityFixture.GetDefaultQualities() };
_parseResultSingle.ParsedEpisodeInfo.Quality = new QualityModel(Quality.MP3_512, new Revision(version: 1));
_fakeArtist.Profile = new Profile { Cutoff = Quality.MP3_512, Items = Qualities.QualityFixture.GetDefaultQualities() };
_parseResultSingle.ParsedAlbumInfo.Quality = new QualityModel(Quality.MP3_512, new Revision(version: 1));
_upgradableQuality = new QualityModel(Quality.MP3_512, new Revision(version: 1));
GivenMostRecentForEpisode(FIRST_EPISODE_ID, "test", _upgradableQuality, DateTime.UtcNow.AddDays(-100), HistoryEventType.Grabbed);
GivenMostRecentForAlbum(FIRST_ALBUM_ID, "test", _upgradableQuality, DateTime.UtcNow.AddDays(-100), HistoryEventType.Grabbed);
_upgradeHistory.IsSatisfiedBy(_parseResultSingle, null).Accepted.Should().BeFalse();
}
[Test]
public void should_return_false_if_only_episode_is_not_upgradable_and_cdh_is_disabled()
public void should_return_false_if_only_album_is_not_upgradable_and_cdh_is_disabled()
{
GivenCdhDisabled();
GivenMostRecentForEpisode(FIRST_EPISODE_ID, "test", _notupgradableQuality, DateTime.UtcNow.AddDays(-100), HistoryEventType.Grabbed);
GivenMostRecentForAlbum(FIRST_ALBUM_ID, "test", _notupgradableQuality, DateTime.UtcNow.AddDays(-100), HistoryEventType.Grabbed);
_upgradeHistory.IsSatisfiedBy(_parseResultSingle, null).Accepted.Should().BeFalse();
}
}

@ -6,7 +6,7 @@ using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Profiles;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Music;
namespace NzbDrone.Core.Test.DecisionEngineTests
{
@ -14,18 +14,18 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
public class LanguageSpecificationFixture : CoreTest
{
private RemoteEpisode _remoteEpisode;
private RemoteAlbum _remoteAlbum;
[SetUp]
public void Setup()
{
_remoteEpisode = new RemoteEpisode
_remoteAlbum = new RemoteAlbum
{
ParsedEpisodeInfo = new ParsedEpisodeInfo
ParsedAlbumInfo = new ParsedAlbumInfo
{
Language = Language.English
},
Series = new Series
Artist = new Artist
{
Profile = new LazyLoaded<Profile>(new Profile
{
@ -37,12 +37,12 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
private void WithEnglishRelease()
{
_remoteEpisode.ParsedEpisodeInfo.Language = Language.English;
_remoteAlbum.ParsedAlbumInfo.Language = Language.English;
}
private void WithGermanRelease()
{
_remoteEpisode.ParsedEpisodeInfo.Language = Language.German;
_remoteAlbum.ParsedAlbumInfo.Language = Language.German;
}
[Test]
@ -50,7 +50,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
{
WithEnglishRelease();
Mocker.Resolve<LanguageSpecification>().IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
Mocker.Resolve<LanguageSpecification>().IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeTrue();
}
[Test]
@ -58,7 +58,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
{
WithGermanRelease();
Mocker.Resolve<LanguageSpecification>().IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
Mocker.Resolve<LanguageSpecification>().IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeFalse();
}
}
}

@ -13,12 +13,12 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
public class MinimumAgeSpecificationFixture : CoreTest<MinimumAgeSpecification>
{
private RemoteEpisode _remoteEpisode;
private RemoteAlbum _remoteAlbum;
[SetUp]
public void Setup()
{
_remoteEpisode = new RemoteEpisode
_remoteAlbum = new RemoteAlbum
{
Release = new ReleaseInfo() { DownloadProtocol = DownloadProtocol.Usenet }
};
@ -31,7 +31,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
private void WithAge(int minutes)
{
_remoteEpisode.Release.PublishDate = DateTime.UtcNow.AddMinutes(-minutes);
_remoteAlbum.Release.PublishDate = DateTime.UtcNow.AddMinutes(-minutes);
}
[Test]
@ -40,7 +40,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
WithMinimumAge(0);
WithAge(100);
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeTrue();
}
[Test]
@ -49,7 +49,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
WithMinimumAge(30);
WithAge(100);
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeTrue();
}
[Test]
@ -58,7 +58,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
WithMinimumAge(30);
WithAge(10);
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeFalse();
}
}
}

@ -0,0 +1,141 @@
using System.Collections.Generic;
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.DecisionEngine.Specifications.RssSync;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Music;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.DecisionEngineTests
{
[TestFixture]
public class MonitoredAlbumSpecificationFixture : CoreTest<MonitoredAlbumSpecification>
{
private MonitoredAlbumSpecification _monitoredAlbumSpecification;
private RemoteAlbum _parseResultMulti;
private RemoteAlbum _parseResultSingle;
private Artist _fakeArtist;
private Album _firstAlbum;
private Album _secondAlbum;
[SetUp]
public void Setup()
{
_monitoredAlbumSpecification = Mocker.Resolve<MonitoredAlbumSpecification>();
_fakeArtist = Builder<Artist>.CreateNew()
.With(c => c.Monitored = true)
.Build();
_firstAlbum = new Album { Monitored = true };
_secondAlbum = new Album { Monitored = true };
var singleAlbumList = new List<Album> { _firstAlbum };
var doubleAlbumList = new List<Album> { _firstAlbum, _secondAlbum };
_parseResultMulti = new RemoteAlbum
{
Artist = _fakeArtist,
Albums = doubleAlbumList
};
_parseResultSingle = new RemoteAlbum
{
Artist = _fakeArtist,
Albums = singleAlbumList
};
}
private void WithFirstAlbumUnmonitored()
{
_firstAlbum.Monitored = false;
}
private void WithSecondAlbumUnmonitored()
{
_secondAlbum.Monitored = false;
}
[Test]
public void setup_should_return_monitored_album_should_return_true()
{
_monitoredAlbumSpecification.IsSatisfiedBy(_parseResultSingle, null).Accepted.Should().BeTrue();
_monitoredAlbumSpecification.IsSatisfiedBy(_parseResultMulti, null).Accepted.Should().BeTrue();
}
[Test]
public void not_monitored_series_should_be_skipped()
{
_fakeArtist.Monitored = false;
_monitoredAlbumSpecification.IsSatisfiedBy(_parseResultMulti, null).Accepted.Should().BeFalse();
}
[Test]
public void only_album_not_monitored_should_return_false()
{
WithFirstAlbumUnmonitored();
_monitoredAlbumSpecification.IsSatisfiedBy(_parseResultSingle, null).Accepted.Should().BeFalse();
}
[Test]
public void both_albums_not_monitored_should_return_false()
{
WithFirstAlbumUnmonitored();
WithSecondAlbumUnmonitored();
_monitoredAlbumSpecification.IsSatisfiedBy(_parseResultMulti, null).Accepted.Should().BeFalse();
}
[Test]
public void only_first_album_not_monitored_should_return_false()
{
WithFirstAlbumUnmonitored();
_monitoredAlbumSpecification.IsSatisfiedBy(_parseResultMulti, null).Accepted.Should().BeFalse();
}
[Test]
public void only_second_album_not_monitored_should_return_false()
{
WithSecondAlbumUnmonitored();
_monitoredAlbumSpecification.IsSatisfiedBy(_parseResultMulti, null).Accepted.Should().BeFalse();
}
[Test]
public void should_return_true_for_single_album_search()
{
_fakeArtist.Monitored = false;
_monitoredAlbumSpecification.IsSatisfiedBy(_parseResultSingle, new SingleEpisodeSearchCriteria()).Accepted.Should().BeTrue();
}
[Test]
public void should_return_true_if_album_is_monitored_for_season_search()
{
_monitoredAlbumSpecification.IsSatisfiedBy(_parseResultSingle, new SeasonSearchCriteria()).Accepted.Should().BeTrue();
}
[Test]
public void should_return_false_if_album_is_not_monitored_for_season_search()
{
WithFirstAlbumUnmonitored();
_monitoredAlbumSpecification.IsSatisfiedBy(_parseResultSingle, new SeasonSearchCriteria()).Accepted.Should().BeFalse();
}
[Test]
public void should_return_true_if_album_is_not_monitored_and_monitoredEpisodesOnly_flag_is_false()
{
WithFirstAlbumUnmonitored();
_monitoredAlbumSpecification.IsSatisfiedBy(_parseResultSingle, new SingleEpisodeSearchCriteria { MonitoredEpisodesOnly = false }).Accepted.Should().BeTrue();
}
[Test]
public void should_return_false_if_album_is_not_monitored_and_monitoredEpisodesOnly_flag_is_true()
{
WithFirstAlbumUnmonitored();
_monitoredAlbumSpecification.IsSatisfiedBy(_parseResultSingle, new SingleEpisodeSearchCriteria{ MonitoredEpisodesOnly = true}).Accepted.Should().BeFalse();
}
}
}

@ -1,141 +0,0 @@
using System.Collections.Generic;
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.DecisionEngine.Specifications.RssSync;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.DecisionEngineTests
{
[TestFixture]
public class MonitoredEpisodeSpecificationFixture : CoreTest<MonitoredEpisodeSpecification>
{
private MonitoredEpisodeSpecification _monitoredEpisodeSpecification;
private RemoteEpisode _parseResultMulti;
private RemoteEpisode _parseResultSingle;
private Series _fakeSeries;
private Episode _firstEpisode;
private Episode _secondEpisode;
[SetUp]
public void Setup()
{
_monitoredEpisodeSpecification = Mocker.Resolve<MonitoredEpisodeSpecification>();
_fakeSeries = Builder<Series>.CreateNew()
.With(c => c.Monitored = true)
.Build();
_firstEpisode = new Episode { Monitored = true };
_secondEpisode = new Episode { Monitored = true };
var singleEpisodeList = new List<Episode> { _firstEpisode };
var doubleEpisodeList = new List<Episode> { _firstEpisode, _secondEpisode };
_parseResultMulti = new RemoteEpisode
{
Series = _fakeSeries,
Episodes = doubleEpisodeList
};
_parseResultSingle = new RemoteEpisode
{
Series = _fakeSeries,
Episodes = singleEpisodeList
};
}
private void WithFirstEpisodeUnmonitored()
{
_firstEpisode.Monitored = false;
}
private void WithSecondEpisodeUnmonitored()
{
_secondEpisode.Monitored = false;
}
[Test]
public void setup_should_return_monitored_episode_should_return_true()
{
_monitoredEpisodeSpecification.IsSatisfiedBy(_parseResultSingle, null).Accepted.Should().BeTrue();
_monitoredEpisodeSpecification.IsSatisfiedBy(_parseResultMulti, null).Accepted.Should().BeTrue();
}
[Test]
public void not_monitored_series_should_be_skipped()
{
_fakeSeries.Monitored = false;
_monitoredEpisodeSpecification.IsSatisfiedBy(_parseResultMulti, null).Accepted.Should().BeFalse();
}
[Test]
public void only_episode_not_monitored_should_return_false()
{
WithFirstEpisodeUnmonitored();
_monitoredEpisodeSpecification.IsSatisfiedBy(_parseResultSingle, null).Accepted.Should().BeFalse();
}
[Test]
public void both_episodes_not_monitored_should_return_false()
{
WithFirstEpisodeUnmonitored();
WithSecondEpisodeUnmonitored();
_monitoredEpisodeSpecification.IsSatisfiedBy(_parseResultMulti, null).Accepted.Should().BeFalse();
}
[Test]
public void only_first_episode_not_monitored_should_return_false()
{
WithFirstEpisodeUnmonitored();
_monitoredEpisodeSpecification.IsSatisfiedBy(_parseResultMulti, null).Accepted.Should().BeFalse();
}
[Test]
public void only_second_episode_not_monitored_should_return_false()
{
WithSecondEpisodeUnmonitored();
_monitoredEpisodeSpecification.IsSatisfiedBy(_parseResultMulti, null).Accepted.Should().BeFalse();
}
[Test]
public void should_return_true_for_single_episode_search()
{
_fakeSeries.Monitored = false;
_monitoredEpisodeSpecification.IsSatisfiedBy(_parseResultSingle, new SingleEpisodeSearchCriteria()).Accepted.Should().BeTrue();
}
[Test]
public void should_return_true_if_episode_is_monitored_for_season_search()
{
_monitoredEpisodeSpecification.IsSatisfiedBy(_parseResultSingle, new SeasonSearchCriteria()).Accepted.Should().BeTrue();
}
[Test]
public void should_return_false_if_episode_is_not_monitored_for_season_search()
{
WithFirstEpisodeUnmonitored();
_monitoredEpisodeSpecification.IsSatisfiedBy(_parseResultSingle, new SeasonSearchCriteria()).Accepted.Should().BeFalse();
}
[Test]
public void should_return_true_if_episode_is_not_monitored_and_monitoredEpisodesOnly_flag_is_false()
{
WithFirstEpisodeUnmonitored();
_monitoredEpisodeSpecification.IsSatisfiedBy(_parseResultSingle, new SingleEpisodeSearchCriteria { MonitoredEpisodesOnly = false }).Accepted.Should().BeTrue();
}
[Test]
public void should_return_false_if_episode_is_not_monitored_and_monitoredEpisodesOnly_flag_is_true()
{
WithFirstEpisodeUnmonitored();
_monitoredEpisodeSpecification.IsSatisfiedBy(_parseResultSingle, new SingleEpisodeSearchCriteria{ MonitoredEpisodesOnly = true}).Accepted.Should().BeFalse();
}
}
}

@ -4,7 +4,7 @@ using System.Linq;
using Moq;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.Profiles.Delay;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Music;
using NzbDrone.Core.Profiles;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.Parser.Model;
@ -26,33 +26,32 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
GivenPreferredDownloadProtocol(DownloadProtocol.Usenet);
}
private Episode GivenEpisode(int id)
private Album GivenAlbum(int id)
{
return Builder<Episode>.CreateNew()
return Builder<Album>.CreateNew()
.With(e => e.Id = id)
.With(e => e.EpisodeNumber = id)
.Build();
}
private RemoteEpisode GivenRemoteEpisode(List<Episode> episodes, QualityModel quality, int age = 0, long size = 0, DownloadProtocol downloadProtocol = DownloadProtocol.Usenet)
private RemoteAlbum GivenRemoteAlbum(List<Album> albums, QualityModel quality, int age = 0, long size = 0, DownloadProtocol downloadProtocol = DownloadProtocol.Usenet)
{
var remoteEpisode = new RemoteEpisode();
remoteEpisode.ParsedEpisodeInfo = new ParsedEpisodeInfo();
remoteEpisode.ParsedEpisodeInfo.Quality = quality;
var remoteAlbum = new RemoteAlbum();
remoteAlbum.ParsedAlbumInfo = new ParsedAlbumInfo();
remoteAlbum.ParsedAlbumInfo.Quality = quality;
remoteEpisode.Episodes = new List<Episode>();
remoteEpisode.Episodes.AddRange(episodes);
remoteAlbum.Albums = new List<Album>();
remoteAlbum.Albums.AddRange(albums);
remoteEpisode.Release = new ReleaseInfo();
remoteEpisode.Release.PublishDate = DateTime.Now.AddDays(-age);
remoteEpisode.Release.Size = size;
remoteEpisode.Release.DownloadProtocol = downloadProtocol;
remoteAlbum.Release = new ReleaseInfo();
remoteAlbum.Release.PublishDate = DateTime.Now.AddDays(-age);
remoteAlbum.Release.Size = size;
remoteAlbum.Release.DownloadProtocol = downloadProtocol;
remoteEpisode.Series = Builder<Series>.CreateNew()
remoteAlbum.Artist = Builder<Artist>.CreateNew()
.With(e => e.Profile = new Profile { Items = Qualities.QualityFixture.GetDefaultQualities() })
.Build();
return remoteEpisode;
return remoteAlbum;
}
private void GivenPreferredDownloadProtocol(DownloadProtocol downloadProtocol)
@ -68,103 +67,75 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
[Test]
public void should_put_propers_before_non_propers()
{
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.MP3_256, new Revision(version: 1)));
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.MP3_256, new Revision(version: 2)));
var remoteAlbum1 = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.MP3_256, new Revision(version: 1)));
var remoteAlbum2 = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.MP3_256, new Revision(version: 2)));
var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteEpisode1));
decisions.Add(new DownloadDecision(remoteEpisode2));
decisions.Add(new DownloadDecision(remoteAlbum1));
decisions.Add(new DownloadDecision(remoteAlbum2));
var qualifiedReports = Subject.PrioritizeDecisions(decisions);
qualifiedReports.First().RemoteEpisode.ParsedEpisodeInfo.Quality.Revision.Version.Should().Be(2);
qualifiedReports.First().RemoteAlbum.ParsedAlbumInfo.Quality.Revision.Version.Should().Be(2);
}
[Test]
public void should_put_higher_quality_before_lower()
{
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.MP3_192));
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.MP3_256));
var remoteAlbum1 = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.MP3_192));
var remoteAlbum2 = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.MP3_256));
var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteEpisode1));
decisions.Add(new DownloadDecision(remoteEpisode2));
decisions.Add(new DownloadDecision(remoteAlbum1));
decisions.Add(new DownloadDecision(remoteAlbum2));
var qualifiedReports = Subject.PrioritizeDecisions(decisions);
qualifiedReports.First().RemoteEpisode.ParsedEpisodeInfo.Quality.Quality.Should().Be(Quality.MP3_256);
}
[Test]
public void should_order_by_lowest_number_of_episodes()
{
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(2) }, new QualityModel(Quality.MP3_256));
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.MP3_256));
var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteEpisode1));
decisions.Add(new DownloadDecision(remoteEpisode2));
var qualifiedReports = Subject.PrioritizeDecisions(decisions);
qualifiedReports.First().RemoteEpisode.Episodes.First().EpisodeNumber.Should().Be(1);
}
[Test]
public void should_order_by_lowest_number_of_episodes_with_multiple_episodes()
{
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(2), GivenEpisode(3) }, new QualityModel(Quality.MP3_256));
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1), GivenEpisode(2) }, new QualityModel(Quality.MP3_256));
var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteEpisode1));
decisions.Add(new DownloadDecision(remoteEpisode2));
var qualifiedReports = Subject.PrioritizeDecisions(decisions);
qualifiedReports.First().RemoteEpisode.Episodes.First().EpisodeNumber.Should().Be(1);
qualifiedReports.First().RemoteAlbum.ParsedAlbumInfo.Quality.Quality.Should().Be(Quality.MP3_256);
}
[Test]
public void should_order_by_age_then_largest_rounded_to_200mb()
{
var remoteEpisodeSd = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.MP3_192), size: 100.Megabytes(), age: 1);
var remoteEpisodeHdSmallOld = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.MP3_256), size: 1200.Megabytes(), age: 1000);
var remoteEpisodeSmallYoung = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.MP3_256), size: 1250.Megabytes(), age: 10);
var remoteEpisodeHdLargeYoung = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.MP3_256), size: 3000.Megabytes(), age: 1);
var remoteAlbumSd = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.MP3_192), size: 100.Megabytes(), age: 1);
var remoteAlbumHdSmallOld = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.MP3_256), size: 1200.Megabytes(), age: 1000);
var remoteAlbumSmallYoung = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.MP3_256), size: 1250.Megabytes(), age: 10);
var remoteAlbumHdLargeYoung = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.MP3_256), size: 3000.Megabytes(), age: 1);
var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteEpisodeSd));
decisions.Add(new DownloadDecision(remoteEpisodeHdSmallOld));
decisions.Add(new DownloadDecision(remoteEpisodeSmallYoung));
decisions.Add(new DownloadDecision(remoteEpisodeHdLargeYoung));
decisions.Add(new DownloadDecision(remoteAlbumSd));
decisions.Add(new DownloadDecision(remoteAlbumHdSmallOld));
decisions.Add(new DownloadDecision(remoteAlbumSmallYoung));
decisions.Add(new DownloadDecision(remoteAlbumHdLargeYoung));
var qualifiedReports = Subject.PrioritizeDecisions(decisions);
qualifiedReports.First().RemoteEpisode.Should().Be(remoteEpisodeHdLargeYoung);
qualifiedReports.First().RemoteAlbum.Should().Be(remoteAlbumHdLargeYoung);
}
[Test]
public void should_order_by_youngest()
{
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.MP3_256), age: 10);
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.MP3_256), age: 5);
var remoteAlbum1 = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.MP3_256), age: 10);
var remoteAlbum2 = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.MP3_256), age: 5);
var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteEpisode1));
decisions.Add(new DownloadDecision(remoteEpisode2));
decisions.Add(new DownloadDecision(remoteAlbum1));
decisions.Add(new DownloadDecision(remoteAlbum2));
var qualifiedReports = Subject.PrioritizeDecisions(decisions);
qualifiedReports.First().RemoteEpisode.Should().Be(remoteEpisode2);
qualifiedReports.First().RemoteAlbum.Should().Be(remoteAlbum2);
}
[Test]
public void should_not_throw_if_no_episodes_are_found()
{
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.MP3_256), size: 500.Megabytes());
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.MP3_256), size: 500.Megabytes());
var remoteAlbum1 = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.MP3_256), size: 500.Megabytes());
var remoteAlbum2 = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.MP3_256), size: 500.Megabytes());
remoteEpisode1.Episodes = new List<Episode>();
remoteAlbum1.Albums = new List<Album>();
var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteEpisode1));
decisions.Add(new DownloadDecision(remoteEpisode2));
decisions.Add(new DownloadDecision(remoteAlbum1));
decisions.Add(new DownloadDecision(remoteAlbum2));
Subject.PrioritizeDecisions(decisions);
}
@ -174,15 +145,15 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
{
GivenPreferredDownloadProtocol(DownloadProtocol.Usenet);
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.MP3_256), downloadProtocol: DownloadProtocol.Torrent);
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.MP3_256), downloadProtocol: DownloadProtocol.Usenet);
var remoteAlbum1 = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.MP3_256), downloadProtocol: DownloadProtocol.Torrent);
var remoteAlbum2 = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.MP3_256), downloadProtocol: DownloadProtocol.Usenet);
var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteEpisode1));
decisions.Add(new DownloadDecision(remoteEpisode2));
decisions.Add(new DownloadDecision(remoteAlbum1));
decisions.Add(new DownloadDecision(remoteAlbum2));
var qualifiedReports = Subject.PrioritizeDecisions(decisions);
qualifiedReports.First().RemoteEpisode.Release.DownloadProtocol.Should().Be(DownloadProtocol.Usenet);
qualifiedReports.First().RemoteAlbum.Release.DownloadProtocol.Should().Be(DownloadProtocol.Usenet);
}
[Test]
@ -190,69 +161,36 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
{
GivenPreferredDownloadProtocol(DownloadProtocol.Torrent);
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.MP3_256), downloadProtocol: DownloadProtocol.Torrent);
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.MP3_256), downloadProtocol: DownloadProtocol.Usenet);
var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteEpisode1));
decisions.Add(new DownloadDecision(remoteEpisode2));
var qualifiedReports = Subject.PrioritizeDecisions(decisions);
qualifiedReports.First().RemoteEpisode.Release.DownloadProtocol.Should().Be(DownloadProtocol.Torrent);
}
[Test]
public void should_prefer_season_pack_above_single_episode()
{
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1), GivenEpisode(2) }, new QualityModel(Quality.MP3_256));
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.MP3_256));
remoteEpisode1.ParsedEpisodeInfo.FullSeason = true;
var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteEpisode1));
decisions.Add(new DownloadDecision(remoteEpisode2));
var qualifiedReports = Subject.PrioritizeDecisions(decisions);
qualifiedReports.First().RemoteEpisode.ParsedEpisodeInfo.FullSeason.Should().BeTrue();
}
[Test]
public void should_prefer_multiepisode_over_single_episode_for_anime()
{
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1), GivenEpisode(2) }, new QualityModel(Quality.MP3_256));
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.MP3_256));
remoteEpisode1.Series.SeriesType = SeriesTypes.Anime;
remoteEpisode2.Series.SeriesType = SeriesTypes.Anime;
var remoteAlbum1 = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.MP3_256), downloadProtocol: DownloadProtocol.Torrent);
var remoteAlbum2 = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.MP3_256), downloadProtocol: DownloadProtocol.Usenet);
var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteEpisode1));
decisions.Add(new DownloadDecision(remoteEpisode2));
decisions.Add(new DownloadDecision(remoteAlbum1));
decisions.Add(new DownloadDecision(remoteAlbum2));
var qualifiedReports = Subject.PrioritizeDecisions(decisions);
qualifiedReports.First().RemoteEpisode.Episodes.Count.Should().Be(remoteEpisode1.Episodes.Count);
qualifiedReports.First().RemoteAlbum.Release.DownloadProtocol.Should().Be(DownloadProtocol.Torrent);
}
[Test]
public void should_prefer_single_episode_over_multi_episode_for_non_anime()
public void should_prefer_single_album_over_multi_album()
{
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1), GivenEpisode(2) }, new QualityModel(Quality.MP3_256));
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.MP3_256));
var remoteAlbum1 = GivenRemoteAlbum(new List<Album> { GivenAlbum(1), GivenAlbum(2) }, new QualityModel(Quality.MP3_256));
var remoteAlbum2 = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.MP3_256));
var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteEpisode1));
decisions.Add(new DownloadDecision(remoteEpisode2));
decisions.Add(new DownloadDecision(remoteAlbum1));
decisions.Add(new DownloadDecision(remoteAlbum2));
var qualifiedReports = Subject.PrioritizeDecisions(decisions);
qualifiedReports.First().RemoteEpisode.Episodes.Count.Should().Be(remoteEpisode2.Episodes.Count);
qualifiedReports.First().RemoteAlbum.Albums.Count.Should().Be(remoteAlbum2.Albums.Count);
}
[Test]
public void should_prefer_releases_with_more_seeders()
{
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.MP3_256));
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.MP3_256));
var remoteAlbum1 = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.MP3_256));
var remoteAlbum2 = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.MP3_256));
var torrentInfo1 = new TorrentInfo();
torrentInfo1.PublishDate = DateTime.Now;
@ -263,22 +201,22 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
var torrentInfo2 = torrentInfo1.JsonClone();
torrentInfo2.Seeders = 100;
remoteEpisode1.Release = torrentInfo1;
remoteEpisode2.Release = torrentInfo2;
remoteAlbum1.Release = torrentInfo1;
remoteAlbum2.Release = torrentInfo2;
var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteEpisode1));
decisions.Add(new DownloadDecision(remoteEpisode2));
decisions.Add(new DownloadDecision(remoteAlbum1));
decisions.Add(new DownloadDecision(remoteAlbum2));
var qualifiedReports = Subject.PrioritizeDecisions(decisions);
((TorrentInfo) qualifiedReports.First().RemoteEpisode.Release).Seeders.Should().Be(torrentInfo2.Seeders);
((TorrentInfo) qualifiedReports.First().RemoteAlbum.Release).Seeders.Should().Be(torrentInfo2.Seeders);
}
[Test]
public void should_prefer_releases_with_more_peers_given_equal_number_of_seeds()
{
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.MP3_256));
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.MP3_256));
var remoteAlbum1 = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.MP3_256));
var remoteAlbum2 = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.MP3_256));
var torrentInfo1 = new TorrentInfo();
torrentInfo1.PublishDate = DateTime.Now;
@ -291,22 +229,22 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
var torrentInfo2 = torrentInfo1.JsonClone();
torrentInfo2.Peers = 100;
remoteEpisode1.Release = torrentInfo1;
remoteEpisode2.Release = torrentInfo2;
remoteAlbum1.Release = torrentInfo1;
remoteAlbum2.Release = torrentInfo2;
var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteEpisode1));
decisions.Add(new DownloadDecision(remoteEpisode2));
decisions.Add(new DownloadDecision(remoteAlbum1));
decisions.Add(new DownloadDecision(remoteAlbum2));
var qualifiedReports = Subject.PrioritizeDecisions(decisions);
((TorrentInfo)qualifiedReports.First().RemoteEpisode.Release).Peers.Should().Be(torrentInfo2.Peers);
((TorrentInfo)qualifiedReports.First().RemoteAlbum.Release).Peers.Should().Be(torrentInfo2.Peers);
}
[Test]
public void should_prefer_releases_with_more_peers_no_seeds()
{
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.MP3_256));
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.MP3_256));
var remoteAlbum1 = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.MP3_256));
var remoteAlbum2 = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.MP3_256));
var torrentInfo1 = new TorrentInfo();
torrentInfo1.PublishDate = DateTime.Now;
@ -320,22 +258,22 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
torrentInfo2.Seeders = 0;
torrentInfo2.Peers = 100;
remoteEpisode1.Release = torrentInfo1;
remoteEpisode2.Release = torrentInfo2;
remoteAlbum1.Release = torrentInfo1;
remoteAlbum2.Release = torrentInfo2;
var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteEpisode1));
decisions.Add(new DownloadDecision(remoteEpisode2));
decisions.Add(new DownloadDecision(remoteAlbum1));
decisions.Add(new DownloadDecision(remoteAlbum2));
var qualifiedReports = Subject.PrioritizeDecisions(decisions);
((TorrentInfo)qualifiedReports.First().RemoteEpisode.Release).Peers.Should().Be(torrentInfo2.Peers);
((TorrentInfo)qualifiedReports.First().RemoteAlbum.Release).Peers.Should().Be(torrentInfo2.Peers);
}
[Test]
public void should_prefer_first_release_if_peers_and_size_are_too_similar()
{
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.MP3_256));
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.MP3_256));
var remoteAlbum1 = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.MP3_256));
var remoteAlbum2 = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.MP3_256));
var torrentInfo1 = new TorrentInfo();
torrentInfo1.PublishDate = DateTime.Now;
@ -349,42 +287,42 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
torrentInfo2.Peers = 10;
torrentInfo1.Size = 250.Megabytes();
remoteEpisode1.Release = torrentInfo1;
remoteEpisode2.Release = torrentInfo2;
remoteAlbum1.Release = torrentInfo1;
remoteAlbum2.Release = torrentInfo2;
var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteEpisode1));
decisions.Add(new DownloadDecision(remoteEpisode2));
decisions.Add(new DownloadDecision(remoteAlbum1));
decisions.Add(new DownloadDecision(remoteAlbum2));
var qualifiedReports = Subject.PrioritizeDecisions(decisions);
((TorrentInfo) qualifiedReports.First().RemoteEpisode.Release).Should().Be(torrentInfo1);
((TorrentInfo) qualifiedReports.First().RemoteAlbum.Release).Should().Be(torrentInfo1);
}
[Test]
public void should_prefer_first_release_if_age_and_size_are_too_similar()
{
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.MP3_256));
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.MP3_256));
var remoteAlbum1 = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.MP3_256));
var remoteAlbum2 = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.MP3_256));
remoteEpisode1.Release.PublishDate = DateTime.UtcNow.AddDays(-100);
remoteEpisode1.Release.Size = 200.Megabytes();
remoteAlbum1.Release.PublishDate = DateTime.UtcNow.AddDays(-100);
remoteAlbum1.Release.Size = 200.Megabytes();
remoteEpisode2.Release.PublishDate = DateTime.UtcNow.AddDays(-150);
remoteEpisode2.Release.Size = 250.Megabytes();
remoteAlbum2.Release.PublishDate = DateTime.UtcNow.AddDays(-150);
remoteAlbum2.Release.Size = 250.Megabytes();
var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteEpisode1));
decisions.Add(new DownloadDecision(remoteEpisode2));
decisions.Add(new DownloadDecision(remoteAlbum1));
decisions.Add(new DownloadDecision(remoteAlbum2));
var qualifiedReports = Subject.PrioritizeDecisions(decisions);
qualifiedReports.First().RemoteEpisode.Release.Should().Be(remoteEpisode1.Release);
qualifiedReports.First().RemoteAlbum.Release.Should().Be(remoteAlbum1.Release);
}
[Test]
public void should_prefer_quality_over_the_number_of_peers()
{
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.MP3_512));
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.MP3_192));
var remoteAlbum1 = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.MP3_512));
var remoteAlbum2 = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.MP3_192));
var torrentInfo1 = new TorrentInfo();
torrentInfo1.PublishDate = DateTime.Now;
@ -398,15 +336,15 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
torrentInfo2.Peers = 10;
torrentInfo1.Size = 250.Megabytes();
remoteEpisode1.Release = torrentInfo1;
remoteEpisode2.Release = torrentInfo2;
remoteAlbum1.Release = torrentInfo1;
remoteAlbum2.Release = torrentInfo2;
var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteEpisode1));
decisions.Add(new DownloadDecision(remoteEpisode2));
decisions.Add(new DownloadDecision(remoteAlbum1));
decisions.Add(new DownloadDecision(remoteAlbum2));
var qualifiedReports = Subject.PrioritizeDecisions(decisions);
((TorrentInfo)qualifiedReports.First().RemoteEpisode.Release).Should().Be(torrentInfo1);
((TorrentInfo)qualifiedReports.First().RemoteAlbum.Release).Should().Be(torrentInfo1);
}
}
}

@ -7,22 +7,22 @@ using NzbDrone.Core.Indexers;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Profiles.Delay;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Music;
namespace NzbDrone.Core.Test.DecisionEngineTests
{
[TestFixture]
public class ProtocolSpecificationFixture : CoreTest<ProtocolSpecification>
{
private RemoteEpisode _remoteEpisode;
private RemoteAlbum _remoteAlbum;
private DelayProfile _delayProfile;
[SetUp]
public void Setup()
{
_remoteEpisode = new RemoteEpisode();
_remoteEpisode.Release = new ReleaseInfo();
_remoteEpisode.Series = new Series();
_remoteAlbum = new RemoteAlbum();
_remoteAlbum.Release = new ReleaseInfo();
_remoteAlbum.Artist = new Artist();
_delayProfile = new DelayProfile();
@ -33,7 +33,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
private void GivenProtocol(DownloadProtocol downloadProtocol)
{
_remoteEpisode.Release.DownloadProtocol = downloadProtocol;
_remoteAlbum.Release.DownloadProtocol = downloadProtocol;
}
[Test]
@ -42,7 +42,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
GivenProtocol(DownloadProtocol.Usenet);
_delayProfile.EnableUsenet = true;
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().Be(true);
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().Be(true);
}
[Test]
@ -51,7 +51,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
GivenProtocol(DownloadProtocol.Torrent);
_delayProfile.EnableTorrent = true;
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().Be(true);
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().Be(true);
}
[Test]
@ -60,7 +60,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
GivenProtocol(DownloadProtocol.Usenet);
_delayProfile.EnableUsenet = false;
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().Be(false);
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().Be(false);
}
[Test]
@ -69,7 +69,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
GivenProtocol(DownloadProtocol.Torrent);
_delayProfile.EnableTorrent = false;
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().Be(false);
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().Be(false);
}
}
}

@ -6,7 +6,7 @@ using NzbDrone.Core.DecisionEngine.Specifications;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Profiles;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Music;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.DecisionEngineTests
@ -15,7 +15,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
public class QualityAllowedByProfileSpecificationFixture : CoreTest<QualityAllowedByProfileSpecification>
{
private RemoteEpisode remoteEpisode;
private RemoteAlbum remoteAlbum;
public static object[] AllowedTestCases =
{
@ -26,41 +26,41 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
public static object[] DeniedTestCases =
{
new object[] { Quality.MP3_192 },
new object[] { Quality.MP3_320 },
new object[] { Quality.MP3_320 }
new object[] { Quality.MP3_VBR },
new object[] { Quality.FLAC },
new object[] { Quality.Unknown }
};
[SetUp]
public void Setup()
{
var fakeSeries = Builder<Series>.CreateNew()
var fakeArtist = Builder<Artist>.CreateNew()
.With(c => c.Profile = (LazyLoaded<Profile>)new Profile { Cutoff = Quality.MP3_512 })
.Build();
remoteEpisode = new RemoteEpisode
remoteAlbum = new RemoteAlbum
{
Series = fakeSeries,
ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.MP3_192, new Revision(version: 2)) },
Artist = fakeArtist,
ParsedAlbumInfo = new ParsedAlbumInfo { Quality = new QualityModel(Quality.MP3_192, new Revision(version: 2)) },
};
}
[Test, TestCaseSource(nameof(AllowedTestCases))]
public void should_allow_if_quality_is_defined_in_profile(Quality qualityType)
{
remoteEpisode.ParsedEpisodeInfo.Quality.Quality = qualityType;
remoteEpisode.Series.Profile.Value.Items = Qualities.QualityFixture.GetDefaultQualities(Quality.MP3_192, Quality.MP3_256, Quality.MP3_512);
remoteAlbum.ParsedAlbumInfo.Quality.Quality = qualityType;
remoteAlbum.Artist.Profile.Value.Items = Qualities.QualityFixture.GetDefaultQualities(Quality.MP3_192, Quality.MP3_256, Quality.MP3_512);
Subject.IsSatisfiedBy(remoteEpisode, null).Accepted.Should().BeTrue();
Subject.IsSatisfiedBy(remoteAlbum, null).Accepted.Should().BeTrue();
}
[Test, TestCaseSource(nameof(DeniedTestCases))]
public void should_not_allow_if_quality_is_not_defined_in_profile(Quality qualityType)
{
remoteEpisode.ParsedEpisodeInfo.Quality.Quality = qualityType;
remoteEpisode.Series.Profile.Value.Items = Qualities.QualityFixture.GetDefaultQualities(Quality.MP3_192, Quality.MP3_256, Quality.MP3_512);
remoteAlbum.ParsedAlbumInfo.Quality.Quality = qualityType;
remoteAlbum.Artist.Profile.Value.Items = Qualities.QualityFixture.GetDefaultQualities(Quality.MP3_192, Quality.MP3_256, Quality.MP3_512);
Subject.IsSatisfiedBy(remoteEpisode, null).Accepted.Should().BeFalse();
Subject.IsSatisfiedBy(remoteAlbum, null).Accepted.Should().BeFalse();
}
}
}

@ -9,7 +9,7 @@ using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Profiles;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.Queue;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Music;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.DecisionEngineTests
@ -17,41 +17,39 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
[TestFixture]
public class QueueSpecificationFixture : CoreTest<QueueSpecification>
{
private Series _series;
private Episode _episode;
private RemoteEpisode _remoteEpisode;
private Artist _artist;
private Album _album;
private RemoteAlbum _remoteAlbum;
private Series _otherSeries;
private Episode _otherEpisode;
private Artist _otherArtist;
private Album _otherAlbum;
[SetUp]
public void Setup()
{
Mocker.Resolve<QualityUpgradableSpecification>();
_series = Builder<Series>.CreateNew()
_artist = Builder<Artist>.CreateNew()
.With(e => e.Profile = new Profile { Items = Qualities.QualityFixture.GetDefaultQualities() })
.Build();
_episode = Builder<Episode>.CreateNew()
.With(e => e.SeriesId = _series.Id)
_album = Builder<Album>.CreateNew()
.With(e => e.ArtistId = _artist.Id)
.Build();
_otherSeries = Builder<Series>.CreateNew()
_otherArtist = Builder<Artist>.CreateNew()
.With(s => s.Id = 2)
.Build();
_otherEpisode = Builder<Episode>.CreateNew()
.With(e => e.SeriesId = _otherSeries.Id)
_otherAlbum = Builder<Album>.CreateNew()
.With(e => e.ArtistId = _otherArtist.Id)
.With(e => e.Id = 2)
.With(e => e.SeasonNumber = 2)
.With(e => e.EpisodeNumber = 2)
.Build();
_remoteEpisode = Builder<RemoteEpisode>.CreateNew()
.With(r => r.Series = _series)
.With(r => r.Episodes = new List<Episode> { _episode })
.With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.MP3_192) })
_remoteAlbum = Builder<RemoteAlbum>.CreateNew()
.With(r => r.Artist = _artist)
.With(r => r.Albums = new List<Album> { _album })
.With(r => r.ParsedAlbumInfo = new ParsedAlbumInfo { Quality = new QualityModel(Quality.MP3_192) })
.Build();
}
@ -62,11 +60,11 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
.Returns(new List<Queue.Queue>());
}
private void GivenQueue(IEnumerable<RemoteEpisode> remoteEpisodes)
private void GivenQueue(IEnumerable<RemoteAlbum> remoteAlbums)
{
var queue = remoteEpisodes.Select(remoteEpisode => new Queue.Queue
var queue = remoteAlbums.Select(remoteAlbum => new Queue.Queue
{
RemoteEpisode = remoteEpisode
RemoteAlbum = remoteAlbum
});
Mocker.GetMock<IQueueService>()
@ -78,181 +76,181 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
public void should_return_true_when_queue_is_empty()
{
GivenEmptyQueue();
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeTrue();
}
[Test]
public void should_return_true_when_series_doesnt_match()
{
var remoteEpisode = Builder<RemoteEpisode>.CreateNew()
.With(r => r.Series = _otherSeries)
.With(r => r.Episodes = new List<Episode> { _episode })
var remoteAlbum = Builder<RemoteAlbum>.CreateNew()
.With(r => r.Artist = _otherArtist)
.With(r => r.Albums = new List<Album> { _album })
.Build();
GivenQueue(new List<RemoteEpisode> { remoteEpisode });
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
GivenQueue(new List<RemoteAlbum> { remoteAlbum });
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeTrue();
}
[Test]
public void should_return_true_when_quality_in_queue_is_lower()
{
_series.Profile.Value.Cutoff = Quality.MP3_512;
_artist.Profile.Value.Cutoff = Quality.MP3_512;
var remoteEpisode = Builder<RemoteEpisode>.CreateNew()
.With(r => r.Series = _series)
.With(r => r.Episodes = new List<Episode> { _episode })
.With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
var remoteAlbum = Builder<RemoteAlbum>.CreateNew()
.With(r => r.Artist = _artist)
.With(r => r.Albums = new List<Album> { _album })
.With(r => r.ParsedAlbumInfo = new ParsedAlbumInfo
{
Quality = new QualityModel(Quality.MP3_192)
})
.Build();
GivenQueue(new List<RemoteEpisode> { remoteEpisode });
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
GivenQueue(new List<RemoteAlbum> { remoteAlbum });
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeTrue();
}
[Test]
public void should_return_true_when_episode_doesnt_match()
public void should_return_true_when_album_doesnt_match()
{
var remoteEpisode = Builder<RemoteEpisode>.CreateNew()
.With(r => r.Series = _series)
.With(r => r.Episodes = new List<Episode> { _otherEpisode })
.With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
var remoteAlbum = Builder<RemoteAlbum>.CreateNew()
.With(r => r.Artist = _artist)
.With(r => r.Albums = new List<Album> { _otherAlbum })
.With(r => r.ParsedAlbumInfo = new ParsedAlbumInfo
{
Quality = new QualityModel(Quality.MP3_192)
})
.Build();
GivenQueue(new List<RemoteEpisode> { remoteEpisode });
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
GivenQueue(new List<RemoteAlbum> { remoteAlbum });
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeTrue();
}
[Test]
public void should_return_false_when_qualities_are_the_same()
{
var remoteEpisode = Builder<RemoteEpisode>.CreateNew()
.With(r => r.Series = _series)
.With(r => r.Episodes = new List<Episode> { _episode })
.With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
var remoteAlbum = Builder<RemoteAlbum>.CreateNew()
.With(r => r.Artist = _artist)
.With(r => r.Albums = new List<Album> { _album })
.With(r => r.ParsedAlbumInfo = new ParsedAlbumInfo
{
Quality = new QualityModel(Quality.MP3_192)
})
.Build();
GivenQueue(new List<RemoteEpisode> { remoteEpisode });
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
GivenQueue(new List<RemoteAlbum> { remoteAlbum });
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeFalse();
}
[Test]
public void should_return_false_when_quality_in_queue_is_better()
{
_series.Profile.Value.Cutoff = Quality.MP3_512;
_artist.Profile.Value.Cutoff = Quality.MP3_512;
var remoteEpisode = Builder<RemoteEpisode>.CreateNew()
.With(r => r.Series = _series)
.With(r => r.Episodes = new List<Episode> { _episode })
.With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
var remoteAlbum = Builder<RemoteAlbum>.CreateNew()
.With(r => r.Artist = _artist)
.With(r => r.Albums = new List<Album> { _album })
.With(r => r.ParsedAlbumInfo = new ParsedAlbumInfo
{
Quality = new QualityModel(Quality.MP3_256)
})
.Build();
GivenQueue(new List<RemoteEpisode> { remoteEpisode });
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
GivenQueue(new List<RemoteAlbum> { remoteAlbum });
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeFalse();
}
[Test]
public void should_return_false_if_matching_multi_episode_is_in_queue()
public void should_return_false_if_matching_multi_album_is_in_queue()
{
var remoteEpisode = Builder<RemoteEpisode>.CreateNew()
.With(r => r.Series = _series)
.With(r => r.Episodes = new List<Episode> { _episode, _otherEpisode })
.With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
var remoteAlbum = Builder<RemoteAlbum>.CreateNew()
.With(r => r.Artist = _artist)
.With(r => r.Albums = new List<Album> { _album, _otherAlbum })
.With(r => r.ParsedAlbumInfo = new ParsedAlbumInfo
{
Quality = new QualityModel(Quality.MP3_256)
})
.Build();
GivenQueue(new List<RemoteEpisode> { remoteEpisode });
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
GivenQueue(new List<RemoteAlbum> { remoteAlbum });
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeFalse();
}
[Test]
public void should_return_false_if_multi_episode_has_one_episode_in_queue()
public void should_return_false_if_multi_album_has_one_album_in_queue()
{
var remoteEpisode = Builder<RemoteEpisode>.CreateNew()
.With(r => r.Series = _series)
.With(r => r.Episodes = new List<Episode> { _episode })
.With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
var remoteAlbum = Builder<RemoteAlbum>.CreateNew()
.With(r => r.Artist = _artist)
.With(r => r.Albums = new List<Album> { _album })
.With(r => r.ParsedAlbumInfo = new ParsedAlbumInfo
{
Quality = new QualityModel(Quality.MP3_256)
})
.Build();
_remoteEpisode.Episodes.Add(_otherEpisode);
_remoteAlbum.Albums.Add(_otherAlbum);
GivenQueue(new List<RemoteEpisode> { remoteEpisode });
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
GivenQueue(new List<RemoteAlbum> { remoteAlbum });
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeFalse();
}
[Test]
public void should_return_false_if_multi_part_episode_is_already_in_queue()
public void should_return_false_if_multi_part_album_is_already_in_queue()
{
var remoteEpisode = Builder<RemoteEpisode>.CreateNew()
.With(r => r.Series = _series)
.With(r => r.Episodes = new List<Episode> { _episode, _otherEpisode })
.With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
var remoteAlbum = Builder<RemoteAlbum>.CreateNew()
.With(r => r.Artist = _artist)
.With(r => r.Albums = new List<Album> { _album, _otherAlbum })
.With(r => r.ParsedAlbumInfo = new ParsedAlbumInfo
{
Quality = new QualityModel(Quality.MP3_256)
})
.Build();
_remoteEpisode.Episodes.Add(_otherEpisode);
_remoteAlbum.Albums.Add(_otherAlbum);
GivenQueue(new List<RemoteEpisode> { remoteEpisode });
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
GivenQueue(new List<RemoteAlbum> { remoteAlbum });
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeFalse();
}
[Test]
public void should_return_false_if_multi_part_episode_has_two_episodes_in_queue()
public void should_return_false_if_multi_part_album_has_two_episodes_in_queue()
{
var remoteEpisodes = Builder<RemoteEpisode>.CreateListOfSize(2)
var remoteAlbums = Builder<RemoteAlbum>.CreateListOfSize(2)
.All()
.With(r => r.Series = _series)
.With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
.With(r => r.Artist = _artist)
.With(r => r.ParsedAlbumInfo = new ParsedAlbumInfo
{
Quality =
new QualityModel(
Quality.MP3_256)
})
.TheFirst(1)
.With(r => r.Episodes = new List<Episode> { _episode })
.With(r => r.Albums = new List<Album> { _album })
.TheNext(1)
.With(r => r.Episodes = new List<Episode> { _otherEpisode })
.With(r => r.Albums = new List<Album> { _otherAlbum })
.Build();
_remoteEpisode.Episodes.Add(_otherEpisode);
GivenQueue(remoteEpisodes);
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
_remoteAlbum.Albums.Add(_otherAlbum);
GivenQueue(remoteAlbums);
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeFalse();
}
[Test]
public void should_return_false_if_quality_in_queue_meets_cutoff()
{
_series.Profile.Value.Cutoff = _remoteEpisode.ParsedEpisodeInfo.Quality.Quality;
_artist.Profile.Value.Cutoff = _remoteAlbum.ParsedAlbumInfo.Quality.Quality;
var remoteEpisode = Builder<RemoteEpisode>.CreateNew()
.With(r => r.Series = _series)
.With(r => r.Episodes = new List<Episode> { _episode })
.With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
var remoteAlbum = Builder<RemoteAlbum>.CreateNew()
.With(r => r.Artist = _artist)
.With(r => r.Albums = new List<Album> { _album })
.With(r => r.ParsedAlbumInfo = new ParsedAlbumInfo
{
Quality = new QualityModel(Quality.MP3_256)
})
.Build();
GivenQueue(new List<RemoteEpisode> { remoteEpisode });
GivenQueue(new List<RemoteAlbum> { remoteAlbum });
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeFalse();
}
}
}

@ -2,7 +2,6 @@
using NUnit.Framework;
using NzbDrone.Core.DecisionEngine.Specifications;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Indexers;
@ -12,12 +11,12 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
public class RawDiskSpecificationFixture : CoreTest<RawDiskSpecification>
{
private RemoteEpisode _remoteEpisode;
private RemoteAlbum _remoteAlbum;
[SetUp]
public void Setup()
{
_remoteEpisode = new RemoteEpisode
_remoteAlbum = new RemoteAlbum
{
Release = new ReleaseInfo() { DownloadProtocol = DownloadProtocol.Torrent }
};
@ -25,48 +24,41 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
private void WithContainer(string container)
{
_remoteEpisode.Release.Container = container;
_remoteAlbum.Release.Container = container;
}
[Test]
public void should_return_true_if_no_container_specified()
{
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeTrue();
}
[Test]
public void should_return_true_if_mkv()
public void should_return_true_if_flac()
{
WithContainer("MKV");
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
WithContainer("FLAC");
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeTrue();
}
[Test]
public void should_return_false_if_vob()
{
WithContainer("VOB");
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeFalse();
}
[Test]
public void should_return_false_if_iso()
{
WithContainer("ISO");
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
}
[Test]
public void should_return_false_if_m2ts()
{
WithContainer("M2TS");
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeFalse();
}
[Test]
public void should_compare_case_insensitive()
{
WithContainer("vob");
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeFalse();
}
}

@ -6,21 +6,21 @@ using NzbDrone.Core.DecisionEngine.Specifications;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Restrictions;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Music;
namespace NzbDrone.Core.Test.DecisionEngineTests
{
[TestFixture]
public class ReleaseRestrictionsSpecificationFixture : CoreTest<ReleaseRestrictionsSpecification>
{
private RemoteEpisode _remoteEpisode;
private RemoteAlbum _remoteAlbum;
[SetUp]
public void Setup()
{
_remoteEpisode = new RemoteEpisode
_remoteAlbum = new RemoteAlbum
{
Series = new Series
Artist = new Artist
{
Tags = new HashSet<int>()
},
@ -52,7 +52,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
.Setup(s => s.AllForTags(It.IsAny<HashSet<int>>()))
.Returns(new List<Restriction>());
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeTrue();
}
[Test]
@ -60,7 +60,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
{
GivenRestictions("WEBRip", null);
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeTrue();
}
[Test]
@ -68,7 +68,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
{
GivenRestictions("doesnt,exist", null);
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeFalse();
}
[Test]
@ -76,7 +76,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
{
GivenRestictions(null, "ignored");
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeTrue();
}
[Test]
@ -84,7 +84,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
{
GivenRestictions(null, "edited");
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeFalse();
}
[TestCase("EdiTED")]
@ -95,7 +95,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
{
GivenRestictions(required, null);
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeTrue();
}
[TestCase("EdiTED")]
@ -106,22 +106,22 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
{
GivenRestictions(null, ignored);
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeFalse();
}
[Test]
public void should_be_false_when_release_contains_one_restricted_word_and_one_required_word()
{
_remoteEpisode.Release.Title = "[ www.Speed.cd ] -Whose.Line.is.it.Anyway.US.S10E24.720p.HDTV.x264-BAJSKORV";
_remoteAlbum.Release.Title = "[ www.Speed.cd ] - Katy Perry - Witness (2017) MP3 [320 kbps] ";
Mocker.GetMock<IRestrictionService>()
.Setup(s => s.AllForTags(It.IsAny<HashSet<int>>()))
.Returns(new List<Restriction>
{
new Restriction { Required = "x264", Ignored = "www.Speed.cd" }
new Restriction { Required = "320", Ignored = "www.Speed.cd" }
});
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeFalse();
}
}
}

@ -13,12 +13,12 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
public class RetentionSpecificationFixture : CoreTest<RetentionSpecification>
{
private RemoteEpisode _remoteEpisode;
private RemoteAlbum _remoteAlbum;
[SetUp]
public void Setup()
{
_remoteEpisode = new RemoteEpisode
_remoteAlbum = new RemoteAlbum
{
Release = new ReleaseInfo() { DownloadProtocol = DownloadProtocol.Usenet }
};
@ -31,7 +31,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
private void WithAge(int days)
{
_remoteEpisode.Release.PublishDate = DateTime.UtcNow.AddDays(-days);
_remoteAlbum.Release.PublishDate = DateTime.UtcNow.AddDays(-days);
}
[Test]
@ -40,7 +40,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
WithRetention(0);
WithAge(100);
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeTrue();
}
[Test]
@ -49,7 +49,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
WithRetention(1000);
WithAge(100);
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeTrue();
}
[Test]
@ -58,7 +58,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
WithRetention(100);
WithAge(100);
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeTrue();
}
[Test]
@ -67,7 +67,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
WithRetention(10);
WithAge(100);
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeFalse();
}
[Test]
@ -76,18 +76,18 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
WithRetention(0);
WithAge(100);
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeTrue();
}
[Test]
public void should_return_true_when_release_is_not_usenet()
{
_remoteEpisode.Release.DownloadProtocol = DownloadProtocol.Torrent;
_remoteAlbum.Release.DownloadProtocol = DownloadProtocol.Torrent;
WithRetention(10);
WithAge(100);
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeTrue();
}
}
}

@ -17,7 +17,7 @@ using NzbDrone.Core.Profiles;
using NzbDrone.Core.Profiles.Delay;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Music;
namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
{
@ -26,7 +26,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
{
private Profile _profile;
private DelayProfile _delayProfile;
private RemoteEpisode _remoteEpisode;
private RemoteAlbum _remoteAlbum;
[SetUp]
public void Setup()
@ -38,12 +38,12 @@ namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
.With(d => d.PreferredProtocol = DownloadProtocol.Usenet)
.Build();
var series = Builder<Series>.CreateNew()
var artist = Builder<Artist>.CreateNew()
.With(s => s.Profile = _profile)
.Build();
_remoteEpisode = Builder<RemoteEpisode>.CreateNew()
.With(r => r.Series = series)
_remoteAlbum = Builder<RemoteAlbum>.CreateNew()
.With(r => r.Artist = artist)
.Build();
_profile.Items = new List<ProfileQualityItem>();
@ -53,30 +53,30 @@ namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
_profile.Cutoff = Quality.MP3_320;
_remoteEpisode.ParsedEpisodeInfo = new ParsedEpisodeInfo();
_remoteEpisode.Release = new ReleaseInfo();
_remoteEpisode.Release.DownloadProtocol = DownloadProtocol.Usenet;
_remoteAlbum.ParsedAlbumInfo = new ParsedAlbumInfo();
_remoteAlbum.Release = new ReleaseInfo();
_remoteAlbum.Release.DownloadProtocol = DownloadProtocol.Usenet;
_remoteEpisode.Episodes = Builder<Episode>.CreateListOfSize(1).Build().ToList();
_remoteEpisode.Episodes.First().EpisodeFileId = 0;
_remoteAlbum.Albums = Builder<Album>.CreateListOfSize(1).Build().ToList();
Mocker.GetMock<IMediaFileService>()
.Setup(s => s.GetFilesByAlbum(It.IsAny<int>(), It.IsAny<int>()))
.Returns(new List<TrackFile> {});
Mocker.GetMock<IDelayProfileService>()
.Setup(s => s.BestForTags(It.IsAny<HashSet<int>>()))
.Returns(_delayProfile);
Mocker.GetMock<IPendingReleaseService>()
.Setup(s => s.GetPendingRemoteEpisodes(It.IsAny<int>()))
.Returns(new List<RemoteEpisode>());
.Setup(s => s.GetPendingRemoteAlbums(It.IsAny<int>()))
.Returns(new List<RemoteAlbum>());
}
private void GivenExistingFile(QualityModel quality)
{
_remoteEpisode.Episodes.First().EpisodeFileId = 1;
_remoteEpisode.Episodes.First().EpisodeFile = new LazyLoaded<EpisodeFile>(new EpisodeFile
{
Quality = quality
});
Mocker.GetMock<IMediaFileService>()
.Setup(s => s.GetFilesByAlbum(It.IsAny<int>(), It.IsAny<int>()))
.Returns(new List<TrackFile> { new TrackFile { Quality = quality } });
}
private void GivenUpgradeForExistingFile()
@ -89,18 +89,18 @@ namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
[Test]
public void should_be_true_when_user_invoked_search()
{
Subject.IsSatisfiedBy(new RemoteEpisode(), new SingleEpisodeSearchCriteria { UserInvokedSearch = true }).Accepted.Should().BeTrue();
Subject.IsSatisfiedBy(new RemoteAlbum(), new AlbumSearchCriteria { UserInvokedSearch = true }).Accepted.Should().BeTrue();
}
[Test]
public void should_be_false_when_system_invoked_search_and_release_is_younger_than_delay()
{
_remoteEpisode.ParsedEpisodeInfo.Quality = new QualityModel(Quality.MP3_192);
_remoteEpisode.Release.PublishDate = DateTime.UtcNow;
_remoteAlbum.ParsedAlbumInfo.Quality = new QualityModel(Quality.MP3_192);
_remoteAlbum.Release.PublishDate = DateTime.UtcNow;
_delayProfile.UsenetDelay = 720;
Subject.IsSatisfiedBy(_remoteEpisode, new SingleEpisodeSearchCriteria()).Accepted.Should().BeFalse();
Subject.IsSatisfiedBy(_remoteAlbum, new AlbumSearchCriteria()).Accepted.Should().BeFalse();
}
[Test]
@ -108,44 +108,44 @@ namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
{
_delayProfile.UsenetDelay = 0;
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeTrue();
}
[Test]
public void should_be_true_when_quality_is_last_allowed_in_profile()
{
_remoteEpisode.ParsedEpisodeInfo.Quality = new QualityModel(Quality.MP3_320);
_remoteAlbum.ParsedAlbumInfo.Quality = new QualityModel(Quality.MP3_320);
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeTrue();
}
[Test]
public void should_be_true_when_release_is_older_than_delay()
{
_remoteEpisode.ParsedEpisodeInfo.Quality = new QualityModel(Quality.MP3_256);
_remoteEpisode.Release.PublishDate = DateTime.UtcNow.AddHours(-10);
_remoteAlbum.ParsedAlbumInfo.Quality = new QualityModel(Quality.MP3_256);
_remoteAlbum.Release.PublishDate = DateTime.UtcNow.AddHours(-10);
_delayProfile.UsenetDelay = 60;
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeTrue();
}
[Test]
public void should_be_false_when_release_is_younger_than_delay()
{
_remoteEpisode.ParsedEpisodeInfo.Quality = new QualityModel(Quality.MP3_192);
_remoteEpisode.Release.PublishDate = DateTime.UtcNow;
_remoteAlbum.ParsedAlbumInfo.Quality = new QualityModel(Quality.MP3_192);
_remoteAlbum.Release.PublishDate = DateTime.UtcNow;
_delayProfile.UsenetDelay = 720;
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeFalse();
}
[Test]
public void should_be_true_when_release_is_a_proper_for_existing_episode()
public void should_be_true_when_release_is_a_proper_for_existing_album()
{
_remoteEpisode.ParsedEpisodeInfo.Quality = new QualityModel(Quality.MP3_256, new Revision(version: 2));
_remoteEpisode.Release.PublishDate = DateTime.UtcNow;
_remoteAlbum.ParsedAlbumInfo.Quality = new QualityModel(Quality.MP3_256, new Revision(version: 2));
_remoteAlbum.Release.PublishDate = DateTime.UtcNow;
GivenExistingFile(new QualityModel(Quality.MP3_256));
GivenUpgradeForExistingFile();
@ -156,14 +156,14 @@ namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
_delayProfile.UsenetDelay = 720;
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeTrue();
}
[Test]
public void should_be_true_when_release_is_a_real_for_existing_episode()
public void should_be_true_when_release_is_a_real_for_existing_album()
{
_remoteEpisode.ParsedEpisodeInfo.Quality = new QualityModel(Quality.MP3_256, new Revision(real: 1));
_remoteEpisode.Release.PublishDate = DateTime.UtcNow;
_remoteAlbum.ParsedAlbumInfo.Quality = new QualityModel(Quality.MP3_256, new Revision(real: 1));
_remoteAlbum.Release.PublishDate = DateTime.UtcNow;
GivenExistingFile(new QualityModel(Quality.MP3_256));
GivenUpgradeForExistingFile();
@ -174,20 +174,20 @@ namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
_delayProfile.UsenetDelay = 720;
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeTrue();
}
[Test]
public void should_be_false_when_release_is_proper_for_existing_episode_of_different_quality()
public void should_be_false_when_release_is_proper_for_existing_album_of_different_quality()
{
_remoteEpisode.ParsedEpisodeInfo.Quality = new QualityModel(Quality.MP3_256, new Revision(version: 2));
_remoteEpisode.Release.PublishDate = DateTime.UtcNow;
_remoteAlbum.ParsedAlbumInfo.Quality = new QualityModel(Quality.MP3_256, new Revision(version: 2));
_remoteAlbum.Release.PublishDate = DateTime.UtcNow;
GivenExistingFile(new QualityModel(Quality.MP3_192));
_delayProfile.UsenetDelay = 720;
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeFalse();
}
}
}

@ -3,6 +3,7 @@ using System.Collections.Generic;
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using Moq;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.DecisionEngine.Specifications.RssSync;
using NzbDrone.Core.IndexerSearch.Definitions;
@ -10,7 +11,7 @@ using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Profiles;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Music;
using NzbDrone.Core.DecisionEngine;
using NzbDrone.Core.Test.Framework;
@ -21,38 +22,43 @@ namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
public class ProperSpecificationFixture : CoreTest<ProperSpecification>
{
private RemoteEpisode _parseResultMulti;
private RemoteEpisode _parseResultSingle;
private EpisodeFile _firstFile;
private EpisodeFile _secondFile;
private RemoteAlbum _parseResultMulti;
private RemoteAlbum _parseResultSingle;
private TrackFile _firstFile;
private TrackFile _secondFile;
[SetUp]
public void Setup()
{
Mocker.Resolve<QualityUpgradableSpecification>();
_firstFile = new EpisodeFile { Quality = new QualityModel(Quality.MP3_512, new Revision(version: 1)), DateAdded = DateTime.Now };
_secondFile = new EpisodeFile { Quality = new QualityModel(Quality.MP3_512, new Revision(version: 1)), DateAdded = DateTime.Now };
_firstFile = new TrackFile { Quality = new QualityModel(Quality.FLAC, new Revision(version: 1)), DateAdded = DateTime.Now };
_secondFile = new TrackFile { Quality = new QualityModel(Quality.FLAC, new Revision(version: 1)), DateAdded = DateTime.Now };
var singleEpisodeList = new List<Episode> { new Episode { EpisodeFile = _firstFile, EpisodeFileId = 1 }, new Episode { EpisodeFile = null } };
var doubleEpisodeList = new List<Episode> { new Episode { EpisodeFile = _firstFile, EpisodeFileId = 1 }, new Episode { EpisodeFile = _secondFile, EpisodeFileId = 1 }, new Episode { EpisodeFile = null } };
var singleEpisodeList = new List<Album> { new Album {}, new Album {} };
var doubleEpisodeList = new List<Album> { new Album {}, new Album {}, new Album {} };
var fakeSeries = Builder<Series>.CreateNew()
.With(c => c.Profile = new Profile { Cutoff = Quality.MP3_512 })
var fakeArtist = Builder<Artist>.CreateNew()
.With(c => c.Profile = new Profile { Cutoff = Quality.FLAC })
.Build();
_parseResultMulti = new RemoteEpisode
Mocker.GetMock<IMediaFileService>()
.Setup(c => c.GetFilesByAlbum(It.IsAny<int>(), It.IsAny<int>()))
.Returns(new List<TrackFile> { _firstFile, _secondFile });
_parseResultMulti = new RemoteAlbum
{
Series = fakeSeries,
ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.MP3_192, new Revision(version: 2)) },
Episodes = doubleEpisodeList
Artist = fakeArtist,
ParsedAlbumInfo = new ParsedAlbumInfo { Quality = new QualityModel(Quality.MP3_256, new Revision(version: 2)) },
Albums = doubleEpisodeList
};
_parseResultSingle = new RemoteEpisode
_parseResultSingle = new RemoteAlbum
{
Series = fakeSeries,
ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.MP3_192, new Revision(version: 2)) },
Episodes = singleEpisodeList
Artist = fakeArtist,
ParsedAlbumInfo = new ParsedAlbumInfo { Quality = new QualityModel(Quality.MP3_256, new Revision(version: 2)) },
Albums = singleEpisodeList
};
}
@ -69,36 +75,36 @@ namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
}
[Test]
public void should_return_false_when_episodeFile_was_added_more_than_7_days_ago()
public void should_return_false_when_trackFile_was_added_more_than_7_days_ago()
{
_firstFile.Quality.Quality = Quality.MP3_192;
_firstFile.Quality.Quality = Quality.MP3_256;
_firstFile.DateAdded = DateTime.Today.AddDays(-30);
Subject.IsSatisfiedBy(_parseResultSingle, null).Accepted.Should().BeFalse();
}
[Test]
public void should_return_false_when_first_episodeFile_was_added_more_than_7_days_ago()
public void should_return_false_when_first_trackFile_was_added_more_than_7_days_ago()
{
_firstFile.Quality.Quality = Quality.MP3_192;
_secondFile.Quality.Quality = Quality.MP3_192;
_firstFile.Quality.Quality = Quality.MP3_256;
_secondFile.Quality.Quality = Quality.MP3_256;
_firstFile.DateAdded = DateTime.Today.AddDays(-30);
Subject.IsSatisfiedBy(_parseResultMulti, null).Accepted.Should().BeFalse();
}
[Test]
public void should_return_false_when_second_episodeFile_was_added_more_than_7_days_ago()
public void should_return_false_when_second_trackFile_was_added_more_than_7_days_ago()
{
_firstFile.Quality.Quality = Quality.MP3_192;
_secondFile.Quality.Quality = Quality.MP3_192;
_firstFile.Quality.Quality = Quality.MP3_256;
_secondFile.Quality.Quality = Quality.MP3_256;
_secondFile.DateAdded = DateTime.Today.AddDays(-30);
Subject.IsSatisfiedBy(_parseResultMulti, null).Accepted.Should().BeFalse();
}
[Test]
public void should_return_true_when_episodeFile_was_added_more_than_7_days_ago_but_proper_is_for_better_quality()
public void should_return_true_when_trackFile_was_added_more_than_7_days_ago_but_proper_is_for_better_quality()
{
WithFirstFileUpgradable();
@ -107,7 +113,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
}
[Test]
public void should_return_true_when_episodeFile_was_added_more_than_7_days_ago_but_is_for_search()
public void should_return_true_when_trackFile_was_added_more_than_7_days_ago_but_is_for_search()
{
WithFirstFileUpgradable();
@ -118,18 +124,18 @@ namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
[Test]
public void should_return_false_when_proper_but_auto_download_propers_is_false()
{
_firstFile.Quality.Quality = Quality.MP3_192;
_firstFile.Quality.Quality = Quality.MP3_256;
_firstFile.DateAdded = DateTime.Today;
Subject.IsSatisfiedBy(_parseResultSingle, null).Accepted.Should().BeFalse();
}
[Test]
public void should_return_true_when_episodeFile_was_added_today()
public void should_return_true_when_trackFile_was_added_today()
{
GivenAutoDownloadPropers();
_firstFile.Quality.Quality = Quality.MP3_192;
_firstFile.Quality.Quality = Quality.MP3_256;
_firstFile.DateAdded = DateTime.Today;
Subject.IsSatisfiedBy(_parseResultSingle, null).Accepted.Should().BeTrue();

@ -0,0 +1,46 @@
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.DecisionEngine.Specifications.Search;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Music;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.DecisionEngineTests.Search
{
[TestFixture]
public class ArtistSpecificationFixture : TestBase<ArtistSpecification>
{
private Artist _artist1;
private Artist _artist2;
private RemoteAlbum _remoteAlbum = new RemoteAlbum();
private SearchCriteriaBase _searchCriteria = new AlbumSearchCriteria();
[SetUp]
public void Setup()
{
_artist1 = Builder<Artist>.CreateNew().With(s => s.Id = 1).Build();
_artist2 = Builder<Artist>.CreateNew().With(s => s.Id = 2).Build();
_remoteAlbum.Artist = _artist1;
}
[Test]
public void should_return_false_if_artist_doesnt_match()
{
_searchCriteria.Artist = _artist2;
Subject.IsSatisfiedBy(_remoteAlbum, _searchCriteria).Accepted.Should().BeFalse();
}
[Test]
public void should_return_true_when_artist_ids_match()
{
_searchCriteria.Artist = _artist1;
Subject.IsSatisfiedBy(_remoteAlbum, _searchCriteria).Accepted.Should().BeTrue();
}
}
}

@ -1,45 +0,0 @@
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.DecisionEngine.Specifications.Search;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Tv;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.DecisionEngineTests.Search
{
[TestFixture]
public class SeriesSpecificationFixture : TestBase<SeriesSpecification>
{
private Series _series1;
private Series _series2;
private RemoteEpisode _remoteEpisode = new RemoteEpisode();
private SearchCriteriaBase _searchCriteria = new SingleEpisodeSearchCriteria();
[SetUp]
public void Setup()
{
_series1 = Builder<Series>.CreateNew().With(s => s.Id = 1).Build();
_series2 = Builder<Series>.CreateNew().With(s => s.Id = 2).Build();
_remoteEpisode.Series = _series1;
}
[Test]
public void should_return_false_if_series_doesnt_match()
{
_searchCriteria.Series = _series2;
Subject.IsSatisfiedBy(_remoteEpisode, _searchCriteria).Accepted.Should().BeFalse();
}
[Test]
public void should_return_true_when_series_ids_match()
{
_searchCriteria.Series = _series1;
Subject.IsSatisfiedBy(_remoteEpisode, _searchCriteria).Accepted.Should().BeTrue();
}
}
}

@ -3,14 +3,14 @@ using System.Collections.Generic;
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using Moq;
using NzbDrone.Core.DecisionEngine.Specifications;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Profiles;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Music;
using NzbDrone.Core.DecisionEngine;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.DecisionEngineTests
@ -19,42 +19,44 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
public class UpgradeDiskSpecificationFixture : CoreTest<UpgradeDiskSpecification>
{
private UpgradeDiskSpecification _upgradeDisk;
private RemoteEpisode _parseResultMulti;
private RemoteEpisode _parseResultSingle;
private EpisodeFile _firstFile;
private EpisodeFile _secondFile;
private RemoteAlbum _parseResultMulti;
private RemoteAlbum _parseResultSingle;
private TrackFile _firstFile;
private TrackFile _secondFile;
[SetUp]
public void Setup()
{
Mocker.Resolve<QualityUpgradableSpecification>();
_upgradeDisk = Mocker.Resolve<UpgradeDiskSpecification>();
_firstFile = new EpisodeFile { Quality = new QualityModel(Quality.MP3_512, new Revision(version: 2)), DateAdded = DateTime.Now };
_secondFile = new EpisodeFile { Quality = new QualityModel(Quality.MP3_512, new Revision(version: 2)), DateAdded = DateTime.Now };
_firstFile = new TrackFile { Quality = new QualityModel(Quality.FLAC, new Revision(version: 2)), DateAdded = DateTime.Now };
_secondFile = new TrackFile { Quality = new QualityModel(Quality.FLAC, new Revision(version: 2)), DateAdded = DateTime.Now };
var singleEpisodeList = new List<Episode> { new Episode { EpisodeFile = _firstFile, EpisodeFileId = 1 }, new Episode { EpisodeFile = null } };
var doubleEpisodeList = new List<Episode> { new Episode { EpisodeFile = _firstFile, EpisodeFileId = 1 }, new Episode { EpisodeFile = _secondFile, EpisodeFileId = 1 }, new Episode { EpisodeFile = null } };
var singleEpisodeList = new List<Album> { new Album {}};
var doubleEpisodeList = new List<Album> { new Album {}, new Album {}, new Album {} };
var fakeSeries = Builder<Series>.CreateNew()
var fakeArtist = Builder<Artist>.CreateNew()
.With(c => c.Profile = new Profile { Cutoff = Quality.MP3_512, Items = Qualities.QualityFixture.GetDefaultQualities() })
.Build();
_parseResultMulti = new RemoteEpisode
Mocker.GetMock<IMediaFileService>()
.Setup(c => c.GetFilesByAlbum(It.IsAny<int>(), It.IsAny<int>()))
.Returns(new List<TrackFile> { _firstFile, _secondFile });
_parseResultMulti = new RemoteAlbum
{
Series = fakeSeries,
ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.MP3_192, new Revision(version: 2)) },
Episodes = doubleEpisodeList
Artist = fakeArtist,
ParsedAlbumInfo = new ParsedAlbumInfo { Quality = new QualityModel(Quality.MP3_256, new Revision(version: 2)) },
Albums = doubleEpisodeList
};
_parseResultSingle = new RemoteEpisode
_parseResultSingle = new RemoteAlbum
{
Series = fakeSeries,
ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.MP3_192, new Revision(version: 2)) },
Episodes = singleEpisodeList
Artist = fakeArtist,
ParsedAlbumInfo = new ParsedAlbumInfo { Quality = new QualityModel(Quality.MP3_256, new Revision(version: 2)) },
Albums = singleEpisodeList
};
}
private void WithFirstFileUpgradable()
@ -68,61 +70,42 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
}
[Test]
public void should_return_true_if_episode_has_no_existing_file()
public void should_return_true_if_album_has_no_existing_file()
{
_parseResultSingle.Episodes.ForEach(c => c.EpisodeFileId = 0);
_upgradeDisk.IsSatisfiedBy(_parseResultSingle, null).Accepted.Should().BeTrue();
}
Mocker.GetMock<IMediaFileService>()
.Setup(c => c.GetFilesByAlbum(It.IsAny<int>(), It.IsAny<int>()))
.Returns(new List<TrackFile> { });
[Test]
public void should_return_true_if_single_episode_doesnt_exist_on_disk()
{
_parseResultSingle.Episodes = new List<Episode>();
_upgradeDisk.IsSatisfiedBy(_parseResultSingle, null).Accepted.Should().BeTrue();
Subject.IsSatisfiedBy(_parseResultSingle, null).Accepted.Should().BeTrue();
}
[Test]
public void should_be_upgradable_if_only_episode_is_upgradable()
public void should_return_true_if_single_album_doesnt_exist_on_disk()
{
WithFirstFileUpgradable();
_upgradeDisk.IsSatisfiedBy(_parseResultSingle, null).Accepted.Should().BeTrue();
}
_parseResultSingle.Albums = new List<Album>();
[Test]
public void should_be_upgradable_if_both_episodes_are_upgradable()
{
WithFirstFileUpgradable();
WithSecondFileUpgradable();
_upgradeDisk.IsSatisfiedBy(_parseResultMulti, null).Accepted.Should().BeTrue();
}
[Test]
public void should_be_not_upgradable_if_both_episodes_are_not_upgradable()
{
_upgradeDisk.IsSatisfiedBy(_parseResultMulti, null).Accepted.Should().BeFalse();
Subject.IsSatisfiedBy(_parseResultSingle, null).Accepted.Should().BeTrue();
}
[Test]
public void should_be_not_upgradable_if_only_first_episodes_is_upgradable()
public void should_be_upgradable_if_album_is_upgradable()
{
WithFirstFileUpgradable();
_upgradeDisk.IsSatisfiedBy(_parseResultMulti, null).Accepted.Should().BeFalse();
Subject.IsSatisfiedBy(_parseResultSingle, null).Accepted.Should().BeTrue();
}
[Test]
public void should_be_not_upgradable_if_only_second_episodes_is_upgradable()
public void should_not_be_upgradable_if_qualities_are_the_same()
{
WithSecondFileUpgradable();
_upgradeDisk.IsSatisfiedBy(_parseResultMulti, null).Accepted.Should().BeFalse();
_firstFile.Quality = new QualityModel(Quality.MP3_512);
_parseResultSingle.ParsedAlbumInfo.Quality = new QualityModel(Quality.MP3_512);
Subject.IsSatisfiedBy(_parseResultSingle, null).Accepted.Should().BeFalse();
}
[Test]
public void should_not_be_upgradable_if_qualities_are_the_same()
public void should_not_be_upgradable_if_all_tracks_are_not_upgradable()
{
_firstFile.Quality = new QualityModel(Quality.MP3_512);
_parseResultSingle.ParsedEpisodeInfo.Quality = new QualityModel(Quality.MP3_512);
_upgradeDisk.IsSatisfiedBy(_parseResultSingle, null).Accepted.Should().BeFalse();
Subject.IsSatisfiedBy(_parseResultSingle, null).Accepted.Should().BeFalse();
}
}
}

@ -11,7 +11,7 @@ using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Profiles;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Music;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
@ -27,89 +27,88 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
.Returns<List<DownloadDecision>>(v => v);
}
private Episode GetEpisode(int id)
private Album GetAlbum(int id)
{
return Builder<Episode>.CreateNew()
return Builder<Album>.CreateNew()
.With(e => e.Id = id)
.With(e => e.EpisodeNumber = id)
.Build();
}
private RemoteEpisode GetRemoteEpisode(List<Episode> episodes, QualityModel quality)
private RemoteAlbum GetRemoteAlbum(List<Album> albums, QualityModel quality)
{
var remoteEpisode = new RemoteEpisode();
remoteEpisode.ParsedEpisodeInfo = new ParsedEpisodeInfo();
remoteEpisode.ParsedEpisodeInfo.Quality = quality;
var remoteAlbum = new RemoteAlbum();
remoteAlbum.ParsedAlbumInfo = new ParsedAlbumInfo();
remoteAlbum.ParsedAlbumInfo.Quality = quality;
remoteEpisode.Episodes = new List<Episode>();
remoteEpisode.Episodes.AddRange(episodes);
remoteAlbum.Albums = new List<Album>();
remoteAlbum.Albums.AddRange(albums);
remoteEpisode.Release = new ReleaseInfo();
remoteEpisode.Release.PublishDate = DateTime.UtcNow;
remoteAlbum.Release = new ReleaseInfo();
remoteAlbum.Release.PublishDate = DateTime.UtcNow;
remoteEpisode.Series = Builder<Series>.CreateNew()
remoteAlbum.Artist = Builder<Artist>.CreateNew()
.With(e => e.Profile = new Profile { Items = Qualities.QualityFixture.GetDefaultQualities() })
.Build();
return remoteEpisode;
return remoteAlbum;
}
[Test]
public void should_download_report_if_epsiode_was_not_already_downloaded()
public void should_download_report_if_album_was_not_already_downloaded()
{
var episodes = new List<Episode> { GetEpisode(1) };
var remoteEpisode = GetRemoteEpisode(episodes, new QualityModel(Quality.MP3_192));
var albums = new List<Album> { GetAlbum(1) };
var remoteEpisode = GetRemoteAlbum(albums, new QualityModel(Quality.MP3_192));
var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteEpisode));
Subject.ProcessDecisions(decisions);
Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.IsAny<RemoteEpisode>()), Times.Once());
Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.IsAny<RemoteAlbum>()), Times.Once());
}
[Test]
public void should_only_download_episode_once()
public void should_only_download_album_once()
{
var episodes = new List<Episode> { GetEpisode(1) };
var remoteEpisode = GetRemoteEpisode(episodes, new QualityModel(Quality.MP3_192));
var albums = new List<Album> { GetAlbum(1) };
var remoteAlbum = GetRemoteAlbum(albums, new QualityModel(Quality.MP3_192));
var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteEpisode));
decisions.Add(new DownloadDecision(remoteEpisode));
decisions.Add(new DownloadDecision(remoteAlbum));
decisions.Add(new DownloadDecision(remoteAlbum));
Subject.ProcessDecisions(decisions);
Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.IsAny<RemoteEpisode>()), Times.Once());
Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.IsAny<RemoteAlbum>()), Times.Once());
}
[Test]
public void should_not_download_if_any_episode_was_already_downloaded()
public void should_not_download_if_any_album_was_already_downloaded()
{
var remoteEpisode1 = GetRemoteEpisode(
new List<Episode> { GetEpisode(1) },
var remoteAlbum1 = GetRemoteAlbum(
new List<Album> { GetAlbum(1) },
new QualityModel(Quality.MP3_192)
);
var remoteEpisode2 = GetRemoteEpisode(
new List<Episode> { GetEpisode(1), GetEpisode(2) },
var remoteAlbum2 = GetRemoteAlbum(
new List<Album> { GetAlbum(1), GetAlbum(2) },
new QualityModel(Quality.MP3_192)
);
var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteEpisode1));
decisions.Add(new DownloadDecision(remoteEpisode2));
decisions.Add(new DownloadDecision(remoteAlbum1));
decisions.Add(new DownloadDecision(remoteAlbum2));
Subject.ProcessDecisions(decisions);
Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.IsAny<RemoteEpisode>()), Times.Once());
Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.IsAny<RemoteAlbum>()), Times.Once());
}
[Test]
public void should_return_downloaded_reports()
{
var episodes = new List<Episode> { GetEpisode(1) };
var remoteEpisode = GetRemoteEpisode(episodes, new QualityModel(Quality.MP3_192));
var albums = new List<Album> { GetAlbum(1) };
var remoteAlbum = GetRemoteAlbum(albums, new QualityModel(Quality.MP3_192));
var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteEpisode));
decisions.Add(new DownloadDecision(remoteAlbum));
Subject.ProcessDecisions(decisions).Grabbed.Should().HaveCount(1);
}
@ -117,19 +116,19 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
[Test]
public void should_return_all_downloaded_reports()
{
var remoteEpisode1 = GetRemoteEpisode(
new List<Episode> { GetEpisode(1) },
var remoteAlbum1 = GetRemoteAlbum(
new List<Album> { GetAlbum(1) },
new QualityModel(Quality.MP3_192)
);
var remoteEpisode2 = GetRemoteEpisode(
new List<Episode> { GetEpisode(2) },
var remoteAlbum2 = GetRemoteAlbum(
new List<Album> { GetAlbum(2) },
new QualityModel(Quality.MP3_192)
);
var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteEpisode1));
decisions.Add(new DownloadDecision(remoteEpisode2));
decisions.Add(new DownloadDecision(remoteAlbum1));
decisions.Add(new DownloadDecision(remoteAlbum2));
Subject.ProcessDecisions(decisions).Grabbed.Should().HaveCount(2);
}
@ -137,25 +136,25 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
[Test]
public void should_only_return_downloaded_reports()
{
var remoteEpisode1 = GetRemoteEpisode(
new List<Episode> { GetEpisode(1) },
var remoteAlbum1 = GetRemoteAlbum(
new List<Album> { GetAlbum(1) },
new QualityModel(Quality.MP3_192)
);
var remoteEpisode2 = GetRemoteEpisode(
new List<Episode> { GetEpisode(2) },
var remoteAlbum2 = GetRemoteAlbum(
new List<Album> { GetAlbum(2) },
new QualityModel(Quality.MP3_192)
);
var remoteEpisode3 = GetRemoteEpisode(
new List<Episode> { GetEpisode(2) },
var remoteAlbum3 = GetRemoteAlbum(
new List<Album> { GetAlbum(2) },
new QualityModel(Quality.MP3_192)
);
var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteEpisode1));
decisions.Add(new DownloadDecision(remoteEpisode2));
decisions.Add(new DownloadDecision(remoteEpisode3));
decisions.Add(new DownloadDecision(remoteAlbum1));
decisions.Add(new DownloadDecision(remoteAlbum2));
decisions.Add(new DownloadDecision(remoteAlbum3));
Subject.ProcessDecisions(decisions).Grabbed.Should().HaveCount(2);
}
@ -163,13 +162,13 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
[Test]
public void should_not_add_to_downloaded_list_when_download_fails()
{
var episodes = new List<Episode> { GetEpisode(1) };
var remoteEpisode = GetRemoteEpisode(episodes, new QualityModel(Quality.MP3_192));
var albums = new List<Album> { GetAlbum(1) };
var remoteAlbum = GetRemoteAlbum(albums, new QualityModel(Quality.MP3_192));
var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteEpisode));
decisions.Add(new DownloadDecision(remoteAlbum));
Mocker.GetMock<IDownloadService>().Setup(s => s.DownloadReport(It.IsAny<RemoteEpisode>())).Throws(new Exception());
Mocker.GetMock<IDownloadService>().Setup(s => s.DownloadReport(It.IsAny<RemoteAlbum>())).Throws(new Exception());
Subject.ProcessDecisions(decisions).Grabbed.Should().BeEmpty();
ExceptionVerification.ExpectedWarns(1);
}
@ -178,8 +177,8 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
public void should_return_an_empty_list_when_none_are_appproved()
{
var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(null, new Rejection("Failure!")));
decisions.Add(new DownloadDecision(null, new Rejection("Failure!")));
decisions.Add(new DownloadDecision(new RemoteAlbum(), new Rejection("Failure!")));
decisions.Add(new DownloadDecision(new RemoteAlbum(), new Rejection("Failure!")));
Subject.GetQualifiedReports(decisions).Should().BeEmpty();
}
@ -187,26 +186,26 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
[Test]
public void should_not_grab_if_pending()
{
var episodes = new List<Episode> { GetEpisode(1) };
var remoteEpisode = GetRemoteEpisode(episodes, new QualityModel(Quality.MP3_192));
var albums = new List<Album> { GetAlbum(1) };
var remoteAlbum = GetRemoteAlbum(albums, new QualityModel(Quality.MP3_192));
var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteEpisode, new Rejection("Failure!", RejectionType.Temporary)));
decisions.Add(new DownloadDecision(remoteEpisode));
decisions.Add(new DownloadDecision(remoteAlbum, new Rejection("Failure!", RejectionType.Temporary)));
decisions.Add(new DownloadDecision(remoteAlbum));
Subject.ProcessDecisions(decisions);
Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.IsAny<RemoteEpisode>()), Times.Never());
Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.IsAny<RemoteAlbum>()), Times.Never());
}
[Test]
public void should_not_add_to_pending_if_episode_was_grabbed()
public void should_not_add_to_pending_if_album_was_grabbed()
{
var episodes = new List<Episode> { GetEpisode(1) };
var remoteEpisode = GetRemoteEpisode(episodes, new QualityModel(Quality.MP3_192));
var albums = new List<Album> { GetAlbum(1) };
var remoteAlbum = GetRemoteAlbum(albums, new QualityModel(Quality.MP3_192));
var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteEpisode));
decisions.Add(new DownloadDecision(remoteEpisode, new Rejection("Failure!", RejectionType.Temporary)));
decisions.Add(new DownloadDecision(remoteAlbum));
decisions.Add(new DownloadDecision(remoteAlbum, new Rejection("Failure!", RejectionType.Temporary)));
Subject.ProcessDecisions(decisions);
Mocker.GetMock<IPendingReleaseService>().Verify(v => v.Add(It.IsAny<DownloadDecision>()), Times.Never());
@ -215,12 +214,12 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
[Test]
public void should_add_to_pending_even_if_already_added_to_pending()
{
var episodes = new List<Episode> { GetEpisode(1) };
var remoteEpisode = GetRemoteEpisode(episodes, new QualityModel(Quality.MP3_192));
var albums = new List<Album> { GetAlbum(1) };
var remoteAlbum = GetRemoteAlbum(albums, new QualityModel(Quality.MP3_192));
var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteEpisode, new Rejection("Failure!", RejectionType.Temporary)));
decisions.Add(new DownloadDecision(remoteEpisode, new Rejection("Failure!", RejectionType.Temporary)));
decisions.Add(new DownloadDecision(remoteAlbum, new Rejection("Failure!", RejectionType.Temporary)));
decisions.Add(new DownloadDecision(remoteAlbum, new Rejection("Failure!", RejectionType.Temporary)));
Subject.ProcessDecisions(decisions);
Mocker.GetMock<IPendingReleaseService>().Verify(v => v.Add(It.IsAny<DownloadDecision>()), Times.Exactly(2));

@ -1,4 +1,4 @@
using System;
using System;
using System.IO;
using System.Linq;
using FluentAssertions;
@ -16,7 +16,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.Blackhole
[TestFixture]
public class ScanWatchFolderFixture : CoreTest<ScanWatchFolder>
{
protected readonly string _title = "Droned.S01E01.Pilot.1080p.WEB-DL-DRONE";
protected readonly string _title = "Radiohead - Scotch Mist [2008-FLAC-Lossless]";
protected string _completedDownloadFolder = @"c:\blackhole\completed".AsOsAgnostic();
protected void GivenCompletedItem()
@ -28,7 +28,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.Blackhole
Mocker.GetMock<IDiskProvider>()
.Setup(c => c.GetFiles(targetDir, SearchOption.AllDirectories))
.Returns(new[] { Path.Combine(targetDir, "somefile.mkv") });
.Returns(new[] { Path.Combine(targetDir, "somefile.flac") });
Mocker.GetMock<IDiskProvider>()
.Setup(c => c.GetFileSize(It.IsAny<string>()))

@ -1,4 +1,4 @@
using System;
using System;
using System.IO;
using System.Linq;
using System.Net;
@ -67,26 +67,26 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.Blackhole
Mocker.GetMock<IDiskProvider>()
.Setup(c => c.GetFiles(targetDir, SearchOption.AllDirectories))
.Returns(new[] { Path.Combine(targetDir, "somefile.mkv") });
.Returns(new[] { Path.Combine(targetDir, "somefile.flac") });
Mocker.GetMock<IDiskProvider>()
.Setup(c => c.GetFileSize(It.IsAny<string>()))
.Returns(1000000);
}
protected override RemoteEpisode CreateRemoteEpisode()
protected override RemoteAlbum CreateRemoteAlbum()
{
var remoteEpisode = base.CreateRemoteEpisode();
var remoteAlbum = base.CreateRemoteAlbum();
var torrentInfo = new TorrentInfo();
torrentInfo.Title = remoteEpisode.Release.Title;
torrentInfo.DownloadUrl = remoteEpisode.Release.DownloadUrl;
torrentInfo.DownloadProtocol = remoteEpisode.Release.DownloadProtocol;
torrentInfo.MagnetUrl = "magnet:?xt=urn:btih:755248817d32b00cc853e633ecdc48e4c21bff15&dn=Series.S05E10.PROPER.HDTV.x264-DEFiNE%5Brartv%5D&tr=http%3A%2F%2Ftracker.trackerfix.com%3A80%2Fannounce&tr=udp%3A%2F%2F9.rarbg.me%3A2710&tr=udp%3A%2F%2F9.rarbg.to%3A2710";
torrentInfo.Title = remoteAlbum.Release.Title;
torrentInfo.DownloadUrl = remoteAlbum.Release.DownloadUrl;
torrentInfo.DownloadProtocol = remoteAlbum.Release.DownloadProtocol;
torrentInfo.MagnetUrl = "magnet:?xt=urn:btih:755248817d32b00cc853e633ecdc48e4c21bff15&dn=Artist.Album.FLAC.loseless-DEFiNE%5Brartv%5D&tr=http%3A%2F%2Ftracker.trackerfix.com%3A80%2Fannounce&tr=udp%3A%2F%2F9.rarbg.me%3A2710&tr=udp%3A%2F%2F9.rarbg.to%3A2710";
remoteEpisode.Release = torrentInfo;
remoteAlbum.Release = torrentInfo;
return remoteEpisode;
return remoteAlbum;
}
[Test]
@ -125,9 +125,9 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.Blackhole
[Test]
public void Download_should_download_file_if_it_doesnt_exist()
{
var remoteEpisode = CreateRemoteEpisode();
var remoteAlbum = CreateRemoteAlbum();
Subject.Download(remoteEpisode);
Subject.Download(remoteAlbum);
Mocker.GetMock<IHttpClient>().Verify(c => c.Get(It.Is<HttpRequest>(v => v.Url.FullUri == _downloadUrl)), Times.Once());
Mocker.GetMock<IDiskProvider>().Verify(c => c.OpenWriteStream(_filePath), Times.Once());
@ -139,10 +139,10 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.Blackhole
{
Subject.Definition.Settings.As<TorrentBlackholeSettings>().SaveMagnetFiles = true;
var remoteEpisode = CreateRemoteEpisode();
remoteEpisode.Release.DownloadUrl = null;
var remoteAlbum = CreateRemoteAlbum();
remoteAlbum.Release.DownloadUrl = null;
Subject.Download(remoteEpisode);
Subject.Download(remoteAlbum);
Mocker.GetMock<IHttpClient>().Verify(c => c.Get(It.Is<HttpRequest>(v => v.Url.FullUri == _downloadUrl)), Times.Never());
Mocker.GetMock<IDiskProvider>().Verify(c => c.OpenWriteStream(_filePath), Times.Never());
@ -153,10 +153,10 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.Blackhole
[Test]
public void Download_should_not_save_magnet_if_disabled()
{
var remoteEpisode = CreateRemoteEpisode();
remoteEpisode.Release.DownloadUrl = null;
var remoteAlbum = CreateRemoteAlbum();
remoteAlbum.Release.DownloadUrl = null;
Assert.Throws<ReleaseDownloadException>(() => Subject.Download(remoteEpisode));
Assert.Throws<ReleaseDownloadException>(() => Subject.Download(remoteAlbum));
Mocker.GetMock<IHttpClient>().Verify(c => c.Get(It.Is<HttpRequest>(v => v.Url.FullUri == _downloadUrl)), Times.Never());
Mocker.GetMock<IDiskProvider>().Verify(c => c.OpenWriteStream(_filePath), Times.Never());
@ -169,9 +169,9 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.Blackhole
{
Subject.Definition.Settings.As<TorrentBlackholeSettings>().SaveMagnetFiles = true;
var remoteEpisode = CreateRemoteEpisode();
var remoteAlbum = CreateRemoteAlbum();
Subject.Download(remoteEpisode);
Subject.Download(remoteAlbum);
Mocker.GetMock<IHttpClient>().Verify(c => c.Get(It.Is<HttpRequest>(v => v.Url.FullUri == _downloadUrl)), Times.Once());
Mocker.GetMock<IDiskProvider>().Verify(c => c.OpenWriteStream(_filePath), Times.Once());
@ -182,13 +182,13 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.Blackhole
[Test]
public void Download_should_replace_illegal_characters_in_title()
{
var illegalTitle = "Saturday Night Live - S38E08 - Jeremy Renner/Maroon 5 [SDTV]";
var expectedFilename = Path.Combine(_blackholeFolder, "Saturday Night Live - S38E08 - Jeremy Renner+Maroon 5 [SDTV]" + Path.GetExtension(_filePath));
var illegalTitle = "Radiohead - Scotch Mist [2008/FLAC/Lossless]";
var expectedFilename = Path.Combine(_blackholeFolder, "Radiohead - Scotch Mist [2008+FLAC+Lossless]" + Path.GetExtension(_filePath));
var remoteEpisode = CreateRemoteEpisode();
remoteEpisode.Release.Title = illegalTitle;
var remoteAlbum = CreateRemoteAlbum();
remoteAlbum.Release.Title = illegalTitle;
Subject.Download(remoteEpisode);
Subject.Download(remoteAlbum);
Mocker.GetMock<IHttpClient>().Verify(c => c.Get(It.Is<HttpRequest>(v => v.Url.FullUri == _downloadUrl)), Times.Once());
Mocker.GetMock<IDiskProvider>().Verify(c => c.OpenWriteStream(expectedFilename), Times.Once());
@ -198,10 +198,10 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.Blackhole
[Test]
public void Download_should_throw_if_magnet_and_torrent_url_does_not_exist()
{
var remoteEpisode = CreateRemoteEpisode();
remoteEpisode.Release.DownloadUrl = null;
var remoteAlbum = CreateRemoteAlbum();
remoteAlbum.Release.DownloadUrl = null;
Assert.Throws<ReleaseDownloadException>(() => Subject.Download(remoteEpisode));
Assert.Throws<ReleaseDownloadException>(() => Subject.Download(remoteAlbum));
}
[Test]
@ -273,9 +273,9 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.Blackhole
[Test]
public void should_return_null_hash()
{
var remoteEpisode = CreateRemoteEpisode();
var remoteAlbum = CreateRemoteAlbum();
Subject.Download(remoteEpisode).Should().BeNull();
Subject.Download(remoteAlbum).Should().BeNull();
}
}
}

@ -1,4 +1,4 @@

using System;
using System.IO;
using System.Linq;
@ -60,7 +60,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.Blackhole
Mocker.GetMock<IDiskProvider>()
.Setup(c => c.GetFiles(targetDir, SearchOption.AllDirectories))
.Returns(new[] { Path.Combine(targetDir, "somefile.mkv") });
.Returns(new[] { Path.Combine(targetDir, "somefile.flac") });
Mocker.GetMock<IDiskProvider>()
.Setup(c => c.GetFileSize(It.IsAny<string>()))
@ -104,7 +104,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.Blackhole
[Test]
public void Download_should_download_file_if_it_doesnt_exist()
{
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
Subject.Download(remoteEpisode);
@ -116,10 +116,10 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.Blackhole
[Test]
public void Download_should_replace_illegal_characters_in_title()
{
var illegalTitle = "Saturday Night Live - S38E08 - Jeremy Renner/Maroon 5 [SDTV]";
var expectedFilename = Path.Combine(_blackholeFolder, "Saturday Night Live - S38E08 - Jeremy Renner+Maroon 5 [SDTV]" + Path.GetExtension(_filePath));
var illegalTitle = "Radiohead - Scotch Mist [2008/FLAC/Lossless]";
var expectedFilename = Path.Combine(_blackholeFolder, "Radiohead - Scotch Mist [2008+FLAC+Lossless]" + Path.GetExtension(_filePath));
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
remoteEpisode.Release.Title = illegalTitle;
Subject.Download(remoteEpisode);

@ -1,4 +1,4 @@
using System;
using System;
using System.Linq;
using System.Collections.Generic;
using FluentAssertions;
@ -196,7 +196,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DelugeTests
{
GivenSuccessfulDownload();
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
var id = Subject.Download(remoteEpisode);
@ -208,7 +208,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DelugeTests
{
GivenSuccessfulDownload();
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
remoteEpisode.Release.DownloadUrl = magnetUrl;
var id = Subject.Download(remoteEpisode);

@ -9,6 +9,7 @@ using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Music;
using NzbDrone.Core.Download;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.RemotePathMappings;
@ -30,8 +31,8 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests
.Returns(30);
Mocker.GetMock<IParsingService>()
.Setup(s => s.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), (SearchCriteriaBase)null))
.Returns(() => CreateRemoteEpisode());
.Setup(s => s.Map(It.IsAny<ParsedAlbumInfo>(), (SearchCriteriaBase)null))
.Returns(() => CreateRemoteAlbum());
Mocker.GetMock<IHttpClient>()
.Setup(s => s.Get(It.IsAny<HttpRequest>()))
@ -42,22 +43,21 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests
.Returns<string, OsPath>((h, r) => r);
}
protected virtual RemoteEpisode CreateRemoteEpisode()
protected virtual RemoteAlbum CreateRemoteAlbum()
{
var remoteEpisode = new RemoteEpisode();
remoteEpisode.Release = new ReleaseInfo();
remoteEpisode.Release.Title = _title;
remoteEpisode.Release.DownloadUrl = _downloadUrl;
remoteEpisode.Release.DownloadProtocol = Subject.Protocol;
var remoteAlbum = new RemoteAlbum();
remoteAlbum.Release = new ReleaseInfo();
remoteAlbum.Release.Title = _title;
remoteAlbum.Release.DownloadUrl = _downloadUrl;
remoteAlbum.Release.DownloadProtocol = Subject.Protocol;
remoteEpisode.ParsedEpisodeInfo = new ParsedEpisodeInfo();
remoteEpisode.ParsedEpisodeInfo.FullSeason = false;
remoteAlbum.ParsedAlbumInfo = new ParsedAlbumInfo();
remoteEpisode.Episodes = new List<Episode>();
remoteAlbum.Albums = new List<Album>();
remoteEpisode.Series = new Series();
remoteAlbum.Artist = new Artist();
return remoteEpisode;
return remoteAlbum;
}
protected void VerifyIdentifiable(DownloadClientItem downloadClientItem)

@ -33,7 +33,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
protected string _serialNumber = "SERIALNUMBER";
protected string _category ="lidarr";
protected string _tvDirectory = @"video/Series";
protected string _musicDirectory = @"music/Artist";
protected string _defaultDestination = "somepath";
protected OsPath _physicalPath = new OsPath("/mnt/sdb1/mydata");
@ -301,7 +301,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
protected void GivenTvDirectory()
{
_settings.TvDirectory = _tvDirectory;
_settings.TvDirectory = _musicDirectory;
}
protected virtual void GivenTasks(List<DownloadStationTask> torrents)
@ -339,13 +339,13 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
.Callback(PrepareClientToReturnQueuedItem);
}
protected override RemoteEpisode CreateRemoteEpisode()
protected override RemoteAlbum CreateRemoteAlbum()
{
var episode = base.CreateRemoteEpisode();
var album = base.CreateRemoteAlbum();
episode.Release.DownloadUrl = DownloadURL;
album.Release.DownloadUrl = DownloadURL;
return episode;
return album;
}
protected int GivenAllKindOfTasks()
@ -366,14 +366,14 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
GivenTvDirectory();
GivenSuccessfulDownload();
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
var id = Subject.Download(remoteEpisode);
id.Should().NotBeNullOrEmpty();
Mocker.GetMock<IDownloadStationTaskProxy>()
.Verify(v => v.AddTaskFromUrl(It.IsAny<string>(), _tvDirectory, It.IsAny<DownloadStationSettings>()), Times.Once());
.Verify(v => v.AddTaskFromUrl(It.IsAny<string>(), _musicDirectory, It.IsAny<DownloadStationSettings>()), Times.Once());
}
[Test]
@ -383,7 +383,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
GivenTvCategory();
GivenSuccessfulDownload();
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
var id = Subject.Download(remoteEpisode);
@ -399,7 +399,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
GivenSerialNumber();
GivenSuccessfulDownload();
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
var id = Subject.Download(remoteEpisode);
@ -474,7 +474,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
[Test]
public void Download_should_throw_and_not_add_task_if_cannot_get_serial_number()
{
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
Mocker.GetMock<ISerialNumberProvider>()
.Setup(s => s.GetSerialNumber(_settings))

@ -29,18 +29,18 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
protected string _serialNumber = "SERIALNUMBER";
protected string _category = "lidarr";
protected string _tvDirectory = @"video/Series";
protected string _musicDirectory = @"music/Artist";
protected string _defaultDestination = "somepath";
protected OsPath _physicalPath = new OsPath("/mnt/sdb1/mydata");
protected RemoteEpisode _remoteEpisode;
protected RemoteAlbum _remoteAlbum;
protected Dictionary<string, object> _downloadStationConfigItems;
[SetUp]
public void Setup()
{
_remoteEpisode = CreateRemoteEpisode();
_remoteAlbum = CreateRemoteAlbum();
_settings = new DownloadStationSettings()
{
@ -66,7 +66,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
Detail = new Dictionary<string, string>
{
{ "destination","shared/folder" },
{ "uri", FileNameBuilder.CleanFileName(_remoteEpisode.Release.Title) + ".nzb" }
{ "uri", FileNameBuilder.CleanFileName(_remoteAlbum.Release.Title) + ".nzb" }
},
Transfer = new Dictionary<string, string>
{
@ -89,7 +89,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
Detail = new Dictionary<string, string>
{
{ "destination","shared/folder" },
{ "uri", FileNameBuilder.CleanFileName(_remoteEpisode.Release.Title) + ".nzb" }
{ "uri", FileNameBuilder.CleanFileName(_remoteAlbum.Release.Title) + ".nzb" }
},
Transfer = new Dictionary<string, string>
{
@ -112,7 +112,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
Detail = new Dictionary<string, string>
{
{ "destination","shared/folder" },
{ "uri", FileNameBuilder.CleanFileName(_remoteEpisode.Release.Title) + ".nzb" }
{ "uri", FileNameBuilder.CleanFileName(_remoteAlbum.Release.Title) + ".nzb" }
},
Transfer = new Dictionary<string, string>
{
@ -135,7 +135,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
Detail = new Dictionary<string, string>
{
{ "destination","shared/folder" },
{ "uri", FileNameBuilder.CleanFileName(_remoteEpisode.Release.Title) + ".nzb" }
{ "uri", FileNameBuilder.CleanFileName(_remoteAlbum.Release.Title) + ".nzb" }
},
Transfer = new Dictionary<string, string>
{
@ -158,7 +158,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
Detail = new Dictionary<string, string>
{
{ "destination","shared/folder" },
{ "uri", FileNameBuilder.CleanFileName(_remoteEpisode.Release.Title) + ".nzb" }
{ "uri", FileNameBuilder.CleanFileName(_remoteAlbum.Release.Title) + ".nzb" }
},
Transfer = new Dictionary<string, string>
{
@ -203,7 +203,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
protected void GivenTvDirectory()
{
_settings.TvDirectory = _tvDirectory;
_settings.TvDirectory = _musicDirectory;
}
protected virtual void GivenTasks(List<DownloadStationTask> nzbs)
@ -254,14 +254,14 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
GivenTvDirectory();
GivenSuccessfulDownload();
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
var id = Subject.Download(remoteEpisode);
id.Should().NotBeNullOrEmpty();
Mocker.GetMock<IDownloadStationTaskProxy>()
.Verify(v => v.AddTaskFromData(It.IsAny<byte[]>(), It.IsAny<string>(), _tvDirectory, It.IsAny<DownloadStationSettings>()), Times.Once());
.Verify(v => v.AddTaskFromData(It.IsAny<byte[]>(), It.IsAny<string>(), _musicDirectory, It.IsAny<DownloadStationSettings>()), Times.Once());
}
[Test]
@ -271,7 +271,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
GivenTvCategory();
GivenSuccessfulDownload();
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
var id = Subject.Download(remoteEpisode);
@ -287,7 +287,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
GivenSerialNumber();
GivenSuccessfulDownload();
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
var id = Subject.Download(remoteEpisode);
@ -362,7 +362,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
[Test]
public void Download_should_throw_and_not_add_task_if_cannot_get_serial_number()
{
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
Mocker.GetMock<ISerialNumberProvider>()
.Setup(s => s.GetSerialNumber(_settings))

@ -197,7 +197,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.HadoukenTests
{
GivenSuccessfulDownload();
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
var id = Subject.Download(remoteEpisode);
@ -276,7 +276,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.HadoukenTests
[Test]
public void Download_from_magnet_link_should_return_hash_uppercase()
{
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
remoteEpisode.Release.DownloadUrl = "magnet:?xt=urn:btih:a45129e59d8750f9da982f53552b1e4f0457ee9f";
@ -291,7 +291,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.HadoukenTests
[Test]
public void Download_from_torrent_file_should_return_hash_uppercase()
{
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
Mocker.GetMock<IHadoukenProxy>()
.Setup(v => v.AddTorrentFile(It.IsAny<HadoukenSettings>(), It.IsAny<byte[]>()))

@ -1,4 +1,4 @@
using System;
using System;
using System.Linq;
using System.Collections.Generic;
using FluentAssertions;
@ -32,7 +32,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbVortexTests
Host = "127.0.0.1",
Port = 2222,
ApiKey = "1234-ABCD",
TvCategory = "tv",
TvCategory = "Music",
RecentTvPriority = (int)NzbgetPriority.High
};
@ -41,16 +41,16 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbVortexTests
Id = RandomNumber,
DownloadedSize = 1000,
TotalDownloadSize = 10,
GroupName = "tv",
UiTitle = "Droned.S01E01.Pilot.1080p.WEB-DL-DRONE"
GroupName = "Music",
UiTitle = "Fall Out Boy-Make America Psycho Again-CD-FLAC-2015-FORSAKEN"
};
_failed = new NzbVortexQueueItem
{
DownloadedSize = 1000,
TotalDownloadSize = 1000,
GroupName = "tv",
UiTitle = "Droned.S01E01.Pilot.1080p.WEB-DL-DRONE",
GroupName = "Music",
UiTitle = "Fall Out Boy-Make America Psycho Again-CD-FLAC-2015-FORSAKEN",
DestinationPath = "somedirectory",
State = NzbVortexStateType.UncompressFailed,
};
@ -59,9 +59,9 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbVortexTests
{
DownloadedSize = 1000,
TotalDownloadSize = 1000,
GroupName = "tv",
UiTitle = "Droned.S01E01.Pilot.1080p.WEB-DL-DRONE",
DestinationPath = "/remote/mount/tv/Droned.S01E01.Pilot.1080p.WEB-DL-DRONE",
GroupName = "Music",
UiTitle = "Fall Out Boy-Make America Psycho Again-CD-FLAC-2015-FORSAKEN",
DestinationPath = "/remote/mount/music/Fall Out Boy-Make America Psycho Again-CD-FLAC-2015-FORSAKEN",
State = NzbVortexStateType.Done
};
}
@ -189,7 +189,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbVortexTests
{
GivenSuccessfulDownload();
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
var id = Subject.Download(remoteEpisode);
@ -201,7 +201,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbVortexTests
{
GivenFailedDownload();
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
Assert.Throws<DownloadClientException>(() => Subject.Download(remoteEpisode));
}
@ -223,13 +223,13 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbVortexTests
{
Mocker.GetMock<IRemotePathMappingService>()
.Setup(v => v.RemapRemoteToLocal("127.0.0.1", It.IsAny<OsPath>()))
.Returns(new OsPath(@"O:\mymount\Droned.S01E01.Pilot.1080p.WEB-DL-DRONE".AsOsAgnostic()));
.Returns(new OsPath(@"O:\mymount\Fall Out Boy-Make America Psycho Again-CD-FLAC-2015-FORSAKEN".AsOsAgnostic()));
GivenQueue(_completed);
var result = Subject.GetItems().Single();
result.OutputPath.Should().Be(@"O:\mymount\Droned.S01E01.Pilot.1080p.WEB-DL-DRONE".AsOsAgnostic());
result.OutputPath.Should().Be(@"O:\mymount\Fall Out Boy-Make America Psycho Again-CD-FLAC-2015-FORSAKEN".AsOsAgnostic());
}
[Test]
@ -241,14 +241,14 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbVortexTests
Mocker.GetMock<INzbVortexProxy>()
.Setup(s => s.GetFiles(It.IsAny<int>(), It.IsAny<NzbVortexSettings>()))
.Returns(new List<NzbVortexFile> { new NzbVortexFile { FileName = "Droned.S01E01.Pilot.1080p.WEB-DL-DRONE.mkv" } });
.Returns(new List<NzbVortexFile> { new NzbVortexFile { FileName = "Fall Out Boy - Make America Psyco Again - Track 1.flac" } });
_completed.State = NzbVortexStateType.Done;
GivenQueue(_completed);
var result = Subject.GetItems().Single();
result.OutputPath.Should().Be(@"O:\mymount\Droned.S01E01.Pilot.1080p.WEB-DL-DRONE.mkv".AsOsAgnostic());
result.OutputPath.Should().Be(@"O:\mymount\Fall Out Boy - Make America Psyco Again - Track 1.flac".AsOsAgnostic());
}
[Test]
@ -262,8 +262,8 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbVortexTests
.Setup(s => s.GetFiles(It.IsAny<int>(), It.IsAny<NzbVortexSettings>()))
.Returns(new List<NzbVortexFile>
{
new NzbVortexFile { FileName = "Droned.S01E01.Pilot.1080p.WEB-DL-DRONE.mkv" },
new NzbVortexFile { FileName = "Droned.S01E01.Pilot.1080p.WEB-DL-DRONE.nfo" }
new NzbVortexFile { FileName = "Fall Out Boy - Make America Psyco Again - Track 1.flac" },
new NzbVortexFile { FileName = "Fall Out Boy-Make America Psycho Again-CD-FLAC-2015-FORSAKEN.nfo" }
});
_completed.State = NzbVortexStateType.Done;

@ -1,4 +1,4 @@
using System;
using System;
using System.Linq;
using System.Collections.Generic;
using FluentAssertions;
@ -30,7 +30,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetTests
Port = 2222,
Username = "admin",
Password = "pass",
TvCategory = "tv",
TvCategory = "music",
RecentTvPriority = (int)NzbgetPriority.High
};
@ -38,16 +38,16 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetTests
{
FileSizeLo = 1000,
RemainingSizeLo = 10,
Category = "tv",
NzbName = "Droned.S01E01.Pilot.1080p.WEB-DL-DRONE",
Category = "music",
NzbName = "Fall Out Boy-Make America Psycho Again-CD-FLAC-2015-FORSAKEN",
Parameters = new List<NzbgetParameter> { new NzbgetParameter { Name = "drone", Value = "id" } }
};
_failed = new NzbgetHistoryItem
{
FileSizeLo = 1000,
Category = "tv",
Name = "Droned.S01E01.Pilot.1080p.WEB-DL-DRONE",
Category = "music",
Name = "Fall Out Boy-Make America Psycho Again-CD-FLAC-2015-FORSAKEN",
DestDir = "somedirectory",
Parameters = new List<NzbgetParameter> { new NzbgetParameter { Name = "drone", Value = "id" } },
ParStatus = "Some Error",
@ -61,9 +61,9 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetTests
_completed = new NzbgetHistoryItem
{
FileSizeLo = 1000,
Category = "tv",
Name = "Droned.S01E01.Pilot.1080p.WEB-DL-DRONE",
DestDir = "/remote/mount/tv/Droned.S01E01.Pilot.1080p.WEB-DL-DRONE",
Category = "music",
Name = "Fall Out Boy-Make America Psycho Again-CD-FLAC-2015-FORSAKEN",
DestDir = "/remote/mount/music/Fall Out Boy-Make America Psycho Again-CD-FLAC-2015-FORSAKEN",
Parameters = new List<NzbgetParameter> { new NzbgetParameter { Name = "drone", Value = "id" } },
ParStatus = "SUCCESS",
UnpackStatus = "NONE",
@ -81,8 +81,8 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetTests
});
var configItems = new Dictionary<string, string>();
configItems.Add("Category1.Name", "tv");
configItems.Add("Category1.DestDir", @"/remote/mount/tv");
configItems.Add("Category1.Name", "music");
configItems.Add("Category1.DestDir", @"/remote/mount/music");
Mocker.GetMock<INzbgetProxy>()
.Setup(v => v.GetConfig(It.IsAny<NzbgetSettings>()))
@ -303,7 +303,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetTests
{
GivenSuccessfulDownload();
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
var id = Subject.Download(remoteEpisode);
@ -315,7 +315,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetTests
{
GivenFailedDownload();
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
Assert.Throws<DownloadClientException>(() => Subject.Download(remoteEpisode));
}
@ -340,7 +340,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetTests
result.IsLocalhost.Should().BeTrue();
result.OutputRootFolders.Should().NotBeNull();
result.OutputRootFolders.First().Should().Be(@"/remote/mount/tv");
result.OutputRootFolders.First().Should().Be(@"/remote/mount/music");
}
[Test]
@ -362,14 +362,14 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetTests
{
Mocker.GetMock<IRemotePathMappingService>()
.Setup(v => v.RemapRemoteToLocal("127.0.0.1", It.IsAny<OsPath>()))
.Returns(new OsPath(@"O:\mymount\Droned.S01E01.Pilot.1080p.WEB-DL-DRONE".AsOsAgnostic()));
.Returns(new OsPath(@"O:\mymount\Fall Out Boy-Make America Psycho Again-CD-FLAC-2015-FORSAKEN".AsOsAgnostic()));
GivenQueue(null);
GivenHistory(_completed);
var result = Subject.GetItems().Single();
result.OutputPath.Should().Be(@"O:\mymount\Droned.S01E01.Pilot.1080p.WEB-DL-DRONE".AsOsAgnostic());
result.OutputPath.Should().Be(@"O:\mymount\Fall Out Boy-Make America Psycho Again-CD-FLAC-2015-FORSAKEN".AsOsAgnostic());
}
[TestCase("11.0", false)]

@ -1,4 +1,4 @@
using System;
using System;
using System.IO;
using System.Net;
using Moq;
@ -21,7 +21,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests
private string _pneumaticFolder;
private string _sabDrop;
private string _nzbPath;
private RemoteEpisode _remoteEpisode;
private RemoteAlbum _remoteEpisode;
[SetUp]
public void Setup()
@ -33,13 +33,12 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests
Mocker.GetMock<IConfigService>().SetupGet(c => c.DownloadedEpisodesFolder).Returns(_sabDrop);
_remoteEpisode = new RemoteEpisode();
_remoteEpisode = new RemoteAlbum();
_remoteEpisode.Release = new ReleaseInfo();
_remoteEpisode.Release.Title = _title;
_remoteEpisode.Release.DownloadUrl = _nzbUrl;
_remoteEpisode.ParsedEpisodeInfo = new ParsedEpisodeInfo();
_remoteEpisode.ParsedEpisodeInfo.FullSeason = false;
_remoteEpisode.ParsedAlbumInfo = new ParsedAlbumInfo();
Subject.Definition = new DownloadClientDefinition();
Subject.Definition.Settings = new PneumaticSettings
@ -74,7 +73,6 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests
public void should_throw_if_full_season_download()
{
_remoteEpisode.Release.Title = "30 Rock - Season 1";
_remoteEpisode.ParsedEpisodeInfo.FullSeason = true;
Assert.Throws<NotSupportedException>(() => Subject.Download(_remoteEpisode));
}

@ -245,7 +245,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
{
GivenSuccessfulDownload();
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
var id = Subject.Download(remoteEpisode);
@ -257,7 +257,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
{
GivenSuccessfulDownload();
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
remoteEpisode.Release.DownloadUrl = magnetUrl;
var id = Subject.Download(remoteEpisode);
@ -290,7 +290,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
GivenRedirectToMagnet();
GivenSuccessfulDownload();
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
var id = Subject.Download(remoteEpisode);
@ -303,7 +303,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
GivenRedirectToTorrent();
GivenSuccessfulDownload();
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
var id = Subject.Download(remoteEpisode);

@ -1,4 +1,4 @@
using System.Linq;
using System.Linq;
using System.Collections.Generic;
using FluentAssertions;
using Moq;
@ -116,7 +116,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.RTorrentTests
{
GivenSuccessfulDownload();
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
var id = Subject.Download(remoteEpisode);

@ -1,4 +1,4 @@
using System;
using System;
using System.Linq;
using System.Collections.Generic;
using FizzWare.NBuilder;
@ -8,7 +8,7 @@ using NUnit.Framework;
using NzbDrone.Core.Download;
using NzbDrone.Core.Download.Clients.Sabnzbd;
using NzbDrone.Core.Download.Clients.Sabnzbd.Responses;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Music;
using NzbDrone.Test.Common;
using NzbDrone.Core.RemotePathMappings;
using NzbDrone.Common.Disk;
@ -281,7 +281,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests
{
GivenSuccessfulDownload();
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
remoteEpisode.Release.Title = title;
var id = Subject.Download(remoteEpisode);
@ -295,7 +295,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests
{
GivenSuccessfulDownload();
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
var id = Subject.Download(remoteEpisode);
@ -336,10 +336,10 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests
.Setup(s => s.DownloadNzb(It.IsAny<byte[]>(), It.IsAny<string>(), It.IsAny<string>(), (int)SabnzbdPriority.High, It.IsAny<SabnzbdSettings>()))
.Returns(new SabnzbdAddResponse());
var remoteEpisode = CreateRemoteEpisode();
remoteEpisode.Episodes = Builder<Episode>.CreateListOfSize(1)
var remoteEpisode = CreateRemoteAlbum();
remoteEpisode.Albums = Builder<Album>.CreateListOfSize(1)
.All()
.With(e => e.AirDate = DateTime.Today.ToString(Episode.AIR_DATE_FORMAT))
.With(e => e.ReleaseDate = DateTime.Today)
.Build()
.ToList();

@ -55,7 +55,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
{
GivenSuccessfulDownload();
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
var id = Subject.Download(remoteEpisode);
@ -68,7 +68,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
GivenTvDirectory();
GivenSuccessfulDownload();
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
var id = Subject.Download(remoteEpisode);
@ -84,7 +84,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
GivenTvCategory();
GivenSuccessfulDownload();
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
var id = Subject.Download(remoteEpisode);
@ -102,7 +102,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
_transmissionConfigItems["download-dir"] += "/";
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
var id = Subject.Download(remoteEpisode);
@ -117,7 +117,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
{
GivenSuccessfulDownload();
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
var id = Subject.Download(remoteEpisode);
@ -132,7 +132,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
{
GivenSuccessfulDownload();
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
remoteEpisode.Release.DownloadUrl = magnetUrl;
var id = Subject.Download(remoteEpisode);

@ -30,7 +30,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.UTorrentTests
Port = 2222,
Username = "admin",
Password = "pass",
TvCategory = "tv"
TvCategory = "lidarr"
};
_queued = new UTorrentTorrent
@ -41,7 +41,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.UTorrentTests
Size = 1000,
Remaining = 1000,
Progress = 0,
Label = "tv",
Label = "lidarr",
DownloadUrl = _downloadUrl,
RootDownloadPath = "somepath"
};
@ -54,7 +54,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.UTorrentTests
Size = 1000,
Remaining = 100,
Progress = 0.9,
Label = "tv",
Label = "lidarr",
DownloadUrl = _downloadUrl,
RootDownloadPath = "somepath"
};
@ -67,7 +67,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.UTorrentTests
Size = 1000,
Remaining = 100,
Progress = 0.9,
Label = "tv",
Label = "lidarr",
DownloadUrl = _downloadUrl,
RootDownloadPath = "somepath"
};
@ -80,7 +80,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.UTorrentTests
Size = 1000,
Remaining = 0,
Progress = 1.0,
Label = "tv",
Label = "lidarr",
DownloadUrl = _downloadUrl,
RootDownloadPath = "somepath"
};
@ -229,7 +229,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.UTorrentTests
{
GivenSuccessfulDownload();
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
var id = Subject.Download(remoteEpisode);
@ -253,7 +253,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.UTorrentTests
{
GivenSuccessfulDownload();
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
remoteEpisode.Release.DownloadUrl = magnetUrl;
var id = Subject.Download(remoteEpisode);
@ -328,7 +328,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.UTorrentTests
result.IsLocalhost.Should().BeTrue();
result.OutputRootFolders.Should().NotBeNull();
result.OutputRootFolders.First().Should().Be(@"C:\Downloads\Finished\utorrent\tv".AsOsAgnostic());
result.OutputRootFolders.First().Should().Be(@"C:\Downloads\Finished\utorrent\lidarr".AsOsAgnostic());
}
[Test]
@ -351,7 +351,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.UTorrentTests
GivenRedirectToMagnet();
GivenSuccessfulDownload();
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
var id = Subject.Download(remoteEpisode);
@ -364,7 +364,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.UTorrentTests
GivenRedirectToTorrent();
GivenSuccessfulDownload();
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
var id = Subject.Download(remoteEpisode);

@ -57,7 +57,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.VuzeTests
{
GivenSuccessfulDownload();
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
var id = Subject.Download(remoteEpisode);
@ -70,7 +70,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.VuzeTests
GivenTvDirectory();
GivenSuccessfulDownload();
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
var id = Subject.Download(remoteEpisode);
@ -86,7 +86,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.VuzeTests
GivenTvCategory();
GivenSuccessfulDownload();
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
var id = Subject.Download(remoteEpisode);
@ -104,7 +104,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.VuzeTests
_transmissionConfigItems["download-dir"] += "/";
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
var id = Subject.Download(remoteEpisode);
@ -119,7 +119,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.VuzeTests
{
GivenSuccessfulDownload();
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
var id = Subject.Download(remoteEpisode);
@ -134,7 +134,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.VuzeTests
{
GivenSuccessfulDownload();
var remoteEpisode = CreateRemoteEpisode();
var remoteEpisode = CreateRemoteAlbum();
remoteEpisode.Release.DownloadUrl = magnetUrl;
var id = Subject.Download(remoteEpisode);

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
@ -12,7 +12,7 @@ using NzbDrone.Core.Exceptions;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Music;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.Download
@ -20,7 +20,7 @@ namespace NzbDrone.Core.Test.Download
[TestFixture]
public class DownloadServiceFixture : CoreTest<DownloadService>
{
private RemoteEpisode _parseResult;
private RemoteAlbum _parseResult;
private List<IDownloadClient> _downloadClients;
[SetUp]
public void Setup()
@ -35,10 +35,10 @@ namespace NzbDrone.Core.Test.Download
.Setup(v => v.GetDownloadClient(It.IsAny<DownloadProtocol>()))
.Returns<DownloadProtocol>(v => _downloadClients.FirstOrDefault(d => d.Protocol == v));
var episodes = Builder<Episode>.CreateListOfSize(2)
var episodes = Builder<Album>.CreateListOfSize(2)
.TheFirst(1).With(s => s.Id = 12)
.TheNext(1).With(s => s.Id = 99)
.All().With(s => s.SeriesId = 5)
.All().With(s => s.ArtistId = 5)
.Build().ToList();
var releaseInfo = Builder<ReleaseInfo>.CreateNew()
@ -46,10 +46,10 @@ namespace NzbDrone.Core.Test.Download
.With(v => v.DownloadUrl = "http://test.site/download1.ext")
.Build();
_parseResult = Builder<RemoteEpisode>.CreateNew()
.With(c => c.Series = Builder<Series>.CreateNew().Build())
_parseResult = Builder<RemoteAlbum>.CreateNew()
.With(c => c.Artist = Builder<Artist>.CreateNew().Build())
.With(c => c.Release = releaseInfo)
.With(c => c.Episodes = episodes)
.With(c => c.Albums = episodes)
.Build();
}
@ -81,42 +81,42 @@ namespace NzbDrone.Core.Test.Download
public void Download_report_should_publish_on_grab_event()
{
var mock = WithUsenetClient();
mock.Setup(s => s.Download(It.IsAny<RemoteEpisode>()));
mock.Setup(s => s.Download(It.IsAny<RemoteAlbum>()));
Subject.DownloadReport(_parseResult);
VerifyEventPublished<EpisodeGrabbedEvent>();
VerifyEventPublished<AlbumGrabbedEvent>();
}
[Test]
public void Download_report_should_grab_using_client()
{
var mock = WithUsenetClient();
mock.Setup(s => s.Download(It.IsAny<RemoteEpisode>()));
mock.Setup(s => s.Download(It.IsAny<RemoteAlbum>()));
Subject.DownloadReport(_parseResult);
mock.Verify(s => s.Download(It.IsAny<RemoteEpisode>()), Times.Once());
mock.Verify(s => s.Download(It.IsAny<RemoteAlbum>()), Times.Once());
}
[Test]
public void Download_report_should_not_publish_on_failed_grab_event()
{
var mock = WithUsenetClient();
mock.Setup(s => s.Download(It.IsAny<RemoteEpisode>()))
mock.Setup(s => s.Download(It.IsAny<RemoteAlbum>()))
.Throws(new WebException());
Assert.Throws<WebException>(() => Subject.DownloadReport(_parseResult));
VerifyEventNotPublished<EpisodeGrabbedEvent>();
VerifyEventNotPublished<AlbumGrabbedEvent>();
}
[Test]
public void Download_report_should_trigger_indexer_backoff_on_indexer_error()
{
var mock = WithUsenetClient();
mock.Setup(s => s.Download(It.IsAny<RemoteEpisode>()))
.Callback<RemoteEpisode>(v => {
mock.Setup(s => s.Download(It.IsAny<RemoteAlbum>()))
.Callback<RemoteAlbum>(v => {
throw new ReleaseDownloadException(v.Release, "Error", new WebException());
});
@ -134,8 +134,8 @@ namespace NzbDrone.Core.Test.Download
response.Headers["Retry-After"] = "300";
var mock = WithUsenetClient();
mock.Setup(s => s.Download(It.IsAny<RemoteEpisode>()))
.Callback<RemoteEpisode>(v => {
mock.Setup(s => s.Download(It.IsAny<RemoteAlbum>()))
.Callback<RemoteAlbum>(v => {
throw new ReleaseDownloadException(v.Release, "Error", new TooManyRequestsException(request, response));
});
@ -153,8 +153,8 @@ namespace NzbDrone.Core.Test.Download
response.Headers["Retry-After"] = DateTime.UtcNow.AddSeconds(300).ToString("r");
var mock = WithUsenetClient();
mock.Setup(s => s.Download(It.IsAny<RemoteEpisode>()))
.Callback<RemoteEpisode>(v =>
mock.Setup(s => s.Download(It.IsAny<RemoteAlbum>()))
.Callback<RemoteAlbum>(v =>
{
throw new ReleaseDownloadException(v.Release, "Error", new TooManyRequestsException(request, response));
});
@ -170,7 +170,7 @@ namespace NzbDrone.Core.Test.Download
public void Download_report_should_not_trigger_indexer_backoff_on_downloadclient_error()
{
var mock = WithUsenetClient();
mock.Setup(s => s.Download(It.IsAny<RemoteEpisode>()))
mock.Setup(s => s.Download(It.IsAny<RemoteAlbum>()))
.Throws(new DownloadClientException("Some Error"));
Assert.Throws<DownloadClientException>(() => Subject.DownloadReport(_parseResult));
@ -184,7 +184,7 @@ namespace NzbDrone.Core.Test.Download
{
Subject.DownloadReport(_parseResult);
Mocker.GetMock<IDownloadClient>().Verify(c => c.Download(It.IsAny<RemoteEpisode>()), Times.Never());
Mocker.GetMock<IDownloadClient>().Verify(c => c.Download(It.IsAny<RemoteAlbum>()), Times.Never());
VerifyEventNotPublished<EpisodeGrabbedEvent>();
ExceptionVerification.ExpectedWarns(1);
@ -198,8 +198,8 @@ namespace NzbDrone.Core.Test.Download
Subject.DownloadReport(_parseResult);
mockTorrent.Verify(c => c.Download(It.IsAny<RemoteEpisode>()), Times.Never());
mockUsenet.Verify(c => c.Download(It.IsAny<RemoteEpisode>()), Times.Once());
mockTorrent.Verify(c => c.Download(It.IsAny<RemoteAlbum>()), Times.Never());
mockUsenet.Verify(c => c.Download(It.IsAny<RemoteAlbum>()), Times.Once());
}
[Test]
@ -212,8 +212,8 @@ namespace NzbDrone.Core.Test.Download
Subject.DownloadReport(_parseResult);
mockTorrent.Verify(c => c.Download(It.IsAny<RemoteEpisode>()), Times.Once());
mockUsenet.Verify(c => c.Download(It.IsAny<RemoteEpisode>()), Times.Never());
mockTorrent.Verify(c => c.Download(It.IsAny<RemoteAlbum>()), Times.Once());
mockUsenet.Verify(c => c.Download(It.IsAny<RemoteAlbum>()), Times.Never());
}
}
}

@ -12,7 +12,7 @@ using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Profiles;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Music;
namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
{
@ -20,20 +20,20 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
public class AddFixture : CoreTest<PendingReleaseService>
{
private DownloadDecision _temporarilyRejected;
private Series _series;
private Episode _episode;
private Artist _artist;
private Album _album;
private Profile _profile;
private ReleaseInfo _release;
private ParsedEpisodeInfo _parsedEpisodeInfo;
private RemoteEpisode _remoteEpisode;
private ParsedAlbumInfo _parsedAlbumInfo;
private RemoteAlbum _remoteAlbum;
[SetUp]
public void Setup()
{
_series = Builder<Series>.CreateNew()
_artist = Builder<Artist>.CreateNew()
.Build();
_episode = Builder<Episode>.CreateNew()
_album = Builder<Album>.CreateNew()
.Build();
_profile = new Profile
@ -48,32 +48,32 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
},
};
_series.Profile = new LazyLoaded<Profile>(_profile);
_artist.Profile = new LazyLoaded<Profile>(_profile);
_release = Builder<ReleaseInfo>.CreateNew().Build();
_parsedEpisodeInfo = Builder<ParsedEpisodeInfo>.CreateNew().Build();
_parsedEpisodeInfo.Quality = new QualityModel(Quality.MP3_256);
_parsedAlbumInfo = Builder<ParsedAlbumInfo>.CreateNew().Build();
_parsedAlbumInfo.Quality = new QualityModel(Quality.MP3_256);
_remoteEpisode = new RemoteEpisode();
_remoteEpisode.Episodes = new List<Episode>{ _episode };
_remoteEpisode.Series = _series;
_remoteEpisode.ParsedEpisodeInfo = _parsedEpisodeInfo;
_remoteEpisode.Release = _release;
_remoteAlbum = new RemoteAlbum();
_remoteAlbum.Albums = new List<Album>{ _album };
_remoteAlbum.Artist = _artist;
_remoteAlbum.ParsedAlbumInfo = _parsedAlbumInfo;
_remoteAlbum.Release = _release;
_temporarilyRejected = new DownloadDecision(_remoteEpisode, new Rejection("Temp Rejected", RejectionType.Temporary));
_temporarilyRejected = new DownloadDecision(_remoteAlbum, new Rejection("Temp Rejected", RejectionType.Temporary));
Mocker.GetMock<IPendingReleaseRepository>()
.Setup(s => s.All())
.Returns(new List<PendingRelease>());
Mocker.GetMock<ISeriesService>()
.Setup(s => s.GetSeries(It.IsAny<int>()))
.Returns(_series);
Mocker.GetMock<IArtistService>()
.Setup(s => s.GetArtist(It.IsAny<int>()))
.Returns(_artist);
Mocker.GetMock<IParsingService>()
.Setup(s => s.GetEpisodes(It.IsAny<ParsedEpisodeInfo>(), _series, true, null))
.Returns(new List<Episode> {_episode});
.Setup(s => s.GetAlbums(It.IsAny<ParsedAlbumInfo>(), _artist, null))
.Returns(new List<Album> {_album});
Mocker.GetMock<IPrioritizeDownloadDecision>()
.Setup(s => s.PrioritizeDecisions(It.IsAny<List<DownloadDecision>>()))
@ -89,7 +89,7 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
var heldReleases = Builder<PendingRelease>.CreateListOfSize(1)
.All()
.With(h => h.SeriesId = _series.Id)
.With(h => h.ArtistId = _artist.Id)
.With(h => h.Title = title)
.With(h => h.Release = release)
.Build();

@ -12,7 +12,7 @@ using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Profiles;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Music;
namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
{
@ -20,20 +20,20 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
public class RemoveGrabbedFixture : CoreTest<PendingReleaseService>
{
private DownloadDecision _temporarilyRejected;
private Series _series;
private Episode _episode;
private Artist _artist;
private Album _album;
private Profile _profile;
private ReleaseInfo _release;
private ParsedEpisodeInfo _parsedEpisodeInfo;
private RemoteEpisode _remoteEpisode;
private ParsedAlbumInfo _parsedAlbumInfo;
private RemoteAlbum _remoteAlbum;
[SetUp]
public void Setup()
{
_series = Builder<Series>.CreateNew()
_artist = Builder<Artist>.CreateNew()
.Build();
_episode = Builder<Episode>.CreateNew()
_album = Builder<Album>.CreateNew()
.Build();
_profile = new Profile
@ -48,32 +48,32 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
},
};
_series.Profile = new LazyLoaded<Profile>(_profile);
_artist.Profile = new LazyLoaded<Profile>(_profile);
_release = Builder<ReleaseInfo>.CreateNew().Build();
_parsedEpisodeInfo = Builder<ParsedEpisodeInfo>.CreateNew().Build();
_parsedEpisodeInfo.Quality = new QualityModel(Quality.MP3_256);
_parsedAlbumInfo = Builder<ParsedAlbumInfo>.CreateNew().Build();
_parsedAlbumInfo.Quality = new QualityModel(Quality.MP3_256);
_remoteEpisode = new RemoteEpisode();
_remoteEpisode.Episodes = new List<Episode>{ _episode };
_remoteEpisode.Series = _series;
_remoteEpisode.ParsedEpisodeInfo = _parsedEpisodeInfo;
_remoteEpisode.Release = _release;
_remoteAlbum = new RemoteAlbum();
_remoteAlbum.Albums = new List<Album>{ _album };
_remoteAlbum.Artist = _artist;
_remoteAlbum.ParsedAlbumInfo = _parsedAlbumInfo;
_remoteAlbum.Release = _release;
_temporarilyRejected = new DownloadDecision(_remoteEpisode, new Rejection("Temp Rejected", RejectionType.Temporary));
_temporarilyRejected = new DownloadDecision(_remoteAlbum, new Rejection("Temp Rejected", RejectionType.Temporary));
Mocker.GetMock<IPendingReleaseRepository>()
.Setup(s => s.All())
.Returns(new List<PendingRelease>());
Mocker.GetMock<ISeriesService>()
.Setup(s => s.GetSeries(It.IsAny<int>()))
.Returns(_series);
Mocker.GetMock<IArtistService>()
.Setup(s => s.GetArtist(It.IsAny<int>()))
.Returns(_artist);
Mocker.GetMock<IParsingService>()
.Setup(s => s.GetEpisodes(It.IsAny<ParsedEpisodeInfo>(), _series, true, null))
.Returns(new List<Episode> {_episode});
.Setup(s => s.GetAlbums(It.IsAny<ParsedAlbumInfo>(), _artist, null))
.Returns(new List<Album> {_album});
Mocker.GetMock<IPrioritizeDownloadDecision>()
.Setup(s => s.PrioritizeDecisions(It.IsAny<List<DownloadDecision>>()))
@ -82,14 +82,14 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
private void GivenHeldRelease(QualityModel quality)
{
var parsedEpisodeInfo = _parsedEpisodeInfo.JsonClone();
var parsedEpisodeInfo = _parsedAlbumInfo.JsonClone();
parsedEpisodeInfo.Quality = quality;
var heldReleases = Builder<PendingRelease>.CreateListOfSize(1)
.All()
.With(h => h.SeriesId = _series.Id)
.With(h => h.ArtistId = _artist.Id)
.With(h => h.Release = _release.JsonClone())
.With(h => h.ParsedEpisodeInfo = parsedEpisodeInfo)
.With(h => h.ParsedAlbumInfo = parsedEpisodeInfo)
.Build();
Mocker.GetMock<IPendingReleaseRepository>()
@ -100,9 +100,9 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
[Test]
public void should_delete_if_the_grabbed_quality_is_the_same()
{
GivenHeldRelease(_parsedEpisodeInfo.Quality);
GivenHeldRelease(_parsedAlbumInfo.Quality);
Subject.Handle(new EpisodeGrabbedEvent(_remoteEpisode));
Subject.Handle(new AlbumGrabbedEvent(_remoteAlbum));
VerifyDelete();
}
@ -112,7 +112,7 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
{
GivenHeldRelease(new QualityModel(Quality.MP3_192));
Subject.Handle(new EpisodeGrabbedEvent(_remoteEpisode));
Subject.Handle(new AlbumGrabbedEvent(_remoteAlbum));
VerifyDelete();
}
@ -122,7 +122,7 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
{
GivenHeldRelease(new QualityModel(Quality.MP3_512));
Subject.Handle(new EpisodeGrabbedEvent(_remoteEpisode));
Subject.Handle(new AlbumGrabbedEvent(_remoteAlbum));
VerifyNoDelete();
}

@ -8,7 +8,7 @@ using NzbDrone.Core.Download.Pending;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Music;
namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
{
@ -16,48 +16,48 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
public class RemovePendingFixture : CoreTest<PendingReleaseService>
{
private List<PendingRelease> _pending;
private Episode _episode;
private Album _album;
[SetUp]
public void Setup()
{
_pending = new List<PendingRelease>();
_episode = Builder<Episode>.CreateNew()
_album = Builder<Album>.CreateNew()
.Build();
Mocker.GetMock<IPendingReleaseRepository>()
.Setup(s => s.AllBySeriesId(It.IsAny<int>()))
.Setup(s => s.AllByArtistId(It.IsAny<int>()))
.Returns(_pending);
Mocker.GetMock<IPendingReleaseRepository>()
.Setup(s => s.All())
.Returns( _pending);
Mocker.GetMock<ISeriesService>()
.Setup(s => s.GetSeries(It.IsAny<int>()))
.Returns(new Series());
Mocker.GetMock<IArtistService>()
.Setup(s => s.GetArtist(It.IsAny<int>()))
.Returns(new Artist());
Mocker.GetMock<IParsingService>()
.Setup(s => s.GetEpisodes(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<Series>(), It.IsAny<bool>(), null))
.Returns(new List<Episode>{ _episode });
.Setup(s => s.GetAlbums(It.IsAny<ParsedAlbumInfo>(), It.IsAny<Artist>(), null))
.Returns(new List<Album>{ _album });
}
private void AddPending(int id, int seasonNumber, int[] episodes)
private void AddPending(int id, string album)
{
_pending.Add(new PendingRelease
{
Id = id,
ParsedEpisodeInfo = new ParsedEpisodeInfo { SeasonNumber = seasonNumber, EpisodeNumbers = episodes }
ParsedAlbumInfo = new ParsedAlbumInfo { AlbumTitle = album}
});
}
[Test]
public void should_remove_same_release()
{
AddPending(id: 1, seasonNumber: 2, episodes: new[] { 3 });
AddPending(id: 1, album: "Album" );
var queueId = HashConverter.GetHashInt31(string.Format("pending-{0}-ep{1}", 1, _episode.Id));
var queueId = HashConverter.GetHashInt31(string.Format("pending-{0}-album{1}", 1, _album.Id));
Subject.RemovePendingQueueItems(queueId);
@ -67,12 +67,12 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
[Test]
public void should_remove_multiple_releases_release()
{
AddPending(id: 1, seasonNumber: 2, episodes: new[] { 1 });
AddPending(id: 2, seasonNumber: 2, episodes: new[] { 2 });
AddPending(id: 3, seasonNumber: 2, episodes: new[] { 3 });
AddPending(id: 4, seasonNumber: 2, episodes: new[] { 3 });
AddPending(id: 1, album: "Album 1");
AddPending(id: 2, album: "Album 2");
AddPending(id: 3, album: "Album 3");
AddPending(id: 4, album: "Album 3");
var queueId = HashConverter.GetHashInt31(string.Format("pending-{0}-ep{1}", 3, _episode.Id));
var queueId = HashConverter.GetHashInt31(string.Format("pending-{0}-album{1}", 3, _album.Id));
Subject.RemovePendingQueueItems(queueId);
@ -80,61 +80,20 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
}
[Test]
public void should_not_remove_diffrent_season()
public void should_not_remove_diffrent_albums()
{
AddPending(id: 1, seasonNumber: 2, episodes: new[] { 1 });
AddPending(id: 2, seasonNumber: 2, episodes: new[] { 1 });
AddPending(id: 3, seasonNumber: 3, episodes: new[] { 1 });
AddPending(id: 4, seasonNumber: 3, episodes: new[] { 1 });
AddPending(id: 1, album: "Album 1");
AddPending(id: 2, album: "Album 1");
AddPending(id: 3, album: "Album 2");
AddPending(id: 4, album: "Album 3");
var queueId = HashConverter.GetHashInt31(string.Format("pending-{0}-ep{1}", 1, _episode.Id));
var queueId = HashConverter.GetHashInt31(string.Format("pending-{0}-album{1}", 1, _album.Id));
Subject.RemovePendingQueueItems(queueId);
AssertRemoved(1, 2);
}
[Test]
public void should_not_remove_diffrent_episodes()
{
AddPending(id: 1, seasonNumber: 2, episodes: new[] { 1 });
AddPending(id: 2, seasonNumber: 2, episodes: new[] { 1 });
AddPending(id: 3, seasonNumber: 2, episodes: new[] { 2 });
AddPending(id: 4, seasonNumber: 2, episodes: new[] { 3 });
var queueId = HashConverter.GetHashInt31(string.Format("pending-{0}-ep{1}", 1, _episode.Id));
Subject.RemovePendingQueueItems(queueId);
AssertRemoved(1, 2);
}
[Test]
public void should_not_remove_multiepisodes()
{
AddPending(id: 1, seasonNumber: 2, episodes: new[] { 1 });
AddPending(id: 2, seasonNumber: 2, episodes: new[] { 1, 2 });
var queueId = HashConverter.GetHashInt31(string.Format("pending-{0}-ep{1}", 1, _episode.Id));
Subject.RemovePendingQueueItems(queueId);
AssertRemoved(1);
}
[Test]
public void should_not_remove_singleepisodes()
{
AddPending(id: 1, seasonNumber: 2, episodes: new[] { 1 });
AddPending(id: 2, seasonNumber: 2, episodes: new[] { 1, 2 });
var queueId = HashConverter.GetHashInt31(string.Format("pending-{0}-ep{1}", 2, _episode.Id));
Subject.RemovePendingQueueItems(queueId);
AssertRemoved(2);
}
private void AssertRemoved(params int[] ids)
{
Mocker.GetMock<IPendingReleaseRepository>().Verify(c => c.DeleteMany(It.Is<IEnumerable<int>>(s => s.SequenceEqual(ids))));

@ -14,7 +14,7 @@ using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Profiles;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Music;
namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
{
@ -22,20 +22,20 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
public class RemoveRejectedFixture : CoreTest<PendingReleaseService>
{
private DownloadDecision _temporarilyRejected;
private Series _series;
private Episode _episode;
private Artist _artist;
private Album _album;
private Profile _profile;
private ReleaseInfo _release;
private ParsedEpisodeInfo _parsedEpisodeInfo;
private RemoteEpisode _remoteEpisode;
private ParsedAlbumInfo _parsedAlbumInfo;
private RemoteAlbum _remoteAlbum;
[SetUp]
public void Setup()
{
_series = Builder<Series>.CreateNew()
_artist = Builder<Artist>.CreateNew()
.Build();
_episode = Builder<Episode>.CreateNew()
_album = Builder<Album>.CreateNew()
.Build();
_profile = new Profile
@ -50,32 +50,32 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
},
};
_series.Profile = new LazyLoaded<Profile>(_profile);
_artist.Profile = new LazyLoaded<Profile>(_profile);
_release = Builder<ReleaseInfo>.CreateNew().Build();
_parsedEpisodeInfo = Builder<ParsedEpisodeInfo>.CreateNew().Build();
_parsedEpisodeInfo.Quality = new QualityModel(Quality.MP3_192);
_parsedAlbumInfo = Builder<ParsedAlbumInfo>.CreateNew().Build();
_parsedAlbumInfo.Quality = new QualityModel(Quality.MP3_192);
_remoteEpisode = new RemoteEpisode();
_remoteEpisode.Episodes = new List<Episode>{ _episode };
_remoteEpisode.Series = _series;
_remoteEpisode.ParsedEpisodeInfo = _parsedEpisodeInfo;
_remoteEpisode.Release = _release;
_remoteAlbum = new RemoteAlbum();
_remoteAlbum.Albums = new List<Album>{ _album };
_remoteAlbum.Artist = _artist;
_remoteAlbum.ParsedAlbumInfo = _parsedAlbumInfo;
_remoteAlbum.Release = _release;
_temporarilyRejected = new DownloadDecision(_remoteEpisode, new Rejection("Temp Rejected", RejectionType.Temporary));
_temporarilyRejected = new DownloadDecision(_remoteAlbum, new Rejection("Temp Rejected", RejectionType.Temporary));
Mocker.GetMock<IPendingReleaseRepository>()
.Setup(s => s.All())
.Returns(new List<PendingRelease>());
Mocker.GetMock<ISeriesService>()
.Setup(s => s.GetSeries(It.IsAny<int>()))
.Returns(_series);
Mocker.GetMock<IArtistService>()
.Setup(s => s.GetArtist(It.IsAny<int>()))
.Returns(_artist);
Mocker.GetMock<IParsingService>()
.Setup(s => s.GetEpisodes(It.IsAny<ParsedEpisodeInfo>(), _series, true, null))
.Returns(new List<Episode> {_episode});
.Setup(s => s.GetAlbums(It.IsAny<ParsedAlbumInfo>(), _artist, null))
.Returns(new List<Album> {_album});
Mocker.GetMock<IPrioritizeDownloadDecision>()
.Setup(s => s.PrioritizeDecisions(It.IsAny<List<DownloadDecision>>()))
@ -91,7 +91,7 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
var heldReleases = Builder<PendingRelease>.CreateListOfSize(1)
.All()
.With(h => h.SeriesId = _series.Id)
.With(h => h.ArtistId = _artist.Id)
.With(h => h.Title = title)
.With(h => h.Release = release)
.Build();

@ -8,7 +8,7 @@ using NzbDrone.Core.History;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Music;
using NzbDrone.Core.Indexers;
using System.Linq;
@ -24,9 +24,9 @@ namespace NzbDrone.Core.Test.Download.TrackedDownloads
.Returns(new List<History.History>(){
new History.History(){
DownloadId = "35238",
SourceTitle = "TV Series S01",
SeriesId = 5,
EpisodeId = 4
SourceTitle = "Audio Artist - Audio Album",
ArtistId = 5,
AlbumId = 4,
}
});
}
@ -36,20 +36,20 @@ namespace NzbDrone.Core.Test.Download.TrackedDownloads
{
GivenDownloadHistory();
var remoteEpisode = new RemoteEpisode
var remoteAlbum = new RemoteAlbum
{
Series = new Series() { Id = 5 },
Episodes = new List<Episode> { new Episode { Id = 4 } },
ParsedEpisodeInfo = new ParsedEpisodeInfo()
Artist = new Artist() { Id = 5 },
Albums = new List<Album> { new Album { Id = 4 } },
ParsedAlbumInfo = new ParsedAlbumInfo()
{
SeriesTitle = "TV Series",
SeasonNumber = 1
AlbumTitle = "Audio Album",
ArtistName = "Audio Artist"
}
};
Mocker.GetMock<IParsingService>()
.Setup(s => s.Map(It.Is<ParsedEpisodeInfo>(i => i.SeasonNumber == 1 && i.SeriesTitle == "TV Series"), It.IsAny<int>(), It.IsAny<IEnumerable<int>>()))
.Returns(remoteEpisode);
.Setup(s => s.Map(It.Is<ParsedAlbumInfo>(i => i.AlbumTitle == "Audio Album" && i.ArtistName == "Audio Artist"), It.IsAny<int>(), It.IsAny<IEnumerable<int>>()))
.Returns(remoteAlbum);
var client = new DownloadClientDefinition()
{
@ -66,67 +66,11 @@ namespace NzbDrone.Core.Test.Download.TrackedDownloads
var trackedDownload = Subject.TrackDownload(client, item);
trackedDownload.Should().NotBeNull();
trackedDownload.RemoteEpisode.Should().NotBeNull();
trackedDownload.RemoteEpisode.Series.Should().NotBeNull();
trackedDownload.RemoteEpisode.Series.Id.Should().Be(5);
trackedDownload.RemoteEpisode.Episodes.First().Id.Should().Be(4);
trackedDownload.RemoteEpisode.ParsedEpisodeInfo.SeasonNumber.Should().Be(1);
trackedDownload.RemoteAlbum.Should().NotBeNull();
trackedDownload.RemoteAlbum.Artist.Should().NotBeNull();
trackedDownload.RemoteAlbum.Artist.Id.Should().Be(5);
trackedDownload.RemoteAlbum.Albums.First().Id.Should().Be(4);
}
[Test]
public void should_parse_as_special_when_source_title_parsing_fails()
{
var remoteEpisode = new RemoteEpisode
{
Series = new Series() { Id = 5 },
Episodes = new List<Episode> { new Episode { Id = 4 } },
ParsedEpisodeInfo = new ParsedEpisodeInfo()
{
SeriesTitle = "TV Series",
SeasonNumber = 0,
EpisodeNumbers = new []{ 1 }
}
};
Mocker.GetMock<IHistoryService>()
.Setup(s => s.FindByDownloadId(It.Is<string>(sr => sr == "35238")))
.Returns(new List<History.History>(){
new History.History(){
DownloadId = "35238",
SourceTitle = "TV Series Special",
SeriesId = 5,
EpisodeId = 4
}
});
Mocker.GetMock<IParsingService>()
.Setup(s => s.Map(It.Is<ParsedEpisodeInfo>(i => i.SeasonNumber == 0 && i.SeriesTitle == "TV Series"), It.IsAny<int>(), It.IsAny<IEnumerable<int>>()))
.Returns(remoteEpisode);
Mocker.GetMock<IParsingService>()
.Setup(s => s.ParseSpecialEpisodeTitle(It.IsAny<string>(), It.IsAny<int>(), It.IsAny<int>(), null))
.Returns(remoteEpisode.ParsedEpisodeInfo);
var client = new DownloadClientDefinition()
{
Id = 1,
Protocol = DownloadProtocol.Torrent
};
var item = new DownloadClientItem()
{
Title = "The torrent release folder",
DownloadId = "35238",
};
var trackedDownload = Subject.TrackDownload(client, item);
trackedDownload.Should().NotBeNull();
trackedDownload.RemoteEpisode.Should().NotBeNull();
trackedDownload.RemoteEpisode.Series.Should().NotBeNull();
trackedDownload.RemoteEpisode.Series.Id.Should().Be(5);
trackedDownload.RemoteEpisode.Episodes.First().Id.Should().Be(4);
trackedDownload.RemoteEpisode.ParsedEpisodeInfo.SeasonNumber.Should().Be(0);
}
}
}

@ -32,13 +32,13 @@ namespace NzbDrone.Core.Test.HistoryTests
{
var historyBluray = Builder<History.History>.CreateNew()
.With(c => c.Quality = new QualityModel(Quality.MP3_320))
.With(c => c.SeriesId = 12)
.With(c => c.ArtistId = 12)
.With(c => c.EventType = HistoryEventType.Grabbed)
.BuildNew();
var historyDvd = Builder<History.History>.CreateNew()
.With(c => c.Quality = new QualityModel(Quality.MP3_192))
.With(c => c.SeriesId = 12)
.With(c => c.ArtistId = 12)
.With(c => c.EventType = HistoryEventType.Grabbed)
.BuildNew();

@ -4,44 +4,44 @@ using NUnit.Framework;
using NzbDrone.Core.Housekeeping.Housekeepers;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Music;
namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
{
[TestFixture]
public class CleanupOrphanedHistoryItemsFixture : DbTest<CleanupOrphanedHistoryItems, History.History>
{
private Series _series;
private Episode _episode;
private Artist _artist;
private Album _album;
[SetUp]
public void Setup()
{
_series = Builder<Series>.CreateNew()
_artist = Builder<Artist>.CreateNew()
.BuildNew();
_episode = Builder<Episode>.CreateNew()
_album = Builder<Album>.CreateNew()
.BuildNew();
}
private void GivenSeries()
private void GivenArtist()
{
Db.Insert(_series);
Db.Insert(_artist);
}
private void GivenEpisode()
private void GivenAlbum()
{
Db.Insert(_episode);
Db.Insert(_album);
}
[Test]
public void should_delete_orphaned_items_by_series()
public void should_delete_orphaned_items_by_artist()
{
GivenEpisode();
GivenAlbum();
var history = Builder<History.History>.CreateNew()
.With(h => h.Quality = new QualityModel())
.With(h => h.EpisodeId = _episode.Id)
.With(h => h.AlbumId = _album.Id)
.BuildNew();
Db.Insert(history);
@ -50,13 +50,13 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
}
[Test]
public void should_delete_orphaned_items_by_episode()
public void should_delete_orphaned_items_by_album()
{
GivenSeries();
GivenArtist();
var history = Builder<History.History>.CreateNew()
.With(h => h.Quality = new QualityModel())
.With(h => h.SeriesId = _series.Id)
.With(h => h.ArtistId = _artist.Id)
.BuildNew();
Db.Insert(history);
@ -65,45 +65,45 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
}
[Test]
public void should_not_delete_unorphaned_data_by_series()
public void should_not_delete_unorphaned_data_by_artist()
{
GivenSeries();
GivenEpisode();
GivenArtist();
GivenAlbum();
var history = Builder<History.History>.CreateListOfSize(2)
.All()
.With(h => h.Quality = new QualityModel())
.With(h => h.EpisodeId = _episode.Id)
.With(h => h.AlbumId = _album.Id)
.TheFirst(1)
.With(h => h.SeriesId = _series.Id)
.With(h => h.ArtistId = _artist.Id)
.BuildListOfNew();
Db.InsertMany(history);
Subject.Clean();
AllStoredModels.Should().HaveCount(1);
AllStoredModels.Should().Contain(h => h.SeriesId == _series.Id);
AllStoredModels.Should().Contain(h => h.ArtistId == _artist.Id);
}
[Test]
public void should_not_delete_unorphaned_data_by_episode()
public void should_not_delete_unorphaned_data_by_album()
{
GivenSeries();
GivenEpisode();
GivenArtist();
GivenAlbum();
var history = Builder<History.History>.CreateListOfSize(2)
.All()
.With(h => h.Quality = new QualityModel())
.With(h => h.SeriesId = _series.Id)
.With(h => h.ArtistId = _artist.Id)
.TheFirst(1)
.With(h => h.EpisodeId = _episode.Id)
.With(h => h.AlbumId = _album.Id)
.BuildListOfNew();
Db.InsertMany(history);
Subject.Clean();
AllStoredModels.Should().HaveCount(1);
AllStoredModels.Should().Contain(h => h.EpisodeId == _episode.Id);
AllStoredModels.Should().Contain(h => h.AlbumId == _album.Id);
}
}
}

@ -5,7 +5,7 @@ using NzbDrone.Core.Download.Pending;
using NzbDrone.Core.Housekeeping.Housekeepers;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Music;
namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
{
@ -16,7 +16,7 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
public void should_delete_orphaned_pending_items()
{
var pendingRelease = Builder<PendingRelease>.CreateNew()
.With(h => h.ParsedEpisodeInfo = new ParsedEpisodeInfo())
.With(h => h.ParsedAlbumInfo = new ParsedAlbumInfo())
.With(h => h.Release = new ReleaseInfo())
.BuildNew();
@ -28,13 +28,13 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
[Test]
public void should_not_delete_unorphaned_pending_items()
{
var series = Builder<Series>.CreateNew().BuildNew();
var artist = Builder<Artist>.CreateNew().BuildNew();
Db.Insert(series);
Db.Insert(artist);
var pendingRelease = Builder<PendingRelease>.CreateNew()
.With(h => h.SeriesId = series.Id)
.With(h => h.ParsedEpisodeInfo = new ParsedEpisodeInfo())
.With(h => h.ArtistId = artist.Id)
.With(h => h.ParsedAlbumInfo = new ParsedAlbumInfo())
.With(h => h.Release = new ReleaseInfo())
.BuildNew();

@ -51,8 +51,6 @@ namespace NzbDrone.Core.Test.IndexerTests.BroadcastheNetTests
torrentInfo.PublishDate.Should().Be(DateTime.Parse("2014/09/16 21:15:33"));
torrentInfo.Size.Should().Be(505099926);
torrentInfo.InfoHash.Should().Be("123");
torrentInfo.TvdbId.Should().Be(71998);
torrentInfo.TvRageId.Should().Be(4055);
torrentInfo.MagnetUrl.Should().BeNullOrEmpty();
torrentInfo.Peers.Should().Be(40+9);
torrentInfo.Seeders.Should().Be(40);

@ -36,7 +36,7 @@ namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
_singleAlbumSearchCriteria = new AlbumSearchCriteria
{
Artist = new Music.Artist { Name = "Alien Ant Farm" },
Album = new Music.Album { Title = "TruANT" }
Albums = new List<Music.Album> { new Music.Album { Title = "TruANT" } }
};

@ -56,8 +56,6 @@ namespace NzbDrone.Core.Test.IndexerTests.RarbgTests
torrentInfo.MagnetUrl.Should().BeNull();
torrentInfo.Peers.Should().Be(304 + 200);
torrentInfo.Seeders.Should().Be(304);
torrentInfo.TvdbId.Should().Be(268156);
torrentInfo.TvRageId.Should().Be(35197);
}
[Test]

@ -60,8 +60,6 @@ namespace NzbDrone.Core.Test.IndexerTests.TorznabTests
releaseInfo.Indexer.Should().Be(Subject.Definition.Name);
releaseInfo.PublishDate.Should().Be(DateTime.Parse("2015/03/14 21:10:42"));
releaseInfo.Size.Should().Be(2538463390);
releaseInfo.TvdbId.Should().Be(273181);
releaseInfo.TvRageId.Should().Be(37780);
releaseInfo.InfoHash.Should().Be("63e07ff523710ca268567dad344ce1e0e6b7e8a3");
releaseInfo.Seeders.Should().Be(7);
releaseInfo.Peers.Should().Be(7);

@ -151,13 +151,12 @@
<Compile Include="Datastore\ReflectionStrategyFixture\Benchmarks.cs" />
<Compile Include="Datastore\SqliteSchemaDumperTests\SqliteSchemaDumperFixture.cs" />
<Compile Include="DecisionEngineTests\AcceptableSizeSpecificationFixture.cs" />
<Compile Include="DecisionEngineTests\AnimeVersionUpgradeSpecificationFixture.cs" />
<Compile Include="DecisionEngineTests\ProtocolSpecificationFixture.cs" />
<Compile Include="DecisionEngineTests\CutoffSpecificationFixture.cs" />
<Compile Include="DecisionEngineTests\DownloadDecisionMakerFixture.cs" />
<Compile Include="DecisionEngineTests\HistorySpecificationFixture.cs" />
<Compile Include="DecisionEngineTests\LanguageSpecificationFixture.cs" />
<Compile Include="DecisionEngineTests\MonitoredEpisodeSpecificationFixture.cs" />
<Compile Include="DecisionEngineTests\MonitoredAlbumSpecificationFixture.cs" />
<Compile Include="DecisionEngineTests\QueueSpecificationFixture.cs" />
<Compile Include="DecisionEngineTests\ReleaseRestrictionsSpecificationFixture.cs" />
<Compile Include="DecisionEngineTests\PrioritizeDownloadDecisionFixture.cs" />
@ -167,7 +166,7 @@
<Compile Include="DecisionEngineTests\RetentionSpecificationFixture.cs" />
<Compile Include="DecisionEngineTests\RssSync\DelaySpecificationFixture.cs" />
<Compile Include="DecisionEngineTests\RssSync\ProperSpecificationFixture.cs" />
<Compile Include="DecisionEngineTests\Search\SeriesSpecificationFixture.cs" />
<Compile Include="DecisionEngineTests\Search\ArtistSpecificationFixture.cs" />
<Compile Include="DecisionEngineTests\SameEpisodesSpecificationFixture.cs" />
<Compile Include="DecisionEngineTests\RawDiskSpecificationFixture.cs" />
<Compile Include="DecisionEngineTests\UpgradeDiskSpecificationFixture.cs" />

@ -1,4 +1,4 @@
using FluentAssertions;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Test.Framework;
@ -62,5 +62,52 @@ namespace NzbDrone.Core.Test.ParserTests
{
Parser.Parser.ParseTitle(postTitle).SeriesTitle.Should().Be(title);
}
[TestCase("VA - The Best 101 Love Ballads (2017) MP3 [192 kbps]", "The Best 101 Love Ballads")]
[TestCase("ATCQ - The Love Movement 1998 2CD 192kbps RIP", "The Love Movement")]
[TestCase("A Tribe Called Quest - The Love Movement 1998 2CD [192kbps] RIP", "The Love Movement")]
[TestCase("Maula - Jism 2 [2012] Mp3 - 192Kbps [Extended]- TK", "Jism 2")]
[TestCase("VA - Complete Clubland - The Ultimate Ride Of Your Lfe [2014][MP3][192 kbps]")]
[TestCase("Complete Clubland - The Ultimate Ride Of Your Lfe [2014][MP3](192kbps)", "The Ultimate Ride Of Your Lfe")]
[TestCase("The Ultimate Ride Of Your Lfe [192 KBPS][2014][MP3]", "The Ultimate Ride Of Your Lfe")]
[TestCase("Gary Clark Jr - Live North America 2016 (2017) MP3 192kbps", "Live North America 2016")]
[TestCase("Beyoncé Lemonade [320] 2016 Beyonce Lemonade [320] 2016", "Lemonade")]
[TestCase("Childish Gambino - Awaken, My Love Album 2016 mp3 320 Kbps", "Awaken, My Love Album")]
[TestCase("Maluma Felices Los 4 MP3 320 Kbps 2017 Download", "Felices Los 4")]
[TestCase("Ricardo Arjona - APNEA (Single 2014) (320 kbps)", "APNEA")]
[TestCase("Kehlani - SweetSexySavage (Deluxe Edition) (2017) 320", "SweetSexySavage")]
[TestCase("Anderson Paak - Malibu (320)(2016)", "Malibu")]
[TestCase("Caetano Veloso Discografia Completa MP3 @256","")]
[TestCase("Little Mix - Salute [Deluxe Edition] [2013] [M4A-256]-V3nom [GLT", "Salute")]
[TestCase("Ricky Martin - A Quien Quiera Escuchar (2015) 256 kbps [GloDLS]", "A Quien Quiera Escuchar")]
[TestCase("Jake Bugg - Jake Bugg (Album) [2012] {MP3 256 kbps}", "Jake Bugg")]
[TestCase("Milky Chance - Sadnecessary [256 Kbps] [M4A]", "Sadnecessary")]
[TestCase("Clean Bandit - New Eyes [2014] [Mp3-256]-V3nom [GLT]", "New Eyes")]
[TestCase("Armin van Buuren - A State Of Trance 810 (20.04.2017) 256 kbps", "A State Of Trance 810")]
[TestCase("PJ Harvey - Let England Shake [mp3-256-2011][trfkad]", "Let England Shake")]
[TestCase("X-Men Soundtracks (2006-2014) AAC, 256 kbps","")]
[TestCase("Walk the Line Soundtrack (2005) [AAC, 256 kbps]", "Walk the Line Soundtrack")]
[TestCase("Emeli Sande Next To Me (512 Kbps)", "Next To Me")]
[TestCase("Kendrick Lamar - DAMN (2017) FLAC", "DAMN")]
[TestCase("Alicia Keys - Vault Playlist Vol. 1 (2017) [FLAC CD]", "Vault Playlist Vol 1")]
[TestCase("Gorillaz - Humanz (Deluxe) - lossless FLAC Tracks - 2017 - CDrip", "Humanz")]
[TestCase("David Bowie - Blackstar (2016) [FLAC]", "Blackstar")]
[TestCase("The Cure - Greatest Hits (2001) FLAC Soup", "Greatest Hits")]
[TestCase("Slowdive - Souvlaki (FLAC)", "Souvlaki")]
[TestCase("John Coltrane - Kulu Se Mama (1965) [EAC-FLAC]", "Kulu Se Mama")]
[TestCase("The Rolling Stones - The Very Best Of '75-'94 (1995) {FLAC}", "The Very Best Of '75-'94")]
[TestCase("Migos-No_Label_II-CD-FLAC-2014-FORSAKEN", "No Label II")]
[TestCase("ADELE 25 CD FLAC 2015 PERFECT", "25")]
[TestCase("A.I. - Sex & Robots [2007/MP3/V0(VBR)]", "Sex & Robots")]
[TestCase("Jay-Z - 4:44 (Deluxe Edition) (2017) 320", "444")]
[TestCase("Roberta Flack 2006 - The Very Best of", "The Very Best of")]
[TestCase("VA - NOW Thats What I Call Music 96 (2017) [Mp3~Kbps]", "NOW Thats What I Call Music 96")]
[TestCase("Queen - The Ultimate Best Of Queen(2011)[mp3]", "The Ultimate Best Of Queen")]
[TestCase("Little Mix - Salute [Deluxe Edition] [2013] [M4A-256]-V3nom [GLT]", "Salute")]
[TestCase("Barış Manço - Ben Bilirim [1993/FLAC/Lossless/Log]", "Ben Bilirim")]
public void should_parse_album_title(string postTitle, string title)
{
Parser.Parser.ParseAlbumTitle(postTitle).AlbumTitle.Should().Be(title);
}
}
}

@ -0,0 +1,36 @@
using FluentMigrator;
using NzbDrone.Core.Datastore.Migration.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(112)]
public class music_history : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
Alter.Table("History")
.AddColumn("ArtistId").AsInt32().WithDefaultValue(0)
.AddColumn("AlbumId").AsInt32().WithDefaultValue(0);
Alter.Table("PendingReleases")
.AddColumn("ArtistId").AsInt32().WithDefaultValue(0)
.AddColumn("ParsedAlbumInfo").AsString().WithDefaultValue("");
Alter.Table("Tracks")
.AddColumn("Duration").AsInt32().WithDefaultValue(0);
Alter.Table("Albums")
.AddColumn("Duration").AsInt32().WithDefaultValue(0);
Delete.Column("SeriesId").FromTable("History");
Delete.Column("EpisodeId").FromTable("History");
Delete.Column("SeriesId").FromTable("PendingReleases");
Delete.Column("ParsedEpisodeInfo").FromTable("PendingReleases");
}
}
}

@ -106,7 +106,7 @@ namespace NzbDrone.Core.Datastore
.For("Tracks")
.LazyLoad(condition: parent => parent.Id > 0,
query: (db, parent) => db.Query<Track>().Where(c => c.ArtistId == parent.Id).ToList()) // TODO: Figure what the hell to do here
.HasOne(file => file.Artist, file => file.AlbumId);
.HasOne(file => file.Artist, file => file.ArtistId);
Mapper.Entity<Track>().RegisterModel("Tracks")
//.Ignore(e => e.SeriesTitle)

@ -1,4 +1,4 @@
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using NzbDrone.Core.Parser.Model;
@ -6,7 +6,7 @@ namespace NzbDrone.Core.DecisionEngine
{
public class DownloadDecision
{
public RemoteEpisode RemoteEpisode { get; private set; }
public RemoteAlbum RemoteAlbum { get; private set; }
public IEnumerable<Rejection> Rejections { get; private set; }
public bool Approved => !Rejections.Any();
@ -27,9 +27,9 @@ namespace NzbDrone.Core.DecisionEngine
}
}
public DownloadDecision(RemoteEpisode episode, params Rejection[] rejections)
public DownloadDecision(RemoteAlbum album, params Rejection[] rejections)
{
RemoteEpisode = episode;
RemoteAlbum = album;
Rejections = rejections.ToList();
}
@ -37,10 +37,10 @@ namespace NzbDrone.Core.DecisionEngine
{
if (Approved)
{
return "[OK] " + RemoteEpisode;
return "[OK] " + RemoteAlbum;
}
return "[Rejected " + Rejections.Count() + "]" + RemoteEpisode;
return "[Rejected " + Rejections.Count() + "]" + RemoteAlbum;
}
}
}

@ -4,7 +4,6 @@ using System.Linq;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Profiles.Delay;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.DecisionEngine
{
@ -25,9 +24,8 @@ namespace NzbDrone.Core.DecisionEngine
{
CompareQuality,
CompareProtocol,
CompareEpisodeCount,
CompareEpisodeNumber,
ComparePeersIfTorrent,
CompareAlbumCount,
CompareAgeIfUsenet,
CompareSize
};
@ -57,67 +55,48 @@ namespace NzbDrone.Core.DecisionEngine
private int CompareQuality(DownloadDecision x, DownloadDecision y)
{
return CompareAll(CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode => remoteEpisode.Series.Profile.Value.Items.FindIndex(v => v.Quality == remoteEpisode.ParsedEpisodeInfo.Quality.Quality)),
CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode => remoteEpisode.ParsedEpisodeInfo.Quality.Revision.Real),
CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode => remoteEpisode.ParsedEpisodeInfo.Quality.Revision.Version));
return CompareAll(CompareBy(x.RemoteAlbum, y.RemoteAlbum, remoteAlbum => remoteAlbum.Artist.Profile.Value.Items.FindIndex(v => v.Quality == remoteAlbum.ParsedAlbumInfo.Quality.Quality)),
CompareBy(x.RemoteAlbum, y.RemoteAlbum, remoteAlbum => remoteAlbum.ParsedAlbumInfo.Quality.Revision.Real),
CompareBy(x.RemoteAlbum, y.RemoteAlbum, remoteAlbum => remoteAlbum.ParsedAlbumInfo.Quality.Revision.Version));
}
private int CompareProtocol(DownloadDecision x, DownloadDecision y)
{
var result = CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode =>
var result = CompareBy(x.RemoteAlbum, y.RemoteAlbum, remoteAlbum =>
{
var delayProfile = _delayProfileService.BestForTags(remoteEpisode.Series.Tags);
var downloadProtocol = remoteEpisode.Release.DownloadProtocol;
var delayProfile = _delayProfileService.BestForTags(remoteAlbum.Artist.Tags);
var downloadProtocol = remoteAlbum.Release.DownloadProtocol;
return downloadProtocol == delayProfile.PreferredProtocol;
});
return result;
}
private int CompareEpisodeCount(DownloadDecision x, DownloadDecision y)
private int CompareAlbumCount(DownloadDecision x, DownloadDecision y)
{
var seasonPackCompare = CompareBy(x.RemoteEpisode, y.RemoteEpisode,
remoteEpisode => remoteEpisode.ParsedEpisodeInfo.FullSeason);
if (seasonPackCompare != 0)
{
return seasonPackCompare;
}
if (x.RemoteEpisode.Series.SeriesType == SeriesTypes.Anime &
y.RemoteEpisode.Series.SeriesType == SeriesTypes.Anime)
{
return CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode => remoteEpisode.Episodes.Count);
}
return CompareByReverse(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode => remoteEpisode.Episodes.Count);
}
private int CompareEpisodeNumber(DownloadDecision x, DownloadDecision y)
{
return CompareByReverse(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode => remoteEpisode.Episodes.Select(e => e.EpisodeNumber).MinOrDefault());
return CompareByReverse(x.RemoteAlbum, y.RemoteAlbum, remoteAlbum => remoteAlbum.Albums.Count);
}
private int ComparePeersIfTorrent(DownloadDecision x, DownloadDecision y)
{
// Different protocols should get caught when checking the preferred protocol,
// since we're dealing with the same series in our comparisions
if (x.RemoteEpisode.Release.DownloadProtocol != DownloadProtocol.Torrent ||
y.RemoteEpisode.Release.DownloadProtocol != DownloadProtocol.Torrent)
if (x.RemoteAlbum.Release.DownloadProtocol != DownloadProtocol.Torrent ||
y.RemoteAlbum.Release.DownloadProtocol != DownloadProtocol.Torrent)
{
return 0;
}
return CompareAll(
CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode =>
CompareBy(x.RemoteAlbum, y.RemoteAlbum, remoteAlbum =>
{
var seeders = TorrentInfo.GetSeeders(remoteEpisode.Release);
var seeders = TorrentInfo.GetSeeders(remoteAlbum.Release);
return seeders.HasValue && seeders.Value > 0 ? Math.Round(Math.Log10(seeders.Value)) : 0;
}),
CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode =>
CompareBy(x.RemoteAlbum, y.RemoteAlbum, remoteAlbum =>
{
var peers = TorrentInfo.GetPeers(remoteEpisode.Release);
var peers = TorrentInfo.GetPeers(remoteAlbum.Release);
return peers.HasValue && peers.Value > 0 ? Math.Round(Math.Log10(peers.Value)) : 0;
}));
@ -125,16 +104,16 @@ namespace NzbDrone.Core.DecisionEngine
private int CompareAgeIfUsenet(DownloadDecision x, DownloadDecision y)
{
if (x.RemoteEpisode.Release.DownloadProtocol != DownloadProtocol.Usenet ||
y.RemoteEpisode.Release.DownloadProtocol != DownloadProtocol.Usenet)
if (x.RemoteAlbum.Release.DownloadProtocol != DownloadProtocol.Usenet ||
y.RemoteAlbum.Release.DownloadProtocol != DownloadProtocol.Usenet)
{
return 0;
}
return CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode =>
return CompareBy(x.RemoteAlbum, y.RemoteAlbum, remoteAlbum =>
{
var ageHours = remoteEpisode.Release.AgeHours;
var age = remoteEpisode.Release.Age;
var ageHours = remoteAlbum.Release.AgeHours;
var age = remoteAlbum.Release.Age;
if (ageHours < 1)
{
@ -159,7 +138,7 @@ namespace NzbDrone.Core.DecisionEngine
{
// TODO: Is smaller better? Smaller for usenet could mean no par2 files.
return CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode => remoteEpisode.Release.Size.Round(200.Megabytes()));
return CompareBy(x.RemoteAlbum, y.RemoteAlbum, remoteAlbum => remoteAlbum.Release.Size.Round(200.Megabytes()));
}
}
}

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using NLog;
@ -32,21 +32,20 @@ namespace NzbDrone.Core.DecisionEngine
public List<DownloadDecision> GetRssDecision(List<ReleaseInfo> reports)
{
return GetDecisions(reports).ToList();
return GetAlbumDecisions(reports).ToList();
}
public List<DownloadDecision> GetSearchDecision(List<ReleaseInfo> reports, SearchCriteriaBase searchCriteriaBase)
{
return GetDecisions(reports, searchCriteriaBase).ToList();
return GetAlbumDecisions(reports, searchCriteriaBase).ToList();
}
private IEnumerable<DownloadDecision> GetDecisions(List<ReleaseInfo> reports, SearchCriteriaBase searchCriteria = null)
private IEnumerable<DownloadDecision> GetAlbumDecisions(List<ReleaseInfo> reports, SearchCriteriaBase searchCriteria = null)
{
if (reports.Any())
{
_logger.ProgressInfo("Processing {0} releases", reports.Count);
}
else
{
_logger.ProgressInfo("No results found");
@ -61,35 +60,25 @@ namespace NzbDrone.Core.DecisionEngine
try
{
var parsedEpisodeInfo = Parser.Parser.ParseTitle(report.Title);
var parsedAlbumInfo = Parser.Parser.ParseAlbumTitle(report.Title);
if (parsedEpisodeInfo == null || parsedEpisodeInfo.IsPossibleSpecialEpisode)
if (parsedAlbumInfo != null && !parsedAlbumInfo.ArtistName.IsNullOrWhiteSpace())
{
var specialEpisodeInfo = _parsingService.ParseSpecialEpisodeTitle(report.Title, report.TvdbId, report.TvRageId, searchCriteria);
var remoteAlbum = _parsingService.Map(parsedAlbumInfo, searchCriteria);
remoteAlbum.Release = report;
if (specialEpisodeInfo != null)
if (remoteAlbum.Artist == null)
{
parsedEpisodeInfo = specialEpisodeInfo;
}
decision = new DownloadDecision(remoteAlbum, new Rejection("Unknown Artist"));
}
if (parsedEpisodeInfo != null && !parsedEpisodeInfo.SeriesTitle.IsNullOrWhiteSpace())
{
var remoteEpisode = _parsingService.Map(parsedEpisodeInfo, report.TvdbId, report.TvRageId, searchCriteria);
remoteEpisode.Release = report;
if (remoteEpisode.Series == null)
else if (remoteAlbum.Albums.Empty())
{
decision = new DownloadDecision(remoteEpisode, new Rejection("Unknown Series"));
}
else if (remoteEpisode.Episodes.Empty())
{
decision = new DownloadDecision(remoteEpisode, new Rejection("Unable to parse episodes from release name"));
decision = new DownloadDecision(remoteAlbum, new Rejection("Unable to parse albums from release name"));
}
else
{
remoteEpisode.DownloadAllowed = remoteEpisode.Episodes.Any();
decision = GetDecisionForReport(remoteEpisode, searchCriteria);
remoteAlbum.DownloadAllowed = remoteAlbum.Albums.Any();
decision = GetDecisionForReport(remoteAlbum, searchCriteria);
}
}
}
@ -97,8 +86,8 @@ namespace NzbDrone.Core.DecisionEngine
{
_logger.Error(e, "Couldn't process release.");
var remoteEpisode = new RemoteEpisode { Release = report };
decision = new DownloadDecision(remoteEpisode, new Rejection("Unexpected error processing release"));
var remoteAlbum = new RemoteAlbum { Release = report };
decision = new DownloadDecision(remoteAlbum, new Rejection("Unexpected error processing release"));
}
reportNumber++;
@ -120,30 +109,34 @@ namespace NzbDrone.Core.DecisionEngine
}
}
private DownloadDecision GetDecisionForReport(RemoteEpisode remoteEpisode, SearchCriteriaBase searchCriteria = null)
private DownloadDecision GetDecisionForReport(RemoteAlbum remoteAlbum, SearchCriteriaBase searchCriteria = null)
{
var reasons = _specifications.Select(c => EvaluateSpec(c, remoteEpisode, searchCriteria))
var reasons = _specifications.Select(c => EvaluateSpec(c, remoteAlbum, searchCriteria))
.Where(c => c != null);
return new DownloadDecision(remoteEpisode, reasons.ToArray());
return new DownloadDecision(remoteAlbum, reasons.ToArray());
}
private Rejection EvaluateSpec(IDecisionEngineSpecification spec, RemoteEpisode remoteEpisode, SearchCriteriaBase searchCriteriaBase = null)
private Rejection EvaluateSpec(IDecisionEngineSpecification spec, RemoteAlbum remoteAlbum, SearchCriteriaBase searchCriteriaBase = null)
{
try
{
var result = spec.IsSatisfiedBy(remoteEpisode, searchCriteriaBase);
var result = spec.IsSatisfiedBy(remoteAlbum, searchCriteriaBase);
if (!result.Accepted)
{
return new Rejection(result.Reason, spec.Type);
}
}
catch (NotImplementedException e)
{
_logger.Trace("Spec " + spec.GetType().Name + " not implemented.");
}
catch (Exception e)
{
e.Data.Add("report", remoteEpisode.Release.ToJson());
e.Data.Add("parsed", remoteEpisode.ParsedEpisodeInfo.ToJson());
_logger.Error(e, "Couldn't evaluate decision on {0}", remoteEpisode.Release.Title);
e.Data.Add("report", remoteAlbum.Release.ToJson());
e.Data.Add("parsed", remoteAlbum.ParsedAlbumInfo.ToJson());
_logger.Error(e, "Couldn't evaluate decision on {0}", remoteAlbum.Release.Title);
return new Rejection($"{spec.GetType().Name}: {e.Message}");
}

@ -20,13 +20,13 @@ namespace NzbDrone.Core.DecisionEngine
public List<DownloadDecision> PrioritizeDecisions(List<DownloadDecision> decisions)
{
return decisions.Where(c => c.RemoteEpisode.Series != null)
.GroupBy(c => c.RemoteEpisode.Series.Id, (seriesId, downloadDecisions) =>
return decisions.Where(c => c.RemoteAlbum.Artist != null)
.GroupBy(c => c.RemoteAlbum.Artist.Id, (artistId, downloadDecisions) =>
{
return downloadDecisions.OrderByDescending(decision => decision, new DownloadDecisionComparer(_delayProfileService));
})
.SelectMany(c => c)
.Union(decisions.Where(c => c.RemoteEpisode.Series == null))
.Union(decisions.Where(c => c.RemoteAlbum.Artist == null))
.ToList();
}
}

@ -1,4 +1,4 @@
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.DecisionEngine
@ -7,6 +7,6 @@ namespace NzbDrone.Core.DecisionEngine
{
RejectionType Type { get; }
Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria);
Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria);
}
}

@ -1,10 +1,9 @@
using System.Linq;
using System.Linq;
using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.Tv;
using System.Collections.Generic;
namespace NzbDrone.Core.DecisionEngine.Specifications
@ -12,29 +11,21 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
public class AcceptableSizeSpecification : IDecisionEngineSpecification
{
private readonly IQualityDefinitionService _qualityDefinitionService;
private readonly IEpisodeService _episodeService;
private readonly Logger _logger;
public AcceptableSizeSpecification(IQualityDefinitionService qualityDefinitionService, IEpisodeService episodeService, Logger logger)
public AcceptableSizeSpecification(IQualityDefinitionService qualityDefinitionService, Logger logger)
{
_qualityDefinitionService = qualityDefinitionService;
_episodeService = episodeService;
_logger = logger;
}
public RejectionType Type => RejectionType.Permanent;
public Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
public Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
{
_logger.Debug("Beginning size check for: {0}", subject);
var quality = subject.ParsedEpisodeInfo.Quality.Quality;
if (subject.ParsedEpisodeInfo.Special)
{
_logger.Debug("Special release found, skipping size check.");
return Decision.Accept();
}
var quality = subject.ParsedAlbumInfo.Quality.Quality;
if (subject.Release.Size == 0)
{
@ -43,20 +34,22 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
}
var qualityDefinition = _qualityDefinitionService.Get(quality);
var albumsDuration = subject.Albums.Sum(album => album.Duration) / 60000;
if (qualityDefinition.MinSize.HasValue)
{
var minSize = qualityDefinition.MinSize.Value.Megabytes();
//Multiply maxSize by Series.Runtime
minSize = minSize * subject.Series.Runtime * subject.Episodes.Count;
//Multiply minSize by Album.Duration
minSize = minSize * albumsDuration;
//If the parsed size is smaller than minSize we don't want it
if (subject.Release.Size < minSize)
{
var runtimeMessage = subject.Episodes.Count == 1 ? $"{subject.Series.Runtime}min" : $"{subject.Episodes.Count}x {subject.Series.Runtime}min";
var runtimeMessage = $"{albumsDuration}min";
_logger.Debug("Item: {0}, Size: {1} is smaller than minimum allowed size ({2} bytes for {3}), rejecting.", subject, subject.Release.Size, minSize, runtimeMessage);
return Decision.Reject("{0} is smaller than minimum allowed {1} (for {2})", subject.Release.Size.SizeSuffix(), minSize.SizeSuffix(), runtimeMessage);
_logger.Debug("Item: {0}, Size: {1} is smaller than minimum allowed size ({2} bytes), rejecting.", subject, subject.Release.Size, minSize);
return Decision.Reject("{0} is smaller than minimum allowed {1}", subject.Release.Size.SizeSuffix(), minSize.SizeSuffix());
}
}
if (!qualityDefinition.MaxSize.HasValue || qualityDefinition.MaxSize.Value == 0)
@ -67,40 +60,16 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
{
var maxSize = qualityDefinition.MaxSize.Value.Megabytes();
//Multiply maxSize by Series.Runtime
maxSize = maxSize * subject.Series.Runtime * subject.Episodes.Count;
if (subject.Episodes.Count == 1)
{
Episode episode = subject.Episodes.First();
List<Episode> seasonEpisodes;
var seasonSearchCriteria = searchCriteria as SeasonSearchCriteria;
if (seasonSearchCriteria != null && !seasonSearchCriteria.Series.UseSceneNumbering && seasonSearchCriteria.Episodes.Any(v => v.Id == episode.Id))
{
seasonEpisodes = (searchCriteria as SeasonSearchCriteria).Episodes;
}
else
{
seasonEpisodes = _episodeService.GetEpisodesBySeason(episode.SeriesId, episode.SeasonNumber);
}
//Ensure that this is either the first episode
//or is the last episode in a season that has 10 or more episodes
if (seasonEpisodes.First().Id == episode.Id || (seasonEpisodes.Count() >= 10 && seasonEpisodes.Last().Id == episode.Id))
{
_logger.Debug("Possible double episode, doubling allowed size.");
maxSize = maxSize * 2;
}
}
//Multiply maxSize by Album.Duration
maxSize = maxSize * albumsDuration;
//If the parsed size is greater than maxSize we don't want it
if (subject.Release.Size > maxSize)
{
var runtimeMessage = subject.Episodes.Count == 1 ? $"{subject.Series.Runtime}min" : $"{subject.Episodes.Count}x {subject.Series.Runtime}min";
var runtimeMessage = $"{albumsDuration}min";
_logger.Debug("Item: {0}, Size: {1} is greater than maximum allowed size ({2} for {3}), rejecting.", subject, subject.Release.Size, maxSize, runtimeMessage);
return Decision.Reject("{0} is larger than maximum allowed {1} (for {2})", subject.Release.Size.SizeSuffix(), maxSize.SizeSuffix(), runtimeMessage);
_logger.Debug("Item: {0}, Size: {1} is greater than maximum allowed size ({2}), rejecting.", subject, subject.Release.Size, maxSize);
return Decision.Reject("{0} is larger than maximum allowed {1}", subject.Release.Size.SizeSuffix(), maxSize.SizeSuffix());
}
}

@ -1,59 +0,0 @@
using System.Linq;
using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.DecisionEngine.Specifications
{
public class AnimeVersionUpgradeSpecification : IDecisionEngineSpecification
{
private readonly QualityUpgradableSpecification _qualityUpgradableSpecification;
private readonly Logger _logger;
public AnimeVersionUpgradeSpecification(QualityUpgradableSpecification qualityUpgradableSpecification, Logger logger)
{
_qualityUpgradableSpecification = qualityUpgradableSpecification;
_logger = logger;
}
public RejectionType Type => RejectionType.Permanent;
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
{
var releaseGroup = subject.ParsedEpisodeInfo.ReleaseGroup;
if (subject.Series.SeriesType != SeriesTypes.Anime)
{
return Decision.Accept();
}
foreach (var file in subject.Episodes.Where(c => c.EpisodeFileId != 0).Select(c => c.EpisodeFile.Value))
{
if (_qualityUpgradableSpecification.IsRevisionUpgrade(file.Quality, subject.ParsedEpisodeInfo.Quality))
{
if (file.ReleaseGroup.IsNullOrWhiteSpace())
{
_logger.Debug("Unable to compare release group, existing file's release group is unknown");
return Decision.Reject("Existing release group is unknown");
}
if (releaseGroup.IsNullOrWhiteSpace())
{
_logger.Debug("Unable to compare release group, release's release group is unknown");
return Decision.Reject("Release group is unknown");
}
if (file.ReleaseGroup != releaseGroup)
{
_logger.Debug("Existing Release group is: {0} - release's release group is: {1}", file.ReleaseGroup, releaseGroup);
return Decision.Reject("{0} does not match existing release group {1}", releaseGroup, file.ReleaseGroup);
}
}
}
return Decision.Accept();
}
}
}

@ -1,4 +1,4 @@
using NLog;
using NLog;
using NzbDrone.Core.Blacklisting;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model;
@ -18,9 +18,9 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
public RejectionType Type => RejectionType.Permanent;
public Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
public Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
{
if (_blacklistService.Blacklisted(subject.Series.Id, subject.Release))
if (_blacklistService.Blacklisted(subject.Artist.Id, subject.Release))
{
_logger.Debug("{0} is blacklisted, rejecting.", subject.Release.Title);
return Decision.Reject("Release is blacklisted");

@ -1,39 +1,46 @@
using System.Linq;
using System;
using System.Linq;
using NLog;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.MediaFiles;
namespace NzbDrone.Core.DecisionEngine.Specifications
{
public class CutoffSpecification : IDecisionEngineSpecification
{
private readonly QualityUpgradableSpecification _qualityUpgradableSpecification;
private readonly IMediaFileService _mediaFileService;
private readonly Logger _logger;
public CutoffSpecification(QualityUpgradableSpecification qualityUpgradableSpecification, Logger logger)
public CutoffSpecification(QualityUpgradableSpecification qualityUpgradableSpecification, Logger logger, IMediaFileService mediaFileService)
{
_qualityUpgradableSpecification = qualityUpgradableSpecification;
_logger = logger;
_mediaFileService = mediaFileService;
}
public RejectionType Type => RejectionType.Permanent;
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
{
foreach (var file in subject.Episodes.Where(c => c.EpisodeFileId != 0).Select(c => c.EpisodeFile.Value))
foreach (var album in subject.Albums)
{
if (file == null)
var trackFiles = _mediaFileService.GetFilesByAlbum(album.ArtistId, album.Id);
if (trackFiles.Any())
{
_logger.Debug("File is no longer available, skipping this file.");
continue;
}
var lowestQuality = trackFiles.Select(c => c.Quality).OrderBy(c => c.Quality.Id).First();
_logger.Debug("Comparing file quality with report. Existing file is {0}", file.Quality);
_logger.Debug("Comparing file quality with report. Existing file is {0}", lowestQuality);
if (!_qualityUpgradableSpecification.CutoffNotMet(subject.Series.Profile, file.Quality, subject.ParsedEpisodeInfo.Quality))
if (!_qualityUpgradableSpecification.CutoffNotMet(subject.Artist.Profile, lowestQuality, subject.ParsedAlbumInfo.Quality))
{
_logger.Debug("Cutoff already met, rejecting.");
return Decision.Reject("Existing file meets cutoff: {0}", subject.Series.Profile.Value.Cutoff);
return Decision.Reject("Existing file meets cutoff: {0}", subject.Artist.Profile.Value.Cutoff);
}
}
}

@ -0,0 +1,26 @@
using System;
using NLog;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Common.Extensions;
using System.Linq;
namespace NzbDrone.Core.DecisionEngine.Specifications
{
public class DiscographySpecification : IDecisionEngineSpecification
{
private readonly Logger _logger;
public DiscographySpecification(Logger logger)
{
_logger = logger;
}
public RejectionType Type => RejectionType.Permanent;
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
{
throw new NotImplementedException();
}
}
}

@ -1,40 +0,0 @@
using System;
using NLog;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Common.Extensions;
using System.Linq;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.DecisionEngine.Specifications
{
public class FullSeasonSpecification : IDecisionEngineSpecification
{
private readonly Logger _logger;
private readonly IEpisodeService _episodeService;
public FullSeasonSpecification(Logger logger, IEpisodeService episodeService)
{
_logger = logger;
_episodeService = episodeService;
}
public RejectionType Type => RejectionType.Permanent;
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
{
if (subject.ParsedEpisodeInfo.FullSeason)
{
_logger.Debug("Checking if all episodes in full season release have aired. {0}", subject.Release.Title);
if (subject.Episodes.Any(e => !e.AirDateUtc.HasValue || e.AirDateUtc.Value.After(DateTime.UtcNow)))
{
_logger.Debug("Full season release {0} rejected. All episodes haven't aired yet.", subject.Release.Title);
return Decision.Reject("Full season release rejected. All episodes haven't aired yet.");
}
}
return Decision.Accept();
}
}
}

@ -1,4 +1,4 @@
using NLog;
using NLog;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model;
@ -15,16 +15,16 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
public RejectionType Type => RejectionType.Permanent;
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
{
var wantedLanguage = subject.Series.Profile.Value.Language;
var wantedLanguage = subject.Artist.Profile.Value.Language;
_logger.Debug("Checking if report meets language requirements. {0}", subject.ParsedEpisodeInfo.Language);
_logger.Debug("Checking if report meets language requirements. {0}", subject.ParsedAlbumInfo.Language);
if (subject.ParsedEpisodeInfo.Language != wantedLanguage)
if (subject.ParsedAlbumInfo.Language != wantedLanguage)
{
_logger.Debug("Report Language: {0} rejected because it is not wanted, wanted {1}", subject.ParsedEpisodeInfo.Language, wantedLanguage);
return Decision.Reject("{0} is wanted, but found {1}", wantedLanguage, subject.ParsedEpisodeInfo.Language);
_logger.Debug("Report Language: {0} rejected because it is not wanted, wanted {1}", subject.ParsedAlbumInfo.Language, wantedLanguage);
return Decision.Reject("{0} is wanted, but found {1}", wantedLanguage, subject.ParsedAlbumInfo.Language);
}
return Decision.Accept();

@ -18,7 +18,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
public RejectionType Type => RejectionType.Temporary;
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
{
if (subject.Release.DownloadProtocol != Indexers.DownloadProtocol.Usenet)
{

@ -1,4 +1,5 @@
using NLog;
using System;
using NLog;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model;
@ -15,9 +16,9 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
_logger = logger;
}
public Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
public Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
{
if (subject.Release.Title.ToLower().Contains("sample") && subject.Release.Size < 70.Megabytes())
if (subject.Release.Title.ToLower().Contains("sample") && subject.Release.Size < 20.Megabytes())
{
_logger.Debug("Sample release, rejecting.");
return Decision.Reject("Sample");
@ -25,5 +26,6 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
return Decision.Accept();
}
}
}

@ -1,4 +1,4 @@
using NLog;
using NLog;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model;
@ -20,20 +20,20 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
public RejectionType Type => RejectionType.Permanent;
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
{
var delayProfile = _delayProfileService.BestForTags(subject.Series.Tags);
var delayProfile = _delayProfileService.BestForTags(subject.Artist.Tags);
if (subject.Release.DownloadProtocol == DownloadProtocol.Usenet && !delayProfile.EnableUsenet)
{
_logger.Debug("[{0}] Usenet is not enabled for this series", subject.Release.Title);
return Decision.Reject("Usenet is not enabled for this series");
_logger.Debug("[{0}] Usenet is not enabled for this artist", subject.Release.Title);
return Decision.Reject("Usenet is not enabled for this artist");
}
if (subject.Release.DownloadProtocol == DownloadProtocol.Torrent && !delayProfile.EnableTorrent)
{
_logger.Debug("[{0}] Torrent is not enabled for this series", subject.Release.Title);
return Decision.Reject("Torrent is not enabled for this series");
_logger.Debug("[{0}] Torrent is not enabled for this artist", subject.Release.Title);
return Decision.Reject("Torrent is not enabled for this artist");
}
return Decision.Accept();

@ -1,4 +1,4 @@
using NLog;
using NLog;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model;
@ -15,13 +15,13 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
public RejectionType Type => RejectionType.Permanent;
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
{
_logger.Debug("Checking if report meets quality requirements. {0}", subject.ParsedEpisodeInfo.Quality);
if (!subject.Series.Profile.Value.Items.Exists(v => v.Allowed && v.Quality == subject.ParsedEpisodeInfo.Quality.Quality))
_logger.Debug("Checking if report meets quality requirements. {0}", subject.ParsedAlbumInfo.Quality);
if (!subject.Artist.Profile.Value.Items.Exists(v => v.Allowed && v.Quality == subject.ParsedAlbumInfo.Quality.Quality))
{
_logger.Debug("Quality {0} rejected by Series' quality profile", subject.ParsedEpisodeInfo.Quality);
return Decision.Reject("{0} is not wanted in profile", subject.ParsedEpisodeInfo.Quality.Quality);
_logger.Debug("Quality {0} rejected by Artist's quality profile", subject.ParsedAlbumInfo.Quality);
return Decision.Reject("{0} is not wanted in profile", subject.ParsedAlbumInfo.Quality.Quality);
}
return Decision.Accept();

@ -1,3 +1,4 @@
using System;
using System.Linq;
using NLog;
using NzbDrone.Core.IndexerSearch.Definitions;
@ -23,32 +24,33 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
public RejectionType Type => RejectionType.Permanent;
public Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
public Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
{
var queue = _queueService.GetQueue()
.Select(q => q.RemoteEpisode).ToList();
.Select(q => q.RemoteAlbum).ToList();
var matchingSeries = queue.Where(q => q.Series.Id == subject.Series.Id);
var matchingEpisode = matchingSeries.Where(q => q.Episodes.Select(e => e.Id).Intersect(subject.Episodes.Select(e => e.Id)).Any());
var matchingArtist = queue.Where(q => q.Artist.Id == subject.Artist.Id);
var matchingAlbum = matchingArtist.Where(q => q.Albums.Select(e => e.Id).Intersect(subject.Albums.Select(e => e.Id)).Any());
foreach (var remoteEpisode in matchingEpisode)
foreach (var remoteAlbum in matchingAlbum)
{
_logger.Debug("Checking if existing release in queue meets cutoff. Queued quality is: {0}", remoteEpisode.ParsedEpisodeInfo.Quality);
_logger.Debug("Checking if existing release in queue meets cutoff. Queued quality is: {0}", remoteAlbum.ParsedAlbumInfo.Quality);
if (!_qualityUpgradableSpecification.CutoffNotMet(subject.Series.Profile, remoteEpisode.ParsedEpisodeInfo.Quality, subject.ParsedEpisodeInfo.Quality))
if (!_qualityUpgradableSpecification.CutoffNotMet(subject.Artist.Profile, remoteAlbum.ParsedAlbumInfo.Quality, subject.ParsedAlbumInfo.Quality))
{
return Decision.Reject("Quality for release in queue already meets cutoff: {0}", remoteEpisode.ParsedEpisodeInfo.Quality);
return Decision.Reject("Quality for release in queue already meets cutoff: {0}", remoteAlbum.ParsedAlbumInfo.Quality);
}
_logger.Debug("Checking if release is higher quality than queued release. Queued quality is: {0}", remoteEpisode.ParsedEpisodeInfo.Quality);
_logger.Debug("Checking if release is higher quality than queued release. Queued quality is: {0}", remoteAlbum.ParsedAlbumInfo.Quality);
if (!_qualityUpgradableSpecification.IsUpgradable(subject.Series.Profile, remoteEpisode.ParsedEpisodeInfo.Quality, subject.ParsedEpisodeInfo.Quality))
if (!_qualityUpgradableSpecification.IsUpgradable(subject.Artist.Profile, remoteAlbum.ParsedAlbumInfo.Quality, subject.ParsedAlbumInfo.Quality))
{
return Decision.Reject("Quality for release in queue is of equal or higher preference: {0}", remoteEpisode.ParsedEpisodeInfo.Quality);
return Decision.Reject("Quality for release in queue is of equal or higher preference: {0}", remoteAlbum.ParsedAlbumInfo.Quality);
}
}
return Decision.Accept();
}
}
}

@ -1,4 +1,4 @@
using System.Linq;
using System.Linq;
using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.IndexerSearch.Definitions;
@ -8,9 +8,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
{
public class RawDiskSpecification : IDecisionEngineSpecification
{
private static readonly string[] _dvdContainerTypes = new[] { "vob", "iso" };
private static readonly string[] _blurayContainerTypes = new[] { "m2ts" };
private static readonly string[] _cdContainerTypes = new[] { "vob", "iso" };
private readonly Logger _logger;
@ -21,23 +19,17 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
public RejectionType Type => RejectionType.Permanent;
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
{
if (subject.Release == null || subject.Release.Container.IsNullOrWhiteSpace())
{
return Decision.Accept();
}
if (_dvdContainerTypes.Contains(subject.Release.Container.ToLower()))
{
_logger.Debug("Release contains raw DVD, rejecting.");
return Decision.Reject("Raw DVD release");
}
if (_blurayContainerTypes.Contains(subject.Release.Container.ToLower()))
if (_cdContainerTypes.Contains(subject.Release.Container.ToLower()))
{
_logger.Debug("Release contains raw Bluray, rejecting.");
return Decision.Reject("Raw Bluray release");
_logger.Debug("Release contains raw CD, rejecting.");
return Decision.Reject("Raw CD release");
}
return Decision.Accept();

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using NLog;
@ -22,12 +22,12 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
public RejectionType Type => RejectionType.Permanent;
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
{
_logger.Debug("Checking if release meets restrictions: {0}", subject);
var title = subject.Release.Title;
var restrictions = _restrictionService.AllForTags(subject.Series.Tags);
var restrictions = _restrictionService.AllForTags(subject.Artist.Tags);
var required = restrictions.Where(r => r.Required.IsNotNullOrWhiteSpace());
var ignored = restrictions.Where(r => r.Ignored.IsNotNullOrWhiteSpace());

@ -18,7 +18,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
public RejectionType Type => RejectionType.Permanent;
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
{
if (subject.Release.DownloadProtocol != Indexers.DownloadProtocol.Usenet)
{

@ -1,10 +1,11 @@
using System.Linq;
using System.Linq;
using NLog;
using NzbDrone.Core.Download.Pending;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Profiles.Delay;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.MediaFiles;
namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
{
@ -13,22 +14,25 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
private readonly IPendingReleaseService _pendingReleaseService;
private readonly IQualityUpgradableSpecification _qualityUpgradableSpecification;
private readonly IDelayProfileService _delayProfileService;
private readonly IMediaFileService _mediaFileService;
private readonly Logger _logger;
public DelaySpecification(IPendingReleaseService pendingReleaseService,
IQualityUpgradableSpecification qualityUpgradableSpecification,
IDelayProfileService delayProfileService,
IMediaFileService mediaFileService,
Logger logger)
{
_pendingReleaseService = pendingReleaseService;
_qualityUpgradableSpecification = qualityUpgradableSpecification;
_delayProfileService = delayProfileService;
_mediaFileService = mediaFileService;
_logger = logger;
}
public RejectionType Type => RejectionType.Temporary;
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
{
if (searchCriteria != null && searchCriteria.UserInvokedSearch)
{
@ -36,8 +40,8 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
return Decision.Accept();
}
var profile = subject.Series.Profile.Value;
var delayProfile = _delayProfileService.BestForTags(subject.Series.Tags);
var profile = subject.Artist.Profile.Value;
var delayProfile = _delayProfileService.BestForTags(subject.Artist.Tags);
var delay = delayProfile.GetProtocolDelay(subject.Release.DownloadProtocol);
var isPreferredProtocol = subject.Release.DownloadProtocol == delayProfile.PreferredProtocol;
@ -51,13 +55,18 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
if (isPreferredProtocol)
{
foreach (var file in subject.Episodes.Where(c => c.EpisodeFileId != 0).Select(c => c.EpisodeFile.Value))
foreach (var album in subject.Albums)
{
var upgradable = _qualityUpgradableSpecification.IsUpgradable(profile, file.Quality, subject.ParsedEpisodeInfo.Quality);
var trackFiles = _mediaFileService.GetFilesByAlbum(album.ArtistId, album.Id);
if (trackFiles.Any())
{
var lowestQuality = trackFiles.Select(c => c.Quality).OrderBy(c => c.Quality.Id).First();
var upgradable = _qualityUpgradableSpecification.IsUpgradable(profile, lowestQuality, subject.ParsedAlbumInfo.Quality);
if (upgradable)
{
var revisionUpgrade = _qualityUpgradableSpecification.IsRevisionUpgrade(file.Quality, subject.ParsedEpisodeInfo.Quality);
var revisionUpgrade = _qualityUpgradableSpecification.IsRevisionUpgrade(lowestQuality, subject.ParsedAlbumInfo.Quality);
if (revisionUpgrade)
{
@ -67,10 +76,11 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
}
}
}
}
// If quality meets or exceeds the best allowed quality in the profile accept it immediately
var bestQualityInProfile = new QualityModel(profile.LastAllowedQuality());
var isBestInProfile = comparer.Compare(subject.ParsedEpisodeInfo.Quality, bestQualityInProfile) >= 0;
var isBestInProfile = comparer.Compare(subject.ParsedAlbumInfo.Quality, bestQualityInProfile) >= 0;
if (isBestInProfile && isPreferredProtocol)
{
@ -78,9 +88,9 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
return Decision.Accept();
}
var episodeIds = subject.Episodes.Select(e => e.Id);
var albumIds = subject.Albums.Select(e => e.Id);
var oldest = _pendingReleaseService.OldestPendingRelease(subject.Series.Id, episodeIds);
var oldest = _pendingReleaseService.OldestPendingRelease(subject.Artist.Id, albumIds);
if (oldest != null && oldest.Release.AgeMinutes > delay)
{

@ -1,4 +1,4 @@
using System;
using System;
using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Configuration;
@ -28,7 +28,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
public RejectionType Type => RejectionType.Permanent;
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
{
if (searchCriteria != null)
{
@ -39,16 +39,16 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
var cdhEnabled = _configService.EnableCompletedDownloadHandling;
_logger.Debug("Performing history status check on report");
foreach (var episode in subject.Episodes)
foreach (var album in subject.Albums)
{
_logger.Debug("Checking current status of episode [{0}] in history", episode.Id);
var mostRecent = _historyService.MostRecentForEpisode(episode.Id);
_logger.Debug("Checking current status of album [{0}] in history", album.Id);
var mostRecent = _historyService.MostRecentForAlbum(album.Id);
if (mostRecent != null && mostRecent.EventType == HistoryEventType.Grabbed)
{
var recent = mostRecent.Date.After(DateTime.UtcNow.AddHours(-12));
var cutoffUnmet = _qualityUpgradableSpecification.CutoffNotMet(subject.Series.Profile, mostRecent.Quality, subject.ParsedEpisodeInfo.Quality);
var upgradeable = _qualityUpgradableSpecification.IsUpgradable(subject.Series.Profile, mostRecent.Quality, subject.ParsedEpisodeInfo.Quality);
var cutoffUnmet = _qualityUpgradableSpecification.CutoffNotMet(subject.Artist.Profile, mostRecent.Quality, subject.ParsedAlbumInfo.Quality);
var upgradeable = _qualityUpgradableSpecification.IsUpgradable(subject.Artist.Profile, mostRecent.Quality, subject.ParsedAlbumInfo.Quality);
if (!recent && cdhEnabled)
{

@ -1,22 +1,22 @@
using System.Linq;
using System.Linq;
using NLog;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
{
public class MonitoredEpisodeSpecification : IDecisionEngineSpecification
public class MonitoredAlbumSpecification : IDecisionEngineSpecification
{
private readonly Logger _logger;
public MonitoredEpisodeSpecification(Logger logger)
public MonitoredAlbumSpecification(Logger logger)
{
_logger = logger;
}
public RejectionType Type => RejectionType.Permanent;
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
{
if (searchCriteria != null)
{
@ -27,20 +27,20 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
}
}
if (!subject.Series.Monitored)
if (!subject.Artist.Monitored)
{
_logger.Debug("{0} is present in the DB but not tracked. skipping.", subject.Series);
return Decision.Reject("Series is not monitored");
_logger.Debug("{0} is present in the DB but not tracked. skipping.", subject.Artist);
return Decision.Reject("Artist is not monitored");
}
var monitoredCount = subject.Episodes.Count(episode => episode.Monitored);
if (monitoredCount == subject.Episodes.Count)
var monitoredCount = subject.Albums.Count(album => album.Monitored);
if (monitoredCount == subject.Albums.Count)
{
return Decision.Accept();
}
_logger.Debug("Only {0}/{1} episodes are monitored. skipping.", monitoredCount, subject.Episodes.Count);
return Decision.Reject("Episode is not monitored");
_logger.Debug("Only {0}/{1} albums are monitored. skipping.", monitoredCount, subject.Albums.Count);
return Decision.Reject("Album is not monitored");
}
}
}

@ -1,9 +1,10 @@
using System;
using System;
using System.Linq;
using NLog;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.MediaFiles;
namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
{
@ -11,29 +12,40 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
{
private readonly QualityUpgradableSpecification _qualityUpgradableSpecification;
private readonly IConfigService _configService;
private readonly IMediaFileService _mediaFileService;
private readonly Logger _logger;
public ProperSpecification(QualityUpgradableSpecification qualityUpgradableSpecification, IConfigService configService, Logger logger)
public ProperSpecification(QualityUpgradableSpecification qualityUpgradableSpecification, IConfigService configService, IMediaFileService mediaFileService, Logger logger)
{
_qualityUpgradableSpecification = qualityUpgradableSpecification;
_configService = configService;
_mediaFileService = mediaFileService;
_logger = logger;
}
public RejectionType Type => RejectionType.Permanent;
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
{
if (searchCriteria != null)
{
return Decision.Accept();
}
foreach (var file in subject.Episodes.Where(c => c.EpisodeFileId != 0).Select(c => c.EpisodeFile.Value))
foreach (var album in subject.Albums)
{
if (_qualityUpgradableSpecification.IsRevisionUpgrade(file.Quality, subject.ParsedEpisodeInfo.Quality))
var trackFiles = _mediaFileService.GetFilesByAlbum(album.ArtistId, album.Id);
if (trackFiles.Any())
{
var lowestQuality = trackFiles.Select(c => c.Quality).OrderBy(c => c.Quality.Id).First();
var dateAdded = trackFiles[0].DateAdded;
_logger.Debug("Comparing file quality with report. Existing file is {0}", lowestQuality);
if (_qualityUpgradableSpecification.IsRevisionUpgrade(lowestQuality, subject.ParsedAlbumInfo.Quality))
{
if (file.DateAdded < DateTime.Today.AddDays(-7))
if (dateAdded < DateTime.Today.AddDays(-7))
{
_logger.Debug("Proper for old file, rejecting: {0}", subject);
return Decision.Reject("Proper for old file");
@ -45,6 +57,8 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
return Decision.Reject("Proper downloading is disabled");
}
}
}
}
return Decision.Accept();

@ -1,31 +0,0 @@
using NLog;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.DecisionEngine.Specifications
{
public class SameEpisodesGrabSpecification : IDecisionEngineSpecification
{
private readonly SameEpisodesSpecification _sameEpisodesSpecification;
private readonly Logger _logger;
public SameEpisodesGrabSpecification(SameEpisodesSpecification sameEpisodesSpecification, Logger logger)
{
_sameEpisodesSpecification = sameEpisodesSpecification;
_logger = logger;
}
public RejectionType Type => RejectionType.Permanent;
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
{
if (_sameEpisodesSpecification.IsSatisfiedBy(subject.Episodes))
{
return Decision.Accept();
}
_logger.Debug("Episode file on disk contains more episodes than this release contains");
return Decision.Reject("Episode file on disk contains more episodes than this release contains");
}
}
}

@ -0,0 +1,28 @@
using System;
using NLog;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.DecisionEngine.Specifications
{
public class SameTracksGrabSpecification : IDecisionEngineSpecification
{
private readonly SameTracksSpecification _sameTracksSpecification;
private readonly Logger _logger;
public SameTracksGrabSpecification(SameTracksSpecification sameTracksSpecification, Logger logger)
{
_sameTracksSpecification = sameTracksSpecification;
_logger = logger;
}
public RejectionType Type => RejectionType.Permanent;
public Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
{
throw new NotImplementedException();
// TODO: Rework for Tracks if we can parse from release details.
}
}
}

@ -0,0 +1,40 @@
using System.Linq;
using NLog;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Music;
namespace NzbDrone.Core.DecisionEngine.Specifications.Search
{
public class AlbumRequestedSpecification : IDecisionEngineSpecification
{
private readonly Logger _logger;
public AlbumRequestedSpecification(Logger logger)
{
_logger = logger;
}
public RejectionType Type => RejectionType.Permanent;
public Decision IsSatisfiedBy(RemoteAlbum remoteAlbum, SearchCriteriaBase searchCriteria)
{
if (searchCriteria == null)
{
return Decision.Accept();
}
var criteriaAlbum = searchCriteria.Albums.Select(v => v.Id).ToList();
var remoteAlbums = remoteAlbum.Albums.Select(v => v.Id).ToList();
if (!criteriaAlbum.Intersect(remoteAlbums).Any())
{
_logger.Debug("Release rejected since the album wasn't requested: {0}", remoteAlbum.ParsedAlbumInfo);
return Decision.Reject("Album wasn't requested");
}
return Decision.Accept();
}
}
}

@ -0,0 +1,36 @@
using NLog;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.DecisionEngine.Specifications.Search
{
public class ArtistSpecification : IDecisionEngineSpecification
{
private readonly Logger _logger;
public ArtistSpecification(Logger logger)
{
_logger = logger;
}
public RejectionType Type => RejectionType.Permanent;
public Decision IsSatisfiedBy(RemoteAlbum remoteAlbum, SearchCriteriaBase searchCriteria)
{
if (searchCriteria == null)
{
return Decision.Accept();
}
_logger.Debug("Checking if artist matches searched artist");
if (remoteAlbum.Artist.Id != searchCriteria.Artist.Id)
{
_logger.Debug("Artist {0} does not match {1}", remoteAlbum.Artist, searchCriteria.Artist);
return Decision.Reject("Wrong artist");
}
return Decision.Accept();
}
}
}

@ -0,0 +1,26 @@
using System;
using NLog;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.DecisionEngine.Specifications.Search
{
public class DailyAudioMatchSpecification : IDecisionEngineSpecification
{
private readonly Logger _logger;
public DailyAudioMatchSpecification(Logger logger)
{
_logger = logger;
}
public RejectionType Type => RejectionType.Permanent;
public Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
{
throw new NotImplementedException();
// TODO Rework for Daily Audio/Podcasts
}
}
}

@ -1,43 +0,0 @@
using NLog;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.DecisionEngine.Specifications.Search
{
public class DailyEpisodeMatchSpecification : IDecisionEngineSpecification
{
private readonly Logger _logger;
private readonly IEpisodeService _episodeService;
public DailyEpisodeMatchSpecification(Logger logger, IEpisodeService episodeService)
{
_logger = logger;
_episodeService = episodeService;
}
public RejectionType Type => RejectionType.Permanent;
public Decision IsSatisfiedBy(RemoteEpisode remoteEpisode, SearchCriteriaBase searchCriteria)
{
if (searchCriteria == null)
{
return Decision.Accept();
}
var dailySearchSpec = searchCriteria as DailyEpisodeSearchCriteria;
if (dailySearchSpec == null) return Decision.Accept();
var episode = _episodeService.GetEpisode(dailySearchSpec.Series.Id, dailySearchSpec.AirDate.ToString(Episode.AIR_DATE_FORMAT));
if (!remoteEpisode.ParsedEpisodeInfo.IsDaily || remoteEpisode.ParsedEpisodeInfo.AirDate != episode.AirDate)
{
_logger.Debug("Episode AirDate does not match searched episode number, skipping.");
return Decision.Reject("Episode does not match");
}
return Decision.Accept();
}
}
}

@ -1,39 +0,0 @@
using System.Linq;
using NLog;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.DecisionEngine.Specifications.Search
{
public class EpisodeRequestedSpecification : IDecisionEngineSpecification
{
private readonly Logger _logger;
public EpisodeRequestedSpecification(Logger logger)
{
_logger = logger;
}
public RejectionType Type => RejectionType.Permanent;
public Decision IsSatisfiedBy(RemoteEpisode remoteEpisode, SearchCriteriaBase searchCriteria)
{
if (searchCriteria == null)
{
return Decision.Accept();
}
var criteriaEpisodes = searchCriteria.Episodes.Select(v => v.Id).ToList();
var remoteEpisodes = remoteEpisode.Episodes.Select(v => v.Id).ToList();
if (!criteriaEpisodes.Intersect(remoteEpisodes).Any())
{
_logger.Debug("Release rejected since the episode wasn't requested: {0}", remoteEpisode.ParsedEpisodeInfo);
return Decision.Reject("Episode wasn't requested");
}
return Decision.Accept();
}
}
}

@ -1,3 +1,4 @@
using System;
using NLog;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model;
@ -15,23 +16,9 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.Search
public RejectionType Type => RejectionType.Permanent;
public Decision IsSatisfiedBy(RemoteEpisode remoteEpisode, SearchCriteriaBase searchCriteria)
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
{
if (searchCriteria == null)
{
return Decision.Accept();
}
var singleEpisodeSpec = searchCriteria as SeasonSearchCriteria;
if (singleEpisodeSpec == null) return Decision.Accept();
if (singleEpisodeSpec.SeasonNumber != remoteEpisode.ParsedEpisodeInfo.SeasonNumber)
{
_logger.Debug("Season number does not match searched season number, skipping.");
return Decision.Reject("Wrong season");
}
return Decision.Accept();
throw new NotImplementedException();
}
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save