Added tests and refactored TorrentRss code.

This commit is contained in:
Taloth Saldono
2015-05-14 22:57:45 +02:00
parent 9d7522cc15
commit ba2da07c2f
71 changed files with 1188 additions and 5435 deletions
@@ -4,7 +4,7 @@ using NLog;
using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.Indexers.TorrentRssIndexer;
using NzbDrone.Core.Indexers.TorrentRss;
using NzbDrone.Core.Parser;
using NLog.Config;
using NLog.Targets;
@@ -1,88 +1,54 @@
using Moq;
using System;
using System.Linq;
using FluentAssertions;
using Moq;
using NLog;
using NUnit.Framework;
using NzbDrone.Common.Cache;
using NzbDrone.Common.Http;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.Indexers.TorrentRssIndexer;
using NzbDrone.Core.Indexers.TorrentRss;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common;
using System;
using System.Linq;
using FluentAssertions;
namespace NzbDrone.Core.Test.IndexerTests.TorrentRssIndexerTests
{
using NzbDrone.Common.Cache;
[TestFixture]
public class TorrentRssIndexerFixture : CoreTest<TestTorrentRssIndexer>
{
private readonly Logger _logger = LogManager.GetCurrentClassLogger();
private const string _indexerUrl = "http://my.indexer.tv/recent";
[SetUp]
public void Setup()
{
Mocker.SetConstant<IHttpClient>(Mocker.GetMock<IHttpClient>().Object);
Mocker.SetConstant<ICacheManager>(Mocker.Resolve<CacheManager>());
Mocker.SetConstant<ITorrentRssSettingsDetector>(Mocker.Resolve<TorrentRssSettingsDetector>());
Mocker.SetConstant<ITorrentRssParserFactory>(Mocker.Resolve<TorrentRssParserFactory>());
Subject.Definition = new IndexerDefinition()
{
Name = "TorrentRssIndexer",
Settings = new TorrentRssIndexerSettings() { },
Settings = new TorrentRssIndexerSettings() { BaseUrl = _indexerUrl },
};
Mocker.SetConstant<ITorrentRssParserFactory>(new TorrentRssParserFactory(Mocker.Resolve<CacheManager>(), new TorrentRssSettingsDetector(new HttpClient(new CacheManager(), TestLogger), TestLogger), TestLogger));
}
[TestCase("https://www.ezrss.it/", "Eztv.xml")]
[TestCase("https://www.speed.cd/", "speed.cd.xml")]
//[TestCase("https://www.showrss.info/", "showrss.info.xml")]
[TestCase("https://immortalseed.me/rss.php?secret_key=12345678910&feedtype=download&timezone=-12&showrows=50&categories=8", "ImmortalSeed.xml")]
public void should_detect_and_parse_recent_feed(string baseUrl, string rssXmlFile)
private void GivenRecentFeedResponse(string rssXmlFile)
{
Subject.Definition.Settings = new TorrentRssIndexerSettings { BaseUrl = baseUrl };
var recentFeed = ReadAllText(@"Files/RSS/" + rssXmlFile);
var recentFeed = ReadAllText(@"Files/Indexers/" + rssXmlFile);
Mocker.GetMock<IHttpClient>()
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.GET)))
.Setup(o => o.Execute(It.IsAny<HttpRequest>()))
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), recentFeed));
Subject.TestPublic().Should().BeEmpty();
}
[TestCase("https://www.ezrss.it/1", "Eztv_InvalidSize.xml")]
[TestCase("https://www.ezrss.it/2", "Eztv_InvalidTitles.xml")]
[TestCase("https://www.ezrss.it/3", "Eztv_InvalidDownloadUrl.xml")]
[TestCase("https://immortalseed.me/rss.php?secret_key=12345678910&feedtype=download&timezone=-12&showrows=50&categories=8", "ImmortalSeed_InvalidSize.xml")]
[TestCase("https://immortalseed.me/rss.php?secret_key=12345678910&feedtype=download&timezone=-12&showrows=50&categories=9", "ImmortalSeed_InvalidTitles.xml")]
[TestCase("https://immortalseed.me/rss.php?secret_key=12345678910&feedtype=download&timezone=-12&showrows=50&categories=10", "ImmortalSeed_InvalidDownloadUrl.xml")]
public void should_reject_recent_feed(string baseUrl, string rssXmlFile)
{
Subject.Definition.Settings = new TorrentRssIndexerSettings { BaseUrl = baseUrl };
var recentFeed = ReadAllText(@"Files/RSS/" + rssXmlFile);
Mocker.GetMock<IHttpClient>()
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.GET)))
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), recentFeed));
Subject.TestPublic().Should().HaveCount(1);
ExceptionVerification.IgnoreWarns();
}
[Test]
public void should_parse_recent_feed_from_ImmortalSeed()
{
Subject.Definition.Settings = new TorrentRssIndexerSettings { BaseUrl = "https://immortalseed.me/rss.php?secret_key=12345678910&feedtype=download&timezone=-12&showrows=50&categories=8" };
var recentFeed = ReadAllText(@"Files/RSS/ImmortalSeed.xml");
GivenRecentFeedResponse("TorrentRss/ImmortalSeed.xml");
_logger.Debug("Feed: [{0}]", recentFeed);
Mocker.GetMock<IHttpClient>()
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.GET)))
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), recentFeed));
_logger.Trace("Test");
var releases = Subject.FetchRecent();
releases.Should().HaveCount(50);
@@ -96,7 +62,7 @@ namespace NzbDrone.Core.Test.IndexerTests.TorrentRssIndexerTests
torrentInfo.InfoUrl.Should().BeNullOrEmpty();
torrentInfo.CommentUrl.Should().BeNullOrEmpty();
torrentInfo.Indexer.Should().Be(Subject.Definition.Name);
torrentInfo.PublishDate.Should().Be(DateTime.Parse("2015-02-06 12:32:26"));
torrentInfo.PublishDate.Should().Be(DateTime.Parse("2015-02-06 13:32:26"));
torrentInfo.Size.Should().Be(984078090);
torrentInfo.InfoHash.Should().BeNullOrEmpty();
torrentInfo.MagnetUrl.Should().BeNullOrEmpty();
@@ -107,13 +73,7 @@ namespace NzbDrone.Core.Test.IndexerTests.TorrentRssIndexerTests
[Test]
public void should_parse_recent_feed_from_Eztv()
{
Subject.Definition.Settings = new TorrentRssIndexerSettings { BaseUrl = "https://www.ezrss.it/" };
var recentFeed = ReadAllText(@"Files/RSS/Eztv.xml");
Mocker.GetMock<IHttpClient>()
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.GET)))
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), recentFeed));
GivenRecentFeedResponse("Eztv/Eztv.xml");
var releases = Subject.FetchRecent();
@@ -135,5 +95,33 @@ namespace NzbDrone.Core.Test.IndexerTests.TorrentRssIndexerTests
torrentInfo.Peers.Should().NotHaveValue();
torrentInfo.Seeders.Should().NotHaveValue();
}
[Test]
public void should_parse_recent_feed_from_ShowRSS_info()
{
Subject.Definition.Settings.As<TorrentRssIndexerSettings>().AllowZeroSize = true;
GivenRecentFeedResponse("TorrentRss/ShowRSS.info.xml");
var releases = Subject.FetchRecent();
releases.Should().HaveCount(5);
releases.First().Should().BeOfType<TorrentInfo>();
var torrentInfo = releases.First() as TorrentInfo;
torrentInfo.Title.Should().Be("The Voice 8x25");
torrentInfo.DownloadProtocol.Should().Be(DownloadProtocol.Torrent);
torrentInfo.DownloadUrl.Should().Be("magnet:?xt=urn:btih:96CD620BEDA3EFD7C4D7746EF94549D03A2EB13B&dn=The+Voice+S08E25+WEBRip+x264+WNN&tr=udp://tracker.coppersurfer.tk:6969/announce&tr=udp://tracker.leechers-paradise.org:6969&tr=udp://open.demonii.com:1337");
torrentInfo.InfoUrl.Should().BeNullOrEmpty();
torrentInfo.CommentUrl.Should().BeNullOrEmpty();
torrentInfo.Indexer.Should().Be(Subject.Definition.Name);
torrentInfo.PublishDate.Should().Be(DateTime.Parse("2015/05/15 08:30:01"));
torrentInfo.Size.Should().Be(0);
torrentInfo.InfoHash.Should().Be("96CD620BEDA3EFD7C4D7746EF94549D03A2EB13B");
torrentInfo.MagnetUrl.Should().Be("magnet:?xt=urn:btih:96CD620BEDA3EFD7C4D7746EF94549D03A2EB13B&dn=The+Voice+S08E25+WEBRip+x264+WNN&tr=udp://tracker.coppersurfer.tk:6969/announce&tr=udp://tracker.leechers-paradise.org:6969&tr=udp://open.demonii.com:1337");
torrentInfo.Peers.Should().NotHaveValue();
torrentInfo.Seeders.Should().NotHaveValue();
}
}
}
@@ -0,0 +1,168 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Moq;
using NUnit.Framework;
using NzbDrone.Common.Cache;
using NzbDrone.Core.Indexers.TorrentRss;
using NzbDrone.Core.Test.Framework;
using FluentAssertions;
using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.Indexers;
namespace NzbDrone.Core.Test.IndexerTests.TorrentRssIndexerTests
{
[TestFixture]
public class TorrentRssParserFactoryFixture : CoreTest<TorrentRssParserFactory>
{
private TorrentRssIndexerSettings _indexerSettings1;
private TorrentRssIndexerSettings _indexerSettings2;
private TorrentRssIndexerSettings _indexerSettings3;
[SetUp]
public void SetUp()
{
Mocker.SetConstant<ICacheManager>(Mocker.Resolve<CacheManager>());
_indexerSettings1 = new TorrentRssIndexerSettings
{
BaseUrl = "http://my.indexer.com/"
};
_indexerSettings2 = new TorrentRssIndexerSettings
{
BaseUrl = "http://my.other.indexer.com/"
};
_indexerSettings3 = new TorrentRssIndexerSettings
{
BaseUrl = "http://my.indexer.com/",
AllowZeroSize = true
};
}
private void GivenSuccessful(TorrentRssIndexerParserSettings parserSettings = null)
{
if (parserSettings == null)
{
parserSettings = new TorrentRssIndexerParserSettings
{
UseEnclosureLength = true,
ParseSizeInDescription = false
};
}
Mocker.GetMock<ITorrentRssSettingsDetector>()
.Setup(v => v.Detect(It.IsAny<TorrentRssIndexerSettings>()))
.Returns(parserSettings);
}
private void GivenFailed()
{
Mocker.GetMock<ITorrentRssSettingsDetector>()
.Setup(v => v.Detect(It.IsAny<TorrentRssIndexerSettings>()))
.Returns((TorrentRssIndexerParserSettings)null);
}
private void VerifyDetectionCount(int count)
{
Mocker.GetMock<ITorrentRssSettingsDetector>()
.Verify(v => v.Detect(It.IsAny<TorrentRssIndexerSettings>()), Times.Exactly(count));
}
[Test]
public void should_return_ezrssparser()
{
GivenSuccessful(new TorrentRssIndexerParserSettings
{
UseEZTVFormat = true
});
var parser = Subject.GetParser(_indexerSettings1);
parser.Should().BeOfType<EzrssTorrentRssParser>();
}
[Test]
public void should_return_generic_torrentrssparser()
{
GivenSuccessful(new TorrentRssIndexerParserSettings
{
ParseSeedersInDescription = true,
ParseSizeInDescription = true,
SizeElementName = "Hello"
});
var parser = Subject.GetParser(_indexerSettings1);
parser.Should().BeOfType<TorrentRssParser>();
var rssParser = parser as TorrentRssParser;
rssParser.ParseSeedersInDescription.Should().BeTrue();
rssParser.ParseSizeInDescription.Should().BeTrue();
rssParser.SizeElementName.Should().Be("Hello");
}
[Test]
public void should_throw_on_failure()
{
GivenFailed();
Assert.Throws<UnsupportedFeedException>(() => Subject.GetParser(_indexerSettings1));
}
[Test]
public void should_cache_settings_for_same_baseurl()
{
GivenSuccessful();
var detection1 = Subject.GetParser(_indexerSettings1);
var detection2 = Subject.GetParser(_indexerSettings1);
detection1.ShouldBeEquivalentTo(detection2);
VerifyDetectionCount(1);
}
[Test]
public void should_not_cache_failure()
{
GivenFailed();
Assert.Throws<UnsupportedFeedException>(() => Subject.GetParser(_indexerSettings1));
GivenSuccessful();
Subject.GetParser(_indexerSettings1);
VerifyDetectionCount(2);
}
[Test]
public void should_not_cache_settings_for_different_baseurl()
{
GivenSuccessful();
var detection1 = Subject.GetParser(_indexerSettings1);
var detection2 = Subject.GetParser(_indexerSettings2);
VerifyDetectionCount(2);
}
[Test]
public void should_not_cache_settings_for_different_settings()
{
GivenSuccessful();
var detection1 = Subject.GetParser(_indexerSettings1);
var detection2 = Subject.GetParser(_indexerSettings3);
VerifyDetectionCount(2);
}
}
}
@@ -0,0 +1,207 @@
using System;
using System.Collections.Generic;
using System.Linq;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Common.Http;
using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.Indexers.TorrentRss;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.IndexerTests.TorrentRssIndexerTests
{
[TestFixture]
public class TorrentRssSettingsDetectorFixture : CoreTest<TorrentRssSettingsDetector>
{
private const string _indexerUrl = "http://my.indexer.tv/recent";
private TorrentRssIndexerSettings _indexerSettings;
[SetUp]
public void SetUp()
{
_indexerSettings = new TorrentRssIndexerSettings { BaseUrl = _indexerUrl };
}
private void GivenRecentFeedResponse(string rssXmlFile)
{
var recentFeed = ReadAllText(@"Files/Indexers/" + rssXmlFile);
Mocker.GetMock<IHttpClient>()
.Setup(o => o.Execute(It.IsAny<HttpRequest>()))
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), recentFeed));
}
[Test]
public void should_detect_rss_settings_for_eztv()
{
GivenRecentFeedResponse("Eztv/Eztv.xml");
var settings = Subject.Detect(_indexerSettings);
settings.ShouldBeEquivalentTo(new TorrentRssIndexerParserSettings
{
UseEZTVFormat = true,
UseEnclosureLength = false,
ParseSizeInDescription = false,
ParseSeedersInDescription = false,
SizeElementName = null
});
}
[Test]
public void should_detect_rss_settings_for_speed_cd()
{
GivenRecentFeedResponse("TorrentRss/speed.cd.xml");
var settings = Subject.Detect(_indexerSettings);
settings.ShouldBeEquivalentTo(new TorrentRssIndexerParserSettings
{
UseEZTVFormat = false,
UseEnclosureLength = false,
ParseSizeInDescription = true,
ParseSeedersInDescription = false,
SizeElementName = null
});
}
[Test]
public void should_detect_rss_settings_for_ImmortalSeed()
{
GivenRecentFeedResponse("TorrentRss/ImmortalSeed.xml");
var settings = Subject.Detect(_indexerSettings);
settings.ShouldBeEquivalentTo(new TorrentRssIndexerParserSettings
{
UseEZTVFormat = false,
UseEnclosureLength = false,
ParseSizeInDescription = true,
ParseSeedersInDescription = true,
SizeElementName = null
});
}
[Test]
public void should_detect_rss_settings_for_ShowRSS_info()
{
_indexerSettings.AllowZeroSize = true;
GivenRecentFeedResponse("TorrentRss/ShowRSS.info.xml");
var settings = Subject.Detect(_indexerSettings);
settings.ShouldBeEquivalentTo(new TorrentRssIndexerParserSettings
{
UseEZTVFormat = false,
UseEnclosureLength = false,
ParseSizeInDescription = false,
ParseSeedersInDescription = false,
SizeElementName = null
});
}
[Test]
public void should_detect_rss_settings_for_TransmitTheNet()
{
GivenRecentFeedResponse("TorrentRss/TransmitTheNet.xml");
var settings = Subject.Detect(_indexerSettings);
settings.ShouldBeEquivalentTo(new TorrentRssIndexerParserSettings
{
UseEZTVFormat = false,
UseEnclosureLength = false,
ParseSizeInDescription = true,
ParseSeedersInDescription = false,
SizeElementName = null
});
}
[Test]
[Ignore("Cannot reliably reject unparseable titles")]
public void should_reject_rss_settings_for_AwesomeHD()
{
_indexerSettings.AllowZeroSize = true;
GivenRecentFeedResponse("TorrentRss/AwesomeHD.xml");
var settings = Subject.Detect(_indexerSettings);
settings.Should().BeNull();
}
[TestCase("BitMeTv/BitMeTv.xml")]
[TestCase("Fanzub/fanzub.xml")]
[TestCase("KickassTorrents/KickassTorrents.xml")]
[TestCase("IPTorrents/IPTorrents.xml")]
[TestCase("Newznab/newznab_nzb_su.xml")]
[TestCase("Nyaa/Nyaa.xml")]
[TestCase("Omgwtfnzbs/Omgwtfnzbs.xml")]
[TestCase("Torznab/torznab_hdaccess_net.xml")]
[TestCase("Torznab/torznab_tpb.xml")]
public void should_detect_recent_feed(string rssXmlFile)
{
GivenRecentFeedResponse(rssXmlFile);
var settings = Subject.Detect(_indexerSettings);
settings.Should().NotBeNull();
}
[TestCase("TorrentRss/invalid/Eztv_InvalidDownloadUrl.xml")]
[TestCase("TorrentRss/invalid/ImmortalSeed_InvalidDownloadUrl.xml")]
public void should_reject_recent_feed_with_invalid_downloadurl(string rssXmlFile)
{
GivenRecentFeedResponse(rssXmlFile);
var ex = Assert.Throws<UnsupportedFeedException>(() => Subject.Detect(_indexerSettings));
ex.Message.Should().Contain("download url");
}
[TestCase("TorrentRss/invalid/TorrentDay_NoPubDate.xml")]
public void should_reject_recent_feed_without_pubDate(string rssXmlFile)
{
GivenRecentFeedResponse(rssXmlFile);
var ex = Assert.Throws<UnsupportedFeedException>(() => Subject.Detect(_indexerSettings));
ex.Message.Should().Contain("Empty feed");
ExceptionVerification.ExpectedErrors(1);
}
[TestCase("Torrentleech/Torrentleech.xml")]
[TestCase("Wombles/wombles.xml")]
[TestCase("TorrentRss/invalid/Eztv_InvalidSize.xml")]
[TestCase("TorrentRss/invalid/ImmortalSeed_InvalidSize.xml")]
public void should_detect_feed_without_size(string rssXmlFile)
{
_indexerSettings.AllowZeroSize = true;
GivenRecentFeedResponse(rssXmlFile);
var settings = Subject.Detect(_indexerSettings);
settings.Should().NotBeNull();
settings.UseEnclosureLength.Should().BeFalse();
settings.ParseSizeInDescription.Should().BeFalse();
settings.SizeElementName.Should().BeNull();
}
[TestCase("TorrentRss/invalid/Eztv_InvalidSize.xml")]
[TestCase("TorrentRss/invalid/ImmortalSeed_InvalidSize.xml")]
public void should_reject_feed_without_size(string rssXmlFile)
{
GivenRecentFeedResponse(rssXmlFile);
var ex = Assert.Throws<UnsupportedFeedException>(() => Subject.Detect(_indexerSettings));
ex.Message.Should().Contain("content size");
}
}
}