/src/NzbDrone.Core.Test/DecisionEngineTests/QueueSpecificationFixture.cs

https://github.com/NzbDrone/NzbDrone · C# · 460 lines · 394 code · 66 blank · 0 comment · 0 complexity · f0f71757810b2ec536b847abdb8a03f4 MD5 · raw file

  1. using System.Collections.Generic;
  2. using System.Linq;
  3. using FizzWare.NBuilder;
  4. using FluentAssertions;
  5. using NUnit.Framework;
  6. using NzbDrone.Core.DecisionEngine.Specifications;
  7. using NzbDrone.Core.Download.TrackedDownloads;
  8. using NzbDrone.Core.Profiles.Languages;
  9. using NzbDrone.Core.Parser.Model;
  10. using NzbDrone.Core.Profiles.Qualities;
  11. using NzbDrone.Core.Qualities;
  12. using NzbDrone.Core.Queue;
  13. using NzbDrone.Core.Tv;
  14. using NzbDrone.Core.Test.Framework;
  15. using NzbDrone.Core.Languages;
  16. namespace NzbDrone.Core.Test.DecisionEngineTests
  17. {
  18. [TestFixture]
  19. public class QueueSpecificationFixture : CoreTest<QueueSpecification>
  20. {
  21. private Series _series;
  22. private Episode _episode;
  23. private RemoteEpisode _remoteEpisode;
  24. private Series _otherSeries;
  25. private Episode _otherEpisode;
  26. private ReleaseInfo _releaseInfo;
  27. [SetUp]
  28. public void Setup()
  29. {
  30. Mocker.Resolve<UpgradableSpecification>();
  31. _series = Builder<Series>.CreateNew()
  32. .With(e => e.QualityProfile = new QualityProfile
  33. {
  34. UpgradeAllowed = true,
  35. Items = Qualities.QualityFixture.GetDefaultQualities()
  36. })
  37. .With(l => l.LanguageProfile = new LanguageProfile
  38. {
  39. Languages = Languages.LanguageFixture.GetDefaultLanguages(),
  40. UpgradeAllowed = true,
  41. Cutoff = Language.Spanish
  42. })
  43. .Build();
  44. _episode = Builder<Episode>.CreateNew()
  45. .With(e => e.SeriesId = _series.Id)
  46. .Build();
  47. _otherSeries = Builder<Series>.CreateNew()
  48. .With(s => s.Id = 2)
  49. .Build();
  50. _otherEpisode = Builder<Episode>.CreateNew()
  51. .With(e => e.SeriesId = _otherSeries.Id)
  52. .With(e => e.Id = 2)
  53. .With(e => e.SeasonNumber = 2)
  54. .With(e => e.EpisodeNumber = 2)
  55. .Build();
  56. _releaseInfo = Builder<ReleaseInfo>.CreateNew()
  57. .Build();
  58. _remoteEpisode = Builder<RemoteEpisode>.CreateNew()
  59. .With(r => r.Series = _series)
  60. .With(r => r.Episodes = new List<Episode> { _episode })
  61. .With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.DVD) , Language = Language.Spanish})
  62. .With(r => r.PreferredWordScore = 0)
  63. .Build();
  64. }
  65. private void GivenEmptyQueue()
  66. {
  67. Mocker.GetMock<IQueueService>()
  68. .Setup(s => s.GetQueue())
  69. .Returns(new List<Queue.Queue>());
  70. }
  71. private void GivenQueue(IEnumerable<RemoteEpisode> remoteEpisodes, TrackedDownloadState trackedDownloadState = TrackedDownloadState.Downloading)
  72. {
  73. var queue = remoteEpisodes.Select(remoteEpisode => new Queue.Queue
  74. {
  75. RemoteEpisode = remoteEpisode,
  76. TrackedDownloadState = trackedDownloadState
  77. });
  78. Mocker.GetMock<IQueueService>()
  79. .Setup(s => s.GetQueue())
  80. .Returns(queue.ToList());
  81. }
  82. [Test]
  83. public void should_return_true_when_queue_is_empty()
  84. {
  85. GivenEmptyQueue();
  86. Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
  87. }
  88. [Test]
  89. public void should_return_true_when_series_doesnt_match()
  90. {
  91. var remoteEpisode = Builder<RemoteEpisode>.CreateNew()
  92. .With(r => r.Series = _otherSeries)
  93. .With(r => r.Episodes = new List<Episode> { _episode })
  94. .With(r => r.Release = _releaseInfo)
  95. .Build();
  96. GivenQueue(new List<RemoteEpisode> { remoteEpisode });
  97. Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
  98. }
  99. [Test]
  100. public void should_return_false_if_everything_is_the_same()
  101. {
  102. _series.QualityProfile.Value.Cutoff = Quality.Bluray1080p.Id;
  103. var remoteEpisode = Builder<RemoteEpisode>.CreateNew()
  104. .With(r => r.Series = _series)
  105. .With(r => r.Episodes = new List<Episode> { _episode })
  106. .With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
  107. {
  108. Quality = new QualityModel(Quality.DVD),
  109. Language = Language.Spanish
  110. })
  111. .With(r => r.Release = _releaseInfo)
  112. .Build();
  113. GivenQueue(new List<RemoteEpisode> { remoteEpisode });
  114. Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
  115. }
  116. [Test]
  117. public void should_return_true_when_quality_in_queue_is_lower()
  118. {
  119. _series.QualityProfile.Value.Cutoff = Quality.Bluray1080p.Id;
  120. _series.LanguageProfile.Value.Cutoff = Language.Spanish;
  121. var remoteEpisode = Builder<RemoteEpisode>.CreateNew()
  122. .With(r => r.Series = _series)
  123. .With(r => r.Episodes = new List<Episode> { _episode })
  124. .With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
  125. {
  126. Quality = new QualityModel(Quality.SDTV),
  127. Language = Language.Spanish
  128. })
  129. .With(r => r.Release = _releaseInfo)
  130. .Build();
  131. GivenQueue(new List<RemoteEpisode> { remoteEpisode });
  132. Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
  133. }
  134. [Test]
  135. public void should_return_true_when_quality_in_queue_is_lower_but_language_is_higher()
  136. {
  137. _series.QualityProfile.Value.Cutoff = Quality.Bluray1080p.Id;
  138. _series.LanguageProfile.Value.Cutoff = Language.Spanish;
  139. var remoteEpisode = Builder<RemoteEpisode>.CreateNew()
  140. .With(r => r.Series = _series)
  141. .With(r => r.Episodes = new List<Episode> { _episode })
  142. .With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
  143. {
  144. Quality = new QualityModel(Quality.SDTV),
  145. Language = Language.English
  146. })
  147. .With(r => r.Release = _releaseInfo)
  148. .Build();
  149. GivenQueue(new List<RemoteEpisode> { remoteEpisode });
  150. Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
  151. }
  152. [Test]
  153. public void should_return_true_when_episode_doesnt_match()
  154. {
  155. var remoteEpisode = Builder<RemoteEpisode>.CreateNew()
  156. .With(r => r.Series = _series)
  157. .With(r => r.Episodes = new List<Episode> { _otherEpisode })
  158. .With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
  159. {
  160. Quality = new QualityModel(Quality.DVD)
  161. })
  162. .With(r => r.Release = _releaseInfo)
  163. .Build();
  164. GivenQueue(new List<RemoteEpisode> { remoteEpisode });
  165. Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
  166. }
  167. [Test]
  168. public void should_return_true_when_qualities_are_the_same_and_languages_are_the_same_with_higher_preferred_word_score()
  169. {
  170. _remoteEpisode.PreferredWordScore = 1;
  171. var remoteEpisode = Builder<RemoteEpisode>.CreateNew()
  172. .With(r => r.Series = _series)
  173. .With(r => r.Episodes = new List<Episode> { _episode })
  174. .With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
  175. {
  176. Quality = new QualityModel(Quality.DVD),
  177. Language = Language.Spanish,
  178. })
  179. .With(r => r.Release = _releaseInfo)
  180. .Build();
  181. GivenQueue(new List<RemoteEpisode> { remoteEpisode });
  182. Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
  183. }
  184. [Test]
  185. public void should_return_false_when_qualities_are_the_same_and_languages_are_the_same()
  186. {
  187. var remoteEpisode = Builder<RemoteEpisode>.CreateNew()
  188. .With(r => r.Series = _series)
  189. .With(r => r.Episodes = new List<Episode> { _episode })
  190. .With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
  191. {
  192. Quality = new QualityModel(Quality.DVD),
  193. Language = Language.Spanish,
  194. })
  195. .With(r => r.Release = _releaseInfo)
  196. .Build();
  197. GivenQueue(new List<RemoteEpisode> { remoteEpisode });
  198. Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
  199. }
  200. [Test]
  201. public void should_return_true_when_qualities_are_the_same_but_language_is_better()
  202. {
  203. var remoteEpisode = Builder<RemoteEpisode>.CreateNew()
  204. .With(r => r.Series = _series)
  205. .With(r => r.Episodes = new List<Episode> { _episode })
  206. .With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
  207. {
  208. Quality = new QualityModel(Quality.DVD),
  209. Language = Language.English,
  210. })
  211. .With(r => r.Release = _releaseInfo)
  212. .Build();
  213. GivenQueue(new List<RemoteEpisode> { remoteEpisode });
  214. Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
  215. }
  216. [Test]
  217. public void should_return_true_when_quality_is_better_language_is_better_and_upgrade_allowed_is_false_for_quality_profile()
  218. {
  219. _series.QualityProfile.Value.Cutoff = Quality.Bluray1080p.Id;
  220. _series.QualityProfile.Value.UpgradeAllowed = false;
  221. var remoteEpisode = Builder<RemoteEpisode>.CreateNew()
  222. .With(r => r.Series = _series)
  223. .With(r => r.Episodes = new List<Episode> { _episode })
  224. .With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
  225. {
  226. Quality = new QualityModel(Quality.SDTV),
  227. Language = Language.English
  228. })
  229. .With(r => r.Release = _releaseInfo)
  230. .Build();
  231. GivenQueue(new List<RemoteEpisode> { remoteEpisode });
  232. Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
  233. }
  234. [Test]
  235. public void should_return_false_when_quality_in_queue_is_better()
  236. {
  237. _series.QualityProfile.Value.Cutoff = Quality.Bluray1080p.Id;
  238. var remoteEpisode = Builder<RemoteEpisode>.CreateNew()
  239. .With(r => r.Series = _series)
  240. .With(r => r.Episodes = new List<Episode> { _episode })
  241. .With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
  242. {
  243. Quality = new QualityModel(Quality.HDTV720p),
  244. Language = Language.English
  245. })
  246. .With(r => r.Release = _releaseInfo)
  247. .Build();
  248. GivenQueue(new List<RemoteEpisode> { remoteEpisode });
  249. Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
  250. }
  251. [Test]
  252. public void should_return_false_if_matching_multi_episode_is_in_queue()
  253. {
  254. var remoteEpisode = Builder<RemoteEpisode>.CreateNew()
  255. .With(r => r.Series = _series)
  256. .With(r => r.Episodes = new List<Episode> { _episode, _otherEpisode })
  257. .With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
  258. {
  259. Quality = new QualityModel(Quality.HDTV720p),
  260. Language = Language.English
  261. })
  262. .With(r => r.Release = _releaseInfo)
  263. .Build();
  264. GivenQueue(new List<RemoteEpisode> { remoteEpisode });
  265. Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
  266. }
  267. [Test]
  268. public void should_return_false_if_multi_episode_has_one_episode_in_queue()
  269. {
  270. var remoteEpisode = Builder<RemoteEpisode>.CreateNew()
  271. .With(r => r.Series = _series)
  272. .With(r => r.Episodes = new List<Episode> { _episode })
  273. .With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
  274. {
  275. Quality = new QualityModel(Quality.HDTV720p),
  276. Language = Language.English
  277. })
  278. .With(r => r.Release = _releaseInfo)
  279. .Build();
  280. _remoteEpisode.Episodes.Add(_otherEpisode);
  281. GivenQueue(new List<RemoteEpisode> { remoteEpisode });
  282. Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
  283. }
  284. [Test]
  285. public void should_return_false_if_multi_part_episode_is_already_in_queue()
  286. {
  287. var remoteEpisode = Builder<RemoteEpisode>.CreateNew()
  288. .With(r => r.Series = _series)
  289. .With(r => r.Episodes = new List<Episode> { _episode, _otherEpisode })
  290. .With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
  291. {
  292. Quality = new QualityModel(Quality.HDTV720p),
  293. Language = Language.English
  294. })
  295. .With(r => r.Release = _releaseInfo)
  296. .Build();
  297. _remoteEpisode.Episodes.Add(_otherEpisode);
  298. GivenQueue(new List<RemoteEpisode> { remoteEpisode });
  299. Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
  300. }
  301. [Test]
  302. public void should_return_false_if_multi_part_episode_has_two_episodes_in_queue()
  303. {
  304. var remoteEpisodes = Builder<RemoteEpisode>.CreateListOfSize(2)
  305. .All()
  306. .With(r => r.Series = _series)
  307. .With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
  308. {
  309. Quality =
  310. new QualityModel(
  311. Quality.HDTV720p),
  312. Language = Language.English
  313. })
  314. .With(r => r.Release = _releaseInfo)
  315. .TheFirst(1)
  316. .With(r => r.Episodes = new List<Episode> { _episode })
  317. .TheNext(1)
  318. .With(r => r.Episodes = new List<Episode> { _otherEpisode })
  319. .Build();
  320. _remoteEpisode.Episodes.Add(_otherEpisode);
  321. GivenQueue(remoteEpisodes);
  322. Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
  323. }
  324. [Test]
  325. public void should_return_false_if_quality_and_language_in_queue_meets_cutoff()
  326. {
  327. _series.QualityProfile.Value.Cutoff = _remoteEpisode.ParsedEpisodeInfo.Quality.Quality.Id;
  328. var remoteEpisode = Builder<RemoteEpisode>.CreateNew()
  329. .With(r => r.Series = _series)
  330. .With(r => r.Episodes = new List<Episode> { _episode })
  331. .With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
  332. {
  333. Quality = new QualityModel(Quality.HDTV720p),
  334. Language = Language.Spanish
  335. })
  336. .With(r => r.Release = _releaseInfo)
  337. .Build();
  338. GivenQueue(new List<RemoteEpisode> { remoteEpisode });
  339. Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
  340. }
  341. [Test]
  342. public void should_return_false_when_quality_are_the_same_language_is_better_and_upgrade_allowed_is_false_for_language_profile()
  343. {
  344. _series.LanguageProfile.Value.UpgradeAllowed = false;
  345. var remoteEpisode = Builder<RemoteEpisode>.CreateNew()
  346. .With(r => r.Series = _series)
  347. .With(r => r.Episodes = new List<Episode> { _episode })
  348. .With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
  349. {
  350. Quality = new QualityModel(Quality.DVD),
  351. Language = Language.English
  352. })
  353. .With(r => r.Release = _releaseInfo)
  354. .Build();
  355. GivenQueue(new List<RemoteEpisode> { remoteEpisode });
  356. Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
  357. }
  358. [Test]
  359. public void should_return_false_when_quality_is_better_languages_are_the_same_and_upgrade_allowed_is_false_for_quality_profile()
  360. {
  361. _series.QualityProfile.Value.Cutoff = Quality.Bluray1080p.Id;
  362. _series.QualityProfile.Value.UpgradeAllowed = false;
  363. var remoteEpisode = Builder<RemoteEpisode>.CreateNew()
  364. .With(r => r.Series = _series)
  365. .With(r => r.Episodes = new List<Episode> { _episode })
  366. .With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
  367. {
  368. Quality = new QualityModel(Quality.Bluray1080p),
  369. Language = Language.Spanish
  370. })
  371. .With(r => r.Release = _releaseInfo)
  372. .Build();
  373. GivenQueue(new List<RemoteEpisode> { remoteEpisode });
  374. Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
  375. }
  376. [Test]
  377. public void should_return_true_if_everything_is_the_same_for_failed_pending()
  378. {
  379. _series.QualityProfile.Value.Cutoff = Quality.Bluray1080p.Id;
  380. var remoteEpisode = Builder<RemoteEpisode>.CreateNew()
  381. .With(r => r.Series = _series)
  382. .With(r => r.Episodes = new List<Episode> { _episode })
  383. .With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
  384. {
  385. Quality = new QualityModel(Quality.DVD),
  386. Language = Language.Spanish
  387. })
  388. .With(r => r.Release = _releaseInfo)
  389. .Build();
  390. GivenQueue(new List<RemoteEpisode> { remoteEpisode }, TrackedDownloadState.FailedPending);
  391. Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
  392. }
  393. }
  394. }