HttpClient

This commit is contained in:
Keivan Beigi 2014-09-11 16:49:41 -07:00
parent 3a287bf7e7
commit 2c1d3339d0
55 changed files with 995 additions and 582 deletions

View File

@ -9,13 +9,10 @@ namespace NzbDrone.Api.Update
public class UpdateModule : NzbDroneRestModule<UpdateResource> public class UpdateModule : NzbDroneRestModule<UpdateResource>
{ {
private readonly IRecentUpdateProvider _recentUpdateProvider; private readonly IRecentUpdateProvider _recentUpdateProvider;
private readonly IInstallUpdates _installUpdateService;
public UpdateModule(IRecentUpdateProvider recentUpdateProvider, public UpdateModule(IRecentUpdateProvider recentUpdateProvider)
IInstallUpdates installUpdateService)
{ {
_recentUpdateProvider = recentUpdateProvider; _recentUpdateProvider = recentUpdateProvider;
_installUpdateService = installUpdateService;
GetResourceAll = GetRecentUpdates; GetResourceAll = GetRecentUpdates;
} }

View File

@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using System.Net;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Common.Http;
using NzbDrone.Test.Common;
using NzbDrone.Test.Common.Categories;
namespace NzbDrone.Common.Test.Http
{
[TestFixture]
[IntegrationTest]
public class RestClientFixture : TestBase<HttpClient>
{
[Test]
public void should_execute_simple_get()
{
var request = new HttpRequest("http://eu.httpbin.org/get");
var response = Subject.Execute(request);
response.Content.Should().NotBeNullOrWhiteSpace();
}
[Test]
public void should_execute_typed_get()
{
var request = new HttpRequest("http://eu.httpbin.org/get");
var response = Subject.Get<HttpBinResource>(request);
response.Resource.Url.Should().Be(request.Url.ToString());
}
[TestCase("gzip")]
public void should_execute_get_using_gzip(string compression)
{
var request = new HttpRequest("http://eu.httpbin.org/" + compression);
var response = Subject.Get<HttpBinResource>(request);
response.Resource.Headers["Accept-Encoding"].ToString().Should().Be(compression);
response.Headers.ContentLength.Should().BeLessOrEqualTo(response.Content.Length);
}
[TestCase(HttpStatusCode.Unauthorized)]
[TestCase(HttpStatusCode.Forbidden)]
[TestCase(HttpStatusCode.NotFound)]
[TestCase(HttpStatusCode.InternalServerError)]
[TestCase(HttpStatusCode.ServiceUnavailable)]
[TestCase(HttpStatusCode.BadGateway)]
public void should_throw_on_unsuccessful_status_codes(HttpStatusCode statusCode)
{
var request = new HttpRequest("http://eu.httpbin.org/status/" + (int)statusCode);
var exception = Assert.Throws<HttpException>(() => Subject.Get<HttpBinResource>(request));
exception.Response.StatusCode.Should().Be(statusCode);
}
[TestCase(HttpStatusCode.Moved)]
[TestCase(HttpStatusCode.MovedPermanently)]
public void should_not_follow_redirects_when_not_in_production(HttpStatusCode statusCode)
{
var request = new HttpRequest("http://eu.httpbin.org/status/" + (int)statusCode);
Assert.Throws<Exception>(() => Subject.Get<HttpBinResource>(request));
}
}
public class HttpBinResource
{
public Dictionary<string, object> Headers { get; set; }
public string Origin { get; set; }
public string Url { get; set; }
}
}

View File

@ -0,0 +1,22 @@
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Common.Http;
using NzbDrone.Test.Common;
namespace NzbDrone.Common.Test.Http
{
[TestFixture]
public class HttpRequestBuilderFixture : TestBase
{
[Test]
public void should_remove_duplicated_slashes()
{
var builder = new HttpRequestBuilder("http://domain/");
var request = builder.Build("/v1/");
request.Url.ToString().Should().Be("http://domain/v1/");
}
}
}

View File

@ -0,0 +1,29 @@
using System;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Common.Http;
namespace NzbDrone.Common.Test.Http
{
[TestFixture]
public class HttpRequestFixture
{
[TestCase("http://host/{seg}/some", "http://host/dir/some")]
[TestCase("http://host/some/{seg}", "http://host/some/dir")]
public void should_add_single_segment_url_segments(string url, string result)
{
var request = new HttpRequest(url);
request.AddSegment("seg", "dir");
request.Url.Should().Be(result);
}
[Test]
public void shouldnt_add_value_for_nonexisting_segment()
{
var request = new HttpRequest("http://host/{seg}/some");
Assert.Throws<InvalidOperationException>(() => request.AddSegment("seg2", "dir"));
}
}
}

View File

@ -73,6 +73,9 @@
<Compile Include="EnvironmentProviderTest.cs" /> <Compile Include="EnvironmentProviderTest.cs" />
<Compile Include="EnvironmentTests\EnvironmentProviderTest.cs" /> <Compile Include="EnvironmentTests\EnvironmentProviderTest.cs" />
<Compile Include="EnvironmentTests\StartupArgumentsFixture.cs" /> <Compile Include="EnvironmentTests\StartupArgumentsFixture.cs" />
<Compile Include="Http\HttpClientFixture.cs" />
<Compile Include="Http\HttpRequestBuilderFixture.cs" />
<Compile Include="Http\HttpRequestFixture.cs" />
<Compile Include="InstrumentationTests\CleanseLogMessageFixture.cs" /> <Compile Include="InstrumentationTests\CleanseLogMessageFixture.cs" />
<Compile Include="LevenshteinDistanceFixture.cs" /> <Compile Include="LevenshteinDistanceFixture.cs" />
<Compile Include="PathExtensionFixture.cs" /> <Compile Include="PathExtensionFixture.cs" />

View File

@ -26,13 +26,5 @@ namespace NzbDrone.Common.Test
Assert.Throws<ArgumentException>(() => Subject.DownloadString(url)); Assert.Throws<ArgumentException>(() => Subject.DownloadString(url));
ExceptionVerification.ExpectedWarns(1); ExceptionVerification.ExpectedWarns(1);
} }
[Test]
public void should_get_headers()
{
Subject.GetHeader("http://www.google.com").Should().NotBeEmpty();
}
} }
} }

View File

@ -0,0 +1,19 @@
using NzbDrone.Common.Http;
namespace NzbDrone.Common.Cloud
{
public interface IDroneServicesRequestBuilder
{
HttpRequest Build(string path);
}
public class DroneServicesHttpRequestBuilder : HttpRequestBuilder, IDroneServicesRequestBuilder
{
private const string ROOT_URL = "http://services.nzbdrone.com/v1/";
public DroneServicesHttpRequestBuilder()
: base(ROOT_URL)
{
}
}
}

View File

@ -0,0 +1,15 @@
using System;
using System.Net;
namespace NzbDrone.Common.Http
{
public class GZipWebClient : WebClient
{
protected override WebRequest GetWebRequest(Uri address)
{
var request = (HttpWebRequest)base.GetWebRequest(address);
request.AutomaticDecompression = DecompressionMethods.GZip;
return request;
}
}
}

View File

@ -0,0 +1,160 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using NLog;
using NzbDrone.Common.EnvironmentInfo;
namespace NzbDrone.Common.Http
{
public interface IHttpClient
{
HttpResponse Execute(HttpRequest request);
void DownloadFile(string url, string fileName);
HttpResponse Get(HttpRequest request);
HttpResponse<T> Get<T>(HttpRequest request) where T : new();
HttpResponse Head(HttpRequest request);
}
public class HttpClient : IHttpClient
{
private readonly Logger _logger;
private readonly string _userAgent;
public HttpClient(Logger logger)
{
_logger = logger;
_userAgent = String.Format("NzbDrone {0}", BuildInfo.Version);
ServicePointManager.DefaultConnectionLimit = 12;
}
public HttpResponse Execute(HttpRequest request)
{
_logger.Trace(request);
var webRequest = (HttpWebRequest)WebRequest.Create(request.Url);
// Deflate is not a standard and could break depending on implementation.
// we should just stick with the more compatible Gzip
//http://stackoverflow.com/questions/8490718/how-to-decompress-stream-deflated-with-java-util-zip-deflater-in-net
webRequest.AutomaticDecompression = DecompressionMethods.GZip;
webRequest.Credentials = request.NetworkCredential;
webRequest.Method = request.Method.ToString();
webRequest.KeepAlive = false;
if (!RuntimeInfoBase.IsProduction)
{
webRequest.AllowAutoRedirect = false;
}
var stopWatch = Stopwatch.StartNew();
if (!request.Body.IsNullOrWhiteSpace())
{
var bytes = new byte[request.Body.Length * sizeof(char)];
Buffer.BlockCopy(request.Body.ToCharArray(), 0, bytes, 0, bytes.Length);
webRequest.ContentLength = bytes.Length;
using (var writeStream = webRequest.GetRequestStream())
{
writeStream.Write(bytes, 0, bytes.Length);
}
}
HttpWebResponse httpWebResponse;
try
{
httpWebResponse = (HttpWebResponse)webRequest.GetResponse();
}
catch (WebException e)
{
httpWebResponse = (HttpWebResponse)e.Response;
}
string content = null;
using (var responseStream = httpWebResponse.GetResponseStream())
{
if (responseStream != null)
{
using (var reader = new StreamReader(responseStream))
{
content = reader.ReadToEnd();
}
}
}
stopWatch.Stop();
var response = new HttpResponse(request, new HttpHeader(httpWebResponse.Headers), content, httpWebResponse.StatusCode);
_logger.Trace("{0} ({1:n0} ms)", response, stopWatch.ElapsedMilliseconds);
if (!RuntimeInfoBase.IsProduction &&
(response.StatusCode == HttpStatusCode.Moved ||
response.StatusCode == HttpStatusCode.MovedPermanently))
{
throw new Exception("Server requested a redirect to [" + response.Headers["Location"] + "]. Update the request URL to avoid this redirect.");
}
if (!request.SuppressHttpError && response.HasHttpError)
{
_logger.Warn("HTTP Error - {0}", response);
throw new HttpException(request, response);
}
return response;
}
public void DownloadFile(string url, string fileName)
{
try
{
var fileInfo = new FileInfo(fileName);
if (fileInfo.Directory != null && !fileInfo.Directory.Exists)
{
fileInfo.Directory.Create();
}
_logger.Debug("Downloading [{0}] to [{1}]", url, fileName);
var stopWatch = Stopwatch.StartNew();
var webClient = new GZipWebClient();
webClient.Headers.Add(HttpRequestHeader.UserAgent, _userAgent);
webClient.DownloadFile(url, fileName);
stopWatch.Stop();
_logger.Debug("Downloading Completed. took {0:0}s", stopWatch.Elapsed.Seconds);
}
catch (WebException e)
{
_logger.Warn("Failed to get response from: {0} {1}", url, e.Message);
throw;
}
catch (Exception e)
{
_logger.WarnException("Failed to get response from: " + url, e);
throw;
}
}
public HttpResponse Get(HttpRequest request)
{
request.Method = HttpMethod.GET;
return Execute(request);
}
public HttpResponse<T> Get<T>(HttpRequest request) where T : new()
{
var response = Get(request);
return new HttpResponse<T>(response);
}
public HttpResponse Head(HttpRequest request)
{
request.Method = HttpMethod.HEAD;
return Execute(request);
}
}
}

View File

@ -0,0 +1,27 @@
using System;
namespace NzbDrone.Common.Http
{
public class HttpException : Exception
{
public HttpRequest Request { get; private set; }
public HttpResponse Response { get; private set; }
public HttpException(HttpRequest request, HttpResponse response)
: base(string.Format("HTTP request failed: [{0}] [{1}] at [{2}]", (int)response.StatusCode, request.Method, request.Url.ToString()))
{
Request = request;
Response = response;
}
public override string ToString()
{
if (Response != null)
{
return base.ToString() + Environment.NewLine + Response.Content;
}
return base.ToString();
}
}
}

View File

@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
namespace NzbDrone.Common.Http
{
public class HttpHeader : Dictionary<string, object>
{
public HttpHeader(NameValueCollection headers)
{
foreach (var key in headers.AllKeys)
{
this[key] = headers[key];
}
}
public HttpHeader()
{
}
public long? ContentLength
{
get
{
if (!ContainsKey("Content-Length"))
{
return null;
}
return Convert.ToInt64(this["Content-Length"]);
}
set
{
this["Content-Length"] = value;
}
}
public string ContentType
{
get
{
if (!ContainsKey("Content-Type"))
{
return null;
}
return this["Content-Type"].ToString();
}
set
{
this["Content-Type"] = value;
}
}
public string Accept
{
get
{
if (!ContainsKey("Accept"))
{
return null;
}
return this["Accept"].ToString();
}
set
{
this["Accept"] = value;
}
}
}
}

View File

@ -0,0 +1,13 @@
namespace NzbDrone.Common.Http
{
public enum HttpMethod
{
GET,
PUT,
POST,
HEAD,
DELETE,
PATCH,
OPTIONS
}
}

View File

@ -1,40 +1,23 @@
using System; using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net; using System.Net;
using System.Text;
using NLog; using NLog;
using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.EnvironmentInfo;
namespace NzbDrone.Common.Http namespace NzbDrone.Common.Http
{ {
[Obsolete("Use IHttpClient")]
public interface IHttpProvider public interface IHttpProvider
{ {
string DownloadString(string url); string DownloadString(string url);
string DownloadString(string url, string username, string password); string DownloadString(string url, string username, string password);
string DownloadString(string url, ICredentials credentials);
Dictionary<string, string> GetHeader(string url);
Stream DownloadStream(string url, NetworkCredential credential = null);
void DownloadFile(string url, string fileName);
string PostCommand(string address, string username, string password, string command);
} }
[Obsolete("Use HttpProvider")]
public class HttpProvider : IHttpProvider public class HttpProvider : IHttpProvider
{ {
private class GZipWebClient : WebClient
{
protected override WebRequest GetWebRequest(Uri address)
{
HttpWebRequest request = (HttpWebRequest)base.GetWebRequest(address);
request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
return request;
}
}
private readonly Logger _logger; private readonly Logger _logger;
public const string CONTENT_LENGTH_HEADER = "Content-Length";
private readonly string _userAgent; private readonly string _userAgent;
@ -55,7 +38,7 @@ namespace NzbDrone.Common.Http
return DownloadString(url, new NetworkCredential(username, password)); return DownloadString(url, new NetworkCredential(username, password));
} }
public string DownloadString(string url, ICredentials identity) private string DownloadString(string url, ICredentials identity)
{ {
try try
{ {
@ -75,81 +58,6 @@ namespace NzbDrone.Common.Http
} }
} }
public Dictionary<string, string> GetHeader(string url)
{
var headers = new Dictionary<string, string>();
var request = WebRequest.Create(url);
request.Method = "HEAD";
var response = request.GetResponse();
foreach (var key in response.Headers.AllKeys)
{
headers.Add(key, response.Headers[key]);
}
return headers;
}
public Stream DownloadStream(string url, NetworkCredential credential = null)
{
var request = (HttpWebRequest)WebRequest.Create(url);
request.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
request.UserAgent = _userAgent;
request.Timeout = 20 * 1000;
request.Credentials = credential;
var response = request.GetResponse();
return response.GetResponseStream();
}
public void DownloadFile(string url, string fileName)
{
try
{
var fileInfo = new FileInfo(fileName);
if (fileInfo.Directory != null && !fileInfo.Directory.Exists)
{
fileInfo.Directory.Create();
}
_logger.Debug("Downloading [{0}] to [{1}]", url, fileName);
var stopWatch = Stopwatch.StartNew();
var webClient = new GZipWebClient();
webClient.Headers.Add(HttpRequestHeader.UserAgent, _userAgent);
webClient.DownloadFile(url, fileName);
stopWatch.Stop();
_logger.Debug("Downloading Completed. took {0:0}s", stopWatch.Elapsed.Seconds);
}
catch (WebException e)
{
_logger.Warn("Failed to get response from: {0} {1}", url, e.Message);
throw;
}
catch (Exception e)
{
_logger.WarnException("Failed to get response from: " + url, e);
throw;
}
}
public string PostCommand(string address, string username, string password, string command)
{
address = String.Format("http://{0}/jsonrpc", address);
_logger.Debug("Posting command: {0}, to {1}", command, address);
byte[] byteArray = Encoding.ASCII.GetBytes(command);
var wc = new NzbDroneWebClient();
wc.Credentials = new NetworkCredential(username, password);
var response = wc.UploadData(address, "POST", byteArray);
var text = Encoding.ASCII.GetString(response);
return text.Replace("&nbsp;", " ");
}
} }
} }

View File

@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.Net;
namespace NzbDrone.Common.Http
{
public class HttpRequest
{
private readonly Dictionary<string, string> _segments;
public HttpRequest(string url)
{
UriBuilder = new UriBuilder(url);
Headers = new HttpHeader();
_segments = new Dictionary<string, string>();
Headers.Accept = "application/json";
}
public UriBuilder UriBuilder { get; private set; }
public Uri Url
{
get
{
var uri = UriBuilder.Uri.ToString();
foreach (var segment in _segments)
{
uri = uri.Replace(segment.Key, segment.Value);
}
return new Uri(uri);
}
}
public HttpMethod Method { get; set; }
public HttpHeader Headers { get; set; }
public string Body { get; set; }
public NetworkCredential NetworkCredential { get; set; }
public bool SuppressHttpError { get; set; }
public override string ToString()
{
if (Body == null)
{
return string.Format("Req: [{0}] {1}", Method, Url);
}
return string.Format("Req: [{0}] {1} {2} {3}", Method, Url, Environment.NewLine, Body);
}
public void AddSegment(string segment, string value)
{
var key = "{" + segment + "}";
if (!UriBuilder.Uri.ToString().Contains(key))
{
throw new InvalidOperationException("Segment " + key +" is not defined in Uri");
}
_segments.Add(key, value);
}
}
}

View File

@ -0,0 +1,40 @@
using System;
using System.Net;
namespace NzbDrone.Common.Http
{
public class HttpRequestBuilder
{
public Uri BaseUri { get; private set; }
public bool SupressHttpError { get; set; }
public NetworkCredential NetworkCredential { get; set; }
public Action<HttpRequest> PostProcess { get; set; }
public HttpRequestBuilder(string baseUri)
{
BaseUri = new Uri(baseUri);
}
public virtual HttpRequest Build(string path)
{
if (BaseUri.ToString().EndsWith("/"))
{
path = path.TrimStart('/');
}
var request = new HttpRequest(BaseUri + path)
{
SuppressHttpError = SupressHttpError,
NetworkCredential = NetworkCredential
};
if (PostProcess != null)
{
PostProcess(request);
}
return request;
}
}
}

View File

@ -0,0 +1,65 @@
using System;
using System.IO;
using System.Net;
using NzbDrone.Common.Serializer;
namespace NzbDrone.Common.Http
{
public class HttpResponse
{
public HttpResponse(HttpRequest request, HttpHeader headers, string content, HttpStatusCode statusCode)
{
Request = request;
Headers = headers;
Content = content;
StatusCode = statusCode;
}
public HttpRequest Request { get; private set; }
public HttpHeader Headers { get; private set; }
public HttpStatusCode StatusCode { get; private set; }
public string Content { get; private set; }
public bool HasHttpError
{
get
{
return (int)StatusCode >= 400;
}
}
public override string ToString()
{
var result = string.Format("Res: [{0}] {1} : {2}.{3}", Request.Method, Request.Url, (int)StatusCode, StatusCode);
if (HasHttpError)
{
result += Environment.NewLine + Content;
}
return result;
}
public Stream GetStream()
{
var stream = new MemoryStream();
var writer = new StreamWriter(stream);
writer.Write(Content);
writer.Flush();
stream.Position = 0;
return stream;
}
}
public class HttpResponse<T> : HttpResponse where T : new()
{
public HttpResponse(HttpResponse response)
: base(response.Request, response.Headers, response.Content, response.StatusCode)
{
Resource = Json.Deserialize<T>(response.Content);
}
public T Resource { get; private set; }
}
}

View File

@ -0,0 +1,21 @@
using System;
namespace NzbDrone.Common.Http
{
public static class UriExtensions
{
public static void SetQueryParam(this UriBuilder uriBuilder, string key, object value)
{
var query = uriBuilder.Query;
if (query.IsNotNullOrWhiteSpace())
{
query += "&";
}
uriBuilder.Query = query.Trim('?') + (key + "=" + value);
}
}
}

View File

@ -58,16 +58,13 @@
<Reference Include="NLog"> <Reference Include="NLog">
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath> <HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
</Reference> </Reference>
<Reference Include="RestSharp, Version=104.4.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\RestSharp.104.4.0\lib\net4\RestSharp.dll</HintPath>
</Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="ArchiveService.cs" /> <Compile Include="ArchiveService.cs" />
<Compile Include="Cache\Cached.cs" /> <Compile Include="Cache\Cached.cs" />
<Compile Include="Cache\CacheManager.cs" /> <Compile Include="Cache\CacheManager.cs" />
<Compile Include="Cache\ICached.cs" /> <Compile Include="Cache\ICached.cs" />
<Compile Include="Cloud\CloudClient.cs" />
<Compile Include="Composition\Container.cs" /> <Compile Include="Composition\Container.cs" />
<Compile Include="Composition\ContainerBuilderBase.cs" /> <Compile Include="Composition\ContainerBuilderBase.cs" />
<Compile Include="Composition\IContainer.cs" /> <Compile Include="Composition\IContainer.cs" />
@ -114,10 +111,21 @@
<Compile Include="Extensions\Base64Extentions.cs" /> <Compile Include="Extensions\Base64Extentions.cs" />
<Compile Include="Extensions\StreamExtensions.cs" /> <Compile Include="Extensions\StreamExtensions.cs" />
<Compile Include="HashUtil.cs" /> <Compile Include="HashUtil.cs" />
<Compile Include="Http\GZipWebClient.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="Http\HttpClient.cs" />
<Compile Include="Http\HttpException.cs" />
<Compile Include="Http\HttpHeader.cs" />
<Compile Include="Http\HttpMethod.cs" />
<Compile Include="Http\HttpProvider.cs" /> <Compile Include="Http\HttpProvider.cs" />
<Compile Include="Http\HttpRequest.cs" />
<Compile Include="Http\HttpResponse.cs" />
<Compile Include="Http\NzbDroneWebClient.cs"> <Compile Include="Http\NzbDroneWebClient.cs">
<SubType>Component</SubType> <SubType>Component</SubType>
</Compile> </Compile>
<Compile Include="Http\HttpRequestBuilder.cs" />
<Compile Include="Http\UriExtensions.cs" />
<Compile Include="IEnumerableExtensions.cs" /> <Compile Include="IEnumerableExtensions.cs" />
<Compile Include="Instrumentation\CleanseLogMessage.cs" /> <Compile Include="Instrumentation\CleanseLogMessage.cs" />
<Compile Include="Instrumentation\ExceptronTarget.cs" /> <Compile Include="Instrumentation\ExceptronTarget.cs" />

View File

@ -74,6 +74,11 @@ namespace NzbDrone.Common
return String.IsNullOrWhiteSpace(text); return String.IsNullOrWhiteSpace(text);
} }
public static bool IsNotNullOrWhiteSpace(this string text)
{
return !String.IsNullOrWhiteSpace(text);
}
public static bool ContainsIgnoreCase(this string text, string contains) public static bool ContainsIgnoreCase(this string text, string contains)
{ {
return text.IndexOf(contains, StringComparison.InvariantCultureIgnoreCase) > -1; return text.IndexOf(contains, StringComparison.InvariantCultureIgnoreCase) > -1;

View File

@ -3,6 +3,5 @@
<package id="loggly-csharp" version="2.3" targetFramework="net40" /> <package id="loggly-csharp" version="2.3" targetFramework="net40" />
<package id="Newtonsoft.Json" version="6.0.4" targetFramework="net40" /> <package id="Newtonsoft.Json" version="6.0.4" targetFramework="net40" />
<package id="NLog" version="2.1.0" targetFramework="net40" /> <package id="NLog" version="2.1.0" targetFramework="net40" />
<package id="RestSharp" version="104.4.0" targetFramework="net40" />
<package id="SharpZipLib" version="0.86.0" targetFramework="net40" /> <package id="SharpZipLib" version="0.86.0" targetFramework="net40" />
</packages> </packages>

View File

@ -0,0 +1,28 @@
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.DataAugmentation.DailySeries;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common;
using NzbDrone.Test.Common.Categories;
namespace NzbDrone.Core.Test.DataAugmentation.DailySeries
{
[TestFixture]
[IntegrationTest]
public class DailySeriesDataProxyFixture : CoreTest<DailySeriesDataProxy>
{
[SetUp]
public void Setup()
{
UseRealHttp();
}
[Test]
public void should_get_list_of_daily_series()
{
var list = Subject.GetDailySeriesIds();
list.Should().NotBeEmpty();
list.Should().OnlyHaveUniqueItems();
}
}
}

View File

@ -1,53 +1,33 @@
using System;
using System.Net;
using FluentAssertions; using FluentAssertions;
using Newtonsoft.Json;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Common; using NzbDrone.Common;
using NzbDrone.Common.Http;
using NzbDrone.Core.DataAugmentation.Scene; using NzbDrone.Core.DataAugmentation.Scene;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common.Categories;
namespace NzbDrone.Core.Test.DataAugmentationFixture.Scene namespace NzbDrone.Core.Test.DataAugmentationFixture.Scene
{ {
[TestFixture] [TestFixture]
[IntegrationTest]
public class SceneMappingProxyFixture : CoreTest<SceneMappingProxy> public class SceneMappingProxyFixture : CoreTest<SceneMappingProxy>
{ {
private const string SCENE_MAPPING_URL = "http://services.nzbdrone.com/v1/SceneMapping"; [SetUp]
public void Setup()
{
UseRealHttp();
}
[Test] [Test]
public void fetch_should_return_list_of_mappings() public void fetch_should_return_list_of_mappings()
{ {
Mocker.GetMock<IHttpProvider>()
.Setup(s => s.DownloadString(SCENE_MAPPING_URL))
.Returns(ReadAllText("Files", "SceneMappings.json"));
var mappings = Subject.Fetch(); var mappings = Subject.Fetch();
mappings.Should().NotBeEmpty(); mappings.Should().NotBeEmpty();
mappings.Should().NotContain(c => String.IsNullOrWhiteSpace(c.SearchTerm)); mappings.Should().NotContain(c => c.SearchTerm.IsNullOrWhiteSpace());
mappings.Should().NotContain(c => String.IsNullOrWhiteSpace(c.Title)); mappings.Should().NotContain(c => c.Title.IsNullOrWhiteSpace());
mappings.Should().NotContain(c => c.TvdbId == 0); mappings.Should().Contain(c => c.SeasonNumber > 0);
} }
[Test]
public void should_throw_on_server_error()
{
Mocker.GetMock<IHttpProvider>()
.Setup(s => s.DownloadString(SCENE_MAPPING_URL))
.Throws(new WebException());
Assert.Throws<WebException>(() => Subject.Fetch());
}
[Test]
public void should_throw_on_bad_json()
{
Mocker.GetMock<IHttpProvider>()
.Setup(s => s.DownloadString(SCENE_MAPPING_URL))
.Returns("bad json");
Assert.Throws<JsonReaderException>(() => Subject.Fetch());
}
} }
} }

View File

@ -5,13 +5,9 @@ using Moq;
using NUnit.Framework; using NUnit.Framework;
using FluentAssertions; using FluentAssertions;
using NzbDrone.Test.Common; using NzbDrone.Test.Common;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Common;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Download; using NzbDrone.Core.Download;
using NzbDrone.Core.Download.Clients;
using NzbDrone.Core.Download.Clients.UsenetBlackhole; using NzbDrone.Core.Download.Clients.UsenetBlackhole;
namespace NzbDrone.Core.Test.Download.DownloadClientTests.Blackhole namespace NzbDrone.Core.Test.Download.DownloadClientTests.Blackhole
@ -46,7 +42,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.Blackhole
protected void WithFailedDownload() protected void WithFailedDownload()
{ {
Mocker.GetMock<IHttpProvider>() Mocker.GetMock<IHttpClient>()
.Setup(c => c.DownloadFile(It.IsAny<string>(), It.IsAny<string>())) .Setup(c => c.DownloadFile(It.IsAny<string>(), It.IsAny<string>()))
.Throws(new WebException()); .Throws(new WebException());
} }
@ -84,7 +80,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.Blackhole
Subject.Download(remoteEpisode); Subject.Download(remoteEpisode);
Mocker.GetMock<IHttpProvider>().Verify(c => c.DownloadFile(_downloadUrl, _filePath), Times.Once()); Mocker.GetMock<IHttpClient>().Verify(c => c.DownloadFile(_downloadUrl, _filePath), Times.Once());
} }
[Test] [Test]
@ -98,7 +94,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.Blackhole
Subject.Download(remoteEpisode); Subject.Download(remoteEpisode);
Mocker.GetMock<IHttpProvider>().Verify(c => c.DownloadFile(It.IsAny<string>(), expectedFilename), Times.Once()); Mocker.GetMock<IHttpClient>().Verify(c => c.DownloadFile(It.IsAny<string>(), expectedFilename), Times.Once());
} }
[Test] [Test]

View File

@ -1,10 +1,10 @@
using System; using System;
using System.Text; using System.Net;
using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using Moq; using Moq;
using NUnit.Framework; using NUnit.Framework;
using FluentAssertions; using FluentAssertions;
using NzbDrone.Common.Http;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
@ -30,6 +30,12 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests
Mocker.GetMock<IParsingService>() Mocker.GetMock<IParsingService>()
.Setup(s => s.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), null)) .Setup(s => s.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), null))
.Returns(CreateRemoteEpisode()); .Returns(CreateRemoteEpisode());
Mocker.GetMock<IHttpClient>()
.Setup(c => c.Get(It.IsAny<HttpRequest>()))
.Returns(new HttpResponse(null, null, "", HttpStatusCode.OK));
} }
protected virtual RemoteEpisode CreateRemoteEpisode() protected virtual RemoteEpisode CreateRemoteEpisode()

View File

@ -51,14 +51,9 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests
}; };
} }
private void WithExistingFile()
{
Mocker.GetMock<IDiskProvider>().Setup(c => c.FileExists(_nzbPath)).Returns(true);
}
private void WithFailedDownload() private void WithFailedDownload()
{ {
Mocker.GetMock<IHttpProvider>().Setup(c => c.DownloadFile(It.IsAny<string>(), It.IsAny<string>())).Throws(new WebException()); Mocker.GetMock<IHttpClient>().Setup(c => c.DownloadFile(It.IsAny<string>(), It.IsAny<string>())).Throws(new WebException());
} }
[Test] [Test]
@ -66,7 +61,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests
{ {
Subject.Download(_remoteEpisode); Subject.Download(_remoteEpisode);
Mocker.GetMock<IHttpProvider>().Verify(c => c.DownloadFile(_nzbUrl, _nzbPath), Times.Once()); Mocker.GetMock<IHttpClient>().Verify(c => c.DownloadFile(_nzbUrl, _nzbPath), Times.Once());
} }
@ -102,7 +97,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests
Subject.Download(_remoteEpisode); Subject.Download(_remoteEpisode);
Mocker.GetMock<IHttpProvider>().Verify(c => c.DownloadFile(It.IsAny<string>(), expectedFilename), Times.Once()); Mocker.GetMock<IHttpClient>().Verify(c => c.DownloadFile(It.IsAny<string>(), expectedFilename), Times.Once());
} }
} }
} }

View File

@ -1,32 +0,0 @@
[
{
"title": "Adventure Time",
"searchTitle": "Adventure Time",
"season": -1,
"tvdbId": 152831
},
{
"title": "Americas Funniest Home Videos",
"searchTitle": "Americas Funniest Home Videos",
"season": -1,
"tvdbId": 76235
},
{
"title": "Antiques Roadshow UK",
"searchTitle": "Antiques Roadshow UK",
"season": -1,
"tvdbId": 83774
},
{
"title": "Aqua Something You Know Whatever",
"searchTitle": "Aqua Something You Know Whatever",
"season": 9,
"tvdbId": 77120
},
{
"title": "Aqua Teen Hunger Force",
"searchTitle": "Aqua Teen Hunger Force",
"season": -1,
"tvdbId": 77120
}
]

View File

@ -1,5 +1,6 @@
using System.IO; using System.IO;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Common.Cloud;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Test.Common; using NzbDrone.Test.Common;
@ -15,6 +16,8 @@ namespace NzbDrone.Core.Test.Framework
protected void UseRealHttp() protected void UseRealHttp()
{ {
Mocker.SetConstant<IHttpProvider>(new HttpProvider(TestLogger)); Mocker.SetConstant<IHttpProvider>(new HttpProvider(TestLogger));
Mocker.SetConstant<IHttpClient>(new HttpClient(TestLogger));
Mocker.SetConstant<IDroneServicesRequestBuilder>(new DroneServicesHttpRequestBuilder());
} }
} }

View File

@ -1,4 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Net;
using FluentAssertions; using FluentAssertions;
using Moq; using Moq;
using NUnit.Framework; using NUnit.Framework;
@ -14,14 +15,14 @@ namespace NzbDrone.Core.Test.MediaCoverTests
[TestFixture] [TestFixture]
public class CoverAlreadyExistsSpecificationFixture : CoreTest<CoverAlreadyExistsSpecification> public class CoverAlreadyExistsSpecificationFixture : CoreTest<CoverAlreadyExistsSpecification>
{ {
private Dictionary<string, string> _headers; private HttpResponse _httpResponse;
[SetUp] [SetUp]
public void Setup() public void Setup()
{ {
_headers = new Dictionary<string, string>(); _httpResponse = new HttpResponse(null, new HttpHeader(), null, HttpStatusCode.OK);
Mocker.GetMock<IDiskProvider>().Setup(c => c.GetFileSize(It.IsAny<string>())).Returns(100); Mocker.GetMock<IDiskProvider>().Setup(c => c.GetFileSize(It.IsAny<string>())).Returns(100);
Mocker.GetMock<IHttpProvider>().Setup(c => c.GetHeader(It.IsAny<string>())).Returns(_headers); Mocker.GetMock<IHttpClient>().Setup(c => c.Head(It.IsAny<HttpRequest>())).Returns(_httpResponse);
} }
@ -50,7 +51,7 @@ namespace NzbDrone.Core.Test.MediaCoverTests
public void should_return_false_if_file_exists_but_diffrent_size() public void should_return_false_if_file_exists_but_diffrent_size()
{ {
GivenExistingFileSize(100); GivenExistingFileSize(100);
_headers.Add(HttpProvider.CONTENT_LENGTH_HEADER, "200"); _httpResponse.Headers.ContentLength = 200;
Subject.AlreadyExists("http://url", "c:\\file.exe").Should().BeFalse(); Subject.AlreadyExists("http://url", "c:\\file.exe").Should().BeFalse();
} }
@ -60,8 +61,7 @@ namespace NzbDrone.Core.Test.MediaCoverTests
public void should_return_ture_if_file_exists_and_same_size() public void should_return_ture_if_file_exists_and_same_size()
{ {
GivenExistingFileSize(100); GivenExistingFileSize(100);
_headers.Add(HttpProvider.CONTENT_LENGTH_HEADER, "100"); _httpResponse.Headers.ContentLength = 100;
Subject.AlreadyExists("http://url", "c:\\file.exe").Should().BeTrue(); Subject.AlreadyExists("http://url", "c:\\file.exe").Should().BeTrue();
} }
@ -70,8 +70,6 @@ namespace NzbDrone.Core.Test.MediaCoverTests
{ {
GivenExistingFileSize(100); GivenExistingFileSize(100);
Subject.AlreadyExists("http://url", "c:\\file.exe").Should().BeFalse(); Subject.AlreadyExists("http://url", "c:\\file.exe").Should().BeFalse();
ExceptionVerification.ExpectedWarns(1);
} }
} }
} }

View File

@ -3,8 +3,8 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using FluentAssertions; using FluentAssertions;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Common.Http;
using NzbDrone.Core.MetadataSource; using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.Rest;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv; using NzbDrone.Core.Tv;
using NzbDrone.Test.Common; using NzbDrone.Test.Common;
@ -16,12 +16,27 @@ namespace NzbDrone.Core.Test.MetadataSourceTests
[IntegrationTest] [IntegrationTest]
public class TraktProxyFixture : CoreTest<TraktProxy> public class TraktProxyFixture : CoreTest<TraktProxy>
{ {
[SetUp]
public void Setup()
{
UseRealHttp();
}
[TestCase("The Simpsons", "The Simpsons")] [TestCase("The Simpsons", "The Simpsons")]
[TestCase("South Park", "South Park")] [TestCase("South Park", "South Park")]
[TestCase("Franklin & Bash", "Franklin & Bash")] [TestCase("Franklin & Bash", "Franklin & Bash")]
[TestCase("Mr. D", "Mr. D")] [TestCase("Mr. D", "Mr. D")]
[TestCase("Rob & Big", "Rob and Big")] [TestCase("Rob & Big", "Rob and Big")]
[TestCase("M*A*S*H", "M*A*S*H")] [TestCase("M*A*S*H", "M*A*S*H")]
[TestCase("imdb:tt0436992", "Doctor Who (2005)")]
[TestCase("imdb:0436992", "Doctor Who (2005)")]
[TestCase("IMDB:0436992", "Doctor Who (2005)")]
[TestCase("IMDB: 0436992 ", "Doctor Who (2005)")]
[TestCase("tvdb:78804", "Doctor Who (2005)")]
[TestCase("TVDB:78804", "Doctor Who (2005)")]
[TestCase("TVDB: 78804 ", "Doctor Who (2005)")]
public void successful_search(string title, string expected) public void successful_search(string title, string expected)
{ {
var result = Subject.SearchForNewSeries(title); var result = Subject.SearchForNewSeries(title);
@ -52,7 +67,7 @@ namespace NzbDrone.Core.Test.MetadataSourceTests
[Test] [Test]
public void getting_details_of_invalid_series() public void getting_details_of_invalid_series()
{ {
Assert.Throws<RestException>(() => Subject.GetSeriesInfo(Int32.MaxValue)); Assert.Throws<HttpException>(() => Subject.GetSeriesInfo(Int32.MaxValue));
ExceptionVerification.ExpectedWarns(1); ExceptionVerification.ExpectedWarns(1);
} }

View File

@ -1,14 +1,10 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using FluentAssertions; using FluentAssertions;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.MetadataSource.Tvdb; using NzbDrone.Core.MetadataSource.Tvdb;
using NzbDrone.Core.Rest;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv; using NzbDrone.Core.Tv;
using NzbDrone.Test.Common;
using NzbDrone.Test.Common.Categories; using NzbDrone.Test.Common.Categories;
namespace NzbDrone.Core.Test.MetadataSourceTests namespace NzbDrone.Core.Test.MetadataSourceTests
@ -17,70 +13,15 @@ namespace NzbDrone.Core.Test.MetadataSourceTests
[IntegrationTest] [IntegrationTest]
public class TvdbProxyFixture : CoreTest<TvdbProxy> public class TvdbProxyFixture : CoreTest<TvdbProxy>
{ {
// [TestCase("The Simpsons", "The Simpsons")]
// [TestCase("South Park", "South Park")]
// [TestCase("Franklin & Bash", "Franklin & Bash")]
// [TestCase("Mr. D", "Mr. D")]
// [TestCase("Rob & Big", "Rob and Big")]
// [TestCase("M*A*S*H", "M*A*S*H")]
// public void successful_search(string title, string expected)
// {
// var result = Subject.SearchForNewSeries(title);
//
// result.Should().NotBeEmpty();
//
// result[0].Title.Should().Be(expected);
// }
//
// [Test]
// public void no_search_result()
// {
// var result = Subject.SearchForNewSeries(Guid.NewGuid().ToString());
// result.Should().BeEmpty();
// }
[TestCase(88031)] [TestCase(88031)]
[TestCase(179321)] [TestCase(179321)]
public void should_be_able_to_get_series_detail(int tvdbId) public void should_be_able_to_get_series_detail(int tvdbId)
{ {
var details = Subject.GetSeriesInfo(tvdbId); UseRealHttp();
//ValidateSeries(details.Item1); var episodes = Subject.GetEpisodeInfo(tvdbId);
ValidateEpisodes(details.Item2);
}
// [Test] ValidateEpisodes(episodes);
// public void getting_details_of_invalid_series()
// {
// Assert.Throws<RestException>(() => Subject.GetSeriesInfo(Int32.MaxValue));
//
// ExceptionVerification.ExpectedWarns(1);
// }
//
// [Test]
// public void should_not_have_period_at_start_of_title_slug()
// {
// var details = Subject.GetSeriesInfo(79099);
//
// details.Item1.TitleSlug.Should().Be("dothack");
// }
private void ValidateSeries(Series series)
{
series.Should().NotBeNull();
series.Title.Should().NotBeNullOrWhiteSpace();
series.CleanTitle.Should().Be(Parser.Parser.CleanSeriesTitle(series.Title));
series.Overview.Should().NotBeNullOrWhiteSpace();
series.AirTime.Should().NotBeNullOrWhiteSpace();
series.FirstAired.Should().HaveValue();
series.FirstAired.Value.Kind.Should().Be(DateTimeKind.Utc);
series.Images.Should().NotBeEmpty();
series.ImdbId.Should().NotBeNullOrWhiteSpace();
series.Network.Should().NotBeNullOrWhiteSpace();
series.Runtime.Should().BeGreaterThan(0);
series.TitleSlug.Should().NotBeNullOrWhiteSpace();
series.TvRageId.Should().BeGreaterThan(0);
series.TvdbId.Should().BeGreaterThan(0);
} }
private void ValidateEpisodes(List<Episode> episodes) private void ValidateEpisodes(List<Episode> episodes)
@ -91,30 +32,10 @@ namespace NzbDrone.Core.Test.MetadataSourceTests
.Max(e => e.Count()).Should().Be(1); .Max(e => e.Count()).Should().Be(1);
episodes.Should().Contain(c => c.SeasonNumber > 0); episodes.Should().Contain(c => c.SeasonNumber > 0);
// episodes.Should().Contain(c => !string.IsNullOrWhiteSpace(c.Overview));
foreach (var episode in episodes) episodes.Should().OnlyContain(c => c.SeasonNumber > 0 || c.EpisodeNumber > 0);
{
ValidateEpisode(episode);
//if atleast one episdoe has title it means parse it working.
// episodes.Should().Contain(c => !string.IsNullOrWhiteSpace(c.Title));
}
} }
private void ValidateEpisode(Episode episode)
{
episode.Should().NotBeNull();
//TODO: Is there a better way to validate that episode number or season number is greater than zero?
(episode.EpisodeNumber + episode.SeasonNumber).Should().NotBe(0);
episode.Should().NotBeNull();
// if (episode.AirDateUtc.HasValue)
// {
// episode.AirDateUtc.Value.Kind.Should().Be(DateTimeKind.Utc);
// }
}
} }
} }

View File

@ -107,6 +107,7 @@
<Compile Include="Configuration\ConfigServiceFixture.cs" /> <Compile Include="Configuration\ConfigServiceFixture.cs" />
<Compile Include="DataAugmentationFixture\Scene\SceneMappingProxyFixture.cs" /> <Compile Include="DataAugmentationFixture\Scene\SceneMappingProxyFixture.cs" />
<Compile Include="DataAugmentationFixture\Scene\SceneMappingServiceFixture.cs" /> <Compile Include="DataAugmentationFixture\Scene\SceneMappingServiceFixture.cs" />
<Compile Include="DataAugmentation\DailySeries\DailySeriesDataProxyFixture.cs" />
<Compile Include="Datastore\BasicRepositoryFixture.cs" /> <Compile Include="Datastore\BasicRepositoryFixture.cs" />
<Compile Include="Datastore\Converters\ProviderSettingConverterFixture.cs" /> <Compile Include="Datastore\Converters\ProviderSettingConverterFixture.cs" />
<Compile Include="Datastore\DatabaseFixture.cs" /> <Compile Include="Datastore\DatabaseFixture.cs" />
@ -380,9 +381,6 @@
</Content> </Content>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="Files\SceneMappings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="Files\TestArchive.tar.gz"> <None Include="Files\TestArchive.tar.gz">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>

View File

@ -24,6 +24,8 @@ namespace NzbDrone.Core.Test.TvTests
[TestFixtureSetUp] [TestFixtureSetUp]
public void TestFixture() public void TestFixture()
{ {
UseRealHttp();
_gameOfThrones = Mocker.Resolve<TraktProxy>().GetSeriesInfo(121361);//Game of thrones _gameOfThrones = Mocker.Resolve<TraktProxy>().GetSeriesInfo(121361);//Game of thrones
// Remove specials. // Remove specials.

View File

@ -1,6 +1,7 @@
using System; using System;
using FluentAssertions; using FluentAssertions;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Common;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Update; using NzbDrone.Core.Update;
@ -12,7 +13,7 @@ namespace NzbDrone.Core.Test.UpdateTests
public void no_update_when_version_higher() public void no_update_when_version_higher()
{ {
UseRealHttp(); UseRealHttp();
Subject.GetLatestUpdate("master", new Version(10,0)).Should().BeNull(); Subject.GetLatestUpdate("master", new Version(10, 0)).Should().BeNull();
} }
[Test] [Test]
@ -21,5 +22,21 @@ namespace NzbDrone.Core.Test.UpdateTests
UseRealHttp(); UseRealHttp();
Subject.GetLatestUpdate("master", new Version(2, 0)).Should().NotBeNull(); Subject.GetLatestUpdate("master", new Version(2, 0)).Should().NotBeNull();
} }
[Test]
public void should_get_recent_updates()
{
const string branch = "master";
UseRealHttp();
var recent = Subject.GetRecentUpdates(branch, 2);
recent.Should().NotBeEmpty();
recent.Should().OnlyContain(c => c.Hash.IsNotNullOrWhiteSpace());
recent.Should().OnlyContain(c => c.FileName.Contains("Drone.master.2"));
recent.Should().OnlyContain(c => c.ReleaseDate.Year == 2014);
recent.Should().OnlyContain(c => c.Changes.New != null);
recent.Should().OnlyContain(c => c.Changes.Fixed != null);
}
} }
} }

View File

@ -104,7 +104,7 @@ namespace NzbDrone.Core.Test.UpdateTests
Subject.Execute(new ApplicationUpdateCommand()); Subject.Execute(new ApplicationUpdateCommand());
Mocker.GetMock<IHttpProvider>().Verify(c => c.DownloadFile(_updatePackage.Url, updateArchive)); Mocker.GetMock<IHttpClient>().Verify(c => c.DownloadFile(_updatePackage.Url, updateArchive));
} }
[Test] [Test]
@ -124,8 +124,6 @@ namespace NzbDrone.Core.Test.UpdateTests
Subject.Execute(new ApplicationUpdateCommand()); Subject.Execute(new ApplicationUpdateCommand());
Mocker.GetMock<IDiskProvider>().Verify(c => c.MoveFolder(updateClientFolder, _sandboxFolder)); Mocker.GetMock<IDiskProvider>().Verify(c => c.MoveFolder(updateClientFolder, _sandboxFolder));
} }

View File

@ -0,0 +1,7 @@
namespace NzbDrone.Core.DataAugmentation.DailySeries
{
public class DailySeries
{
public int TvdbId { get; set; }
}
}

View File

@ -1,27 +1,27 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using NLog; using NLog;
using NzbDrone.Common; using NzbDrone.Common.Cloud;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Common.Serializer;
namespace NzbDrone.Core.DataAugmentation.DailySeries namespace NzbDrone.Core.DataAugmentation.DailySeries
{ {
public interface IDailySeriesDataProxy public interface IDailySeriesDataProxy
{ {
IEnumerable<int> GetDailySeriesIds(); IEnumerable<int> GetDailySeriesIds();
bool IsDailySeries(int tvdbid);
} }
public class DailySeriesDataProxy : IDailySeriesDataProxy public class DailySeriesDataProxy : IDailySeriesDataProxy
{ {
private readonly IHttpProvider _httpProvider; private readonly IHttpClient _httpClient;
private readonly IDroneServicesRequestBuilder _requestBuilder;
private readonly Logger _logger; private readonly Logger _logger;
public DailySeriesDataProxy(IHttpProvider httpProvider, Logger logger) public DailySeriesDataProxy(IHttpClient httpClient, IDroneServicesRequestBuilder requestBuilder, Logger logger)
{ {
_httpProvider = httpProvider; _httpClient = httpClient;
_requestBuilder = requestBuilder;
_logger = logger; _logger = logger;
} }
@ -29,32 +29,15 @@ namespace NzbDrone.Core.DataAugmentation.DailySeries
{ {
try try
{ {
var dailySeriesIds = _httpProvider.DownloadString(Services.RootUrl + "/v1/DailySeries"); var dailySeriesRequest = _requestBuilder.Build("dailyseries");
var response = _httpClient.Get<List<DailySeries>>(dailySeriesRequest);
var seriesIds = Json.Deserialize<List<int>>(dailySeriesIds); return response.Resource.Select(c => c.TvdbId);
return seriesIds;
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.WarnException("Failed to get Daily Series", ex); _logger.WarnException("Failed to get Daily Series", ex);
return new List<int>(); return new List<int>();
} }
}
public bool IsDailySeries(int tvdbid)
{
try
{
var result = _httpProvider.DownloadString(Services.RootUrl + "/v1/DailySeries?seriesId=" + tvdbid);
return Convert.ToBoolean(result);
}
catch (Exception ex)
{
_logger.WarnException("Failed to check Daily Series status for: " + tvdbid, ex);
return false;
}
} }
} }
} }

View File

@ -1,44 +1,30 @@
using NzbDrone.Core.Tv; using System;
using System.Collections.Generic;
using System.Linq;
using NzbDrone.Common.Cache;
namespace NzbDrone.Core.DataAugmentation.DailySeries namespace NzbDrone.Core.DataAugmentation.DailySeries
{ {
public interface IDailySeriesService public interface IDailySeriesService
{ {
void UpdateDailySeries();
bool IsDailySeries(int tvdbid); bool IsDailySeries(int tvdbid);
} }
public class DailySeriesService : IDailySeriesService public class DailySeriesService : IDailySeriesService
{ {
//TODO: add timer command
private readonly IDailySeriesDataProxy _proxy; private readonly IDailySeriesDataProxy _proxy;
private readonly ISeriesService _seriesService; private readonly ICached<List<int>> _cache;
public DailySeriesService(IDailySeriesDataProxy proxy, ISeriesService seriesService) public DailySeriesService(IDailySeriesDataProxy proxy, ICacheManager cacheManager)
{ {
_proxy = proxy; _proxy = proxy;
_seriesService = seriesService; _cache = cacheManager.GetCache<List<int>>(GetType());
}
public void UpdateDailySeries()
{
var dailySeries = _proxy.GetDailySeriesIds();
foreach (var tvdbId in dailySeries)
{
var series = _seriesService.FindByTvdbId(tvdbId);
if (series != null)
{
_seriesService.SetSeriesType(series.Id, SeriesTypes.Daily);
}
}
} }
public bool IsDailySeries(int tvdbid) public bool IsDailySeries(int tvdbid)
{ {
return _proxy.IsDailySeries(tvdbid); var dailySeries = _cache.Get("all", () => _proxy.GetDailySeriesIds().ToList(), TimeSpan.FromHours(1));
return dailySeries.Any(i => i == tvdbid);
} }
} }
} }

View File

@ -1,7 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using NzbDrone.Common; using NzbDrone.Common.Cloud;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Common.Serializer;
namespace NzbDrone.Core.DataAugmentation.Scene namespace NzbDrone.Core.DataAugmentation.Scene
{ {
@ -12,17 +11,19 @@ namespace NzbDrone.Core.DataAugmentation.Scene
public class SceneMappingProxy : ISceneMappingProxy public class SceneMappingProxy : ISceneMappingProxy
{ {
private readonly IHttpProvider _httpProvider; private readonly IHttpClient _httpClient;
private readonly IDroneServicesRequestBuilder _requestBuilder;
public SceneMappingProxy(IHttpProvider httpProvider) public SceneMappingProxy(IHttpClient httpClient, IDroneServicesRequestBuilder requestBuilder)
{ {
_httpProvider = httpProvider; _httpClient = httpClient;
_requestBuilder = requestBuilder;
} }
public List<SceneMapping> Fetch() public List<SceneMapping> Fetch()
{ {
var mappingsJson = _httpProvider.DownloadString(Services.RootUrl + "/v1/SceneMapping"); var request = _requestBuilder.Build("/scenemapping");
return Json.Deserialize<List<SceneMapping>>(mappingsJson); return _httpClient.Get<List<SceneMapping>>(request).Resource;
} }
} }
} }

View File

@ -3,10 +3,9 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using NLog; using NLog;
using NzbDrone.Common.Http;
using NzbDrone.Core.DataAugmentation.Scene; using NzbDrone.Core.DataAugmentation.Scene;
using NzbDrone.Core.DataAugmentation.Xem.Model; using NzbDrone.Core.DataAugmentation.Xem.Model;
using NzbDrone.Core.Rest;
using RestSharp;
namespace NzbDrone.Core.DataAugmentation.Xem namespace NzbDrone.Core.DataAugmentation.Xem
{ {
@ -20,34 +19,32 @@ namespace NzbDrone.Core.DataAugmentation.Xem
public class XemProxy : IXemProxy public class XemProxy : IXemProxy
{ {
private readonly Logger _logger; private readonly Logger _logger;
private readonly IHttpClient _httpClient;
private const string XEM_BASE_URL = "http://thexem.de/map/"; private const string XEM_BASE_URL = "http://thexem.de/map/";
private static readonly string[] IgnoredErrors = { "no single connection", "no show with the tvdb_id" }; private static readonly string[] IgnoredErrors = { "no single connection", "no show with the tvdb_id" };
private HttpRequestBuilder _xemRequestBuilder;
public XemProxy(Logger logger) public XemProxy(Logger logger, IHttpClient httpClient)
{ {
_logger = logger; _logger = logger;
_httpClient = httpClient;
_xemRequestBuilder = new HttpRequestBuilder(XEM_BASE_URL)
{
PostProcess = r => r.UriBuilder.SetQueryParam("origin", "tvdb")
};
} }
private static RestRequest BuildRequest(string resource)
{
var req = new RestRequest(resource, Method.GET);
req.AddParameter("origin", "tvdb");
return req;
}
public List<int> GetXemSeriesIds() public List<int> GetXemSeriesIds()
{ {
_logger.Debug("Fetching Series IDs from"); _logger.Debug("Fetching Series IDs from");
var restClient = RestClientFactory.BuildClient(XEM_BASE_URL); var request = _xemRequestBuilder.Build("/havemap");
var response = _httpClient.Get<XemResult<List<int>>>(request).Resource;
var request = BuildRequest("havemap");
var response = restClient.ExecuteAndValidate<XemResult<List<int>>>(request);
CheckForFailureResult(response); CheckForFailureResult(response);
return response.Data.ToList(); return response.Data.ToList();
@ -57,13 +54,11 @@ namespace NzbDrone.Core.DataAugmentation.Xem
{ {
_logger.Debug("Fetching Mappings for: {0}", id); _logger.Debug("Fetching Mappings for: {0}", id);
var restClient = RestClientFactory.BuildClient(XEM_BASE_URL);
var request = BuildRequest("all"); var request = _xemRequestBuilder.Build("/all");
request.AddParameter("id", id); request.UriBuilder.SetQueryParam("id", id);
var response = restClient.ExecuteAndValidate<XemResult<List<XemSceneTvdbMapping>>>(request); var response = _httpClient.Get<XemResult<List<XemSceneTvdbMapping>>>(request).Resource;
CheckForFailureResult(response);
return response.Data.Where(c => c.Scene != null).ToList(); return response.Data.Where(c => c.Scene != null).ToList();
} }
@ -71,14 +66,11 @@ namespace NzbDrone.Core.DataAugmentation.Xem
public List<SceneMapping> GetSceneTvdbNames() public List<SceneMapping> GetSceneTvdbNames()
{ {
_logger.Debug("Fetching alternate names"); _logger.Debug("Fetching alternate names");
var restClient = RestClientFactory.BuildClient(XEM_BASE_URL);
var request = BuildRequest("allNames"); var request = _xemRequestBuilder.Build("/allNames");
request.AddParameter("origin", "tvdb"); request.UriBuilder.SetQueryParam("seasonNumbers", true);
request.AddParameter("seasonNumbers", true);
var response = restClient.ExecuteAndValidate<XemResult<Dictionary<Int32, List<JObject>>>>(request); var response = _httpClient.Get<XemResult<Dictionary<Int32, List<JObject>>>>(request).Resource;
CheckForFailureResult(response);
var result = new List<SceneMapping>(); var result = new List<SceneMapping>();

View File

@ -18,10 +18,10 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
public class Nzbget : DownloadClientBase<NzbgetSettings> public class Nzbget : DownloadClientBase<NzbgetSettings>
{ {
private readonly INzbgetProxy _proxy; private readonly INzbgetProxy _proxy;
private readonly IHttpProvider _httpProvider; private readonly IHttpClient _httpClient;
public Nzbget(INzbgetProxy proxy, public Nzbget(INzbgetProxy proxy,
IHttpProvider httpProvider, IHttpClient httpClient,
IConfigService configService, IConfigService configService,
IDiskProvider diskProvider, IDiskProvider diskProvider,
IParsingService parsingService, IParsingService parsingService,
@ -29,7 +29,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
: base(configService, diskProvider, parsingService, logger) : base(configService, diskProvider, parsingService, logger)
{ {
_proxy = proxy; _proxy = proxy;
_httpProvider = httpProvider; _httpClient = httpClient;
} }
public override DownloadProtocol Protocol public override DownloadProtocol Protocol
@ -49,7 +49,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
_logger.Info("Adding report [{0}] to the queue.", title); _logger.Info("Adding report [{0}] to the queue.", title);
using (var nzb = _httpProvider.DownloadStream(url)) using (var nzb = _httpClient.Get(new HttpRequest(url)).GetStream())
{ {
_logger.Info("Adding report [{0}] to the queue.", title); _logger.Info("Adding report [{0}] to the queue.", title);
var response = _proxy.DownloadNzb(nzb, title, category, priority, Settings); var response = _proxy.DownloadNzb(nzb, title, category, priority, Settings);
@ -87,7 +87,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
var totalSize = MakeInt64(item.FileSizeHi, item.FileSizeLo); var totalSize = MakeInt64(item.FileSizeHi, item.FileSizeLo);
var pausedSize = MakeInt64(item.PausedSizeHi, item.PausedSizeLo); var pausedSize = MakeInt64(item.PausedSizeHi, item.PausedSizeLo);
var remainingSize = MakeInt64(item.RemainingSizeHi, item.RemainingSizeLo); var remainingSize = MakeInt64(item.RemainingSizeHi, item.RemainingSizeLo);
var droneParameter = item.Parameters.SingleOrDefault(p => p.Name == "drone"); var droneParameter = item.Parameters.SingleOrDefault(p => p.Name == "drone");
var queueItem = new DownloadClientItem(); var queueItem = new DownloadClientItem();
@ -152,7 +152,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
} }
var historyItems = new List<DownloadClientItem>(); var historyItems = new List<DownloadClientItem>();
var successStatus = new[] {"SUCCESS", "NONE"}; var successStatus = new[] { "SUCCESS", "NONE" };
foreach (var item in history) foreach (var item in history)
{ {
@ -190,7 +190,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
public override IEnumerable<DownloadClientItem> GetItems() public override IEnumerable<DownloadClientItem> GetItems()
{ {
Dictionary<String,String> config = null; Dictionary<String, String> config = null;
NzbgetCategory category = null; NzbgetCategory category = null;
try try
{ {
@ -270,7 +270,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
if (name == null) yield break; if (name == null) yield break;
var destDir = config.GetValueOrDefault("Category" + i + ".DestDir"); var destDir = config.GetValueOrDefault("Category" + i + ".DestDir");
if (destDir.IsNullOrWhiteSpace()) if (destDir.IsNullOrWhiteSpace())
{ {
var mainDir = config.GetValueOrDefault("MainDir"); var mainDir = config.GetValueOrDefault("MainDir");

View File

@ -16,16 +16,16 @@ namespace NzbDrone.Core.Download.Clients.Pneumatic
{ {
public class Pneumatic : DownloadClientBase<PneumaticSettings> public class Pneumatic : DownloadClientBase<PneumaticSettings>
{ {
private readonly IHttpProvider _httpProvider; private readonly IHttpClient _httpClient;
public Pneumatic(IHttpProvider httpProvider, public Pneumatic(IHttpClient httpClient,
IConfigService configService, IConfigService configService,
IDiskProvider diskProvider, IDiskProvider diskProvider,
IParsingService parsingService, IParsingService parsingService,
Logger logger) Logger logger)
: base(configService, diskProvider, parsingService, logger) : base(configService, diskProvider, parsingService, logger)
{ {
_httpProvider = httpProvider; _httpClient = httpClient;
} }
public override DownloadProtocol Protocol public override DownloadProtocol Protocol
@ -52,7 +52,7 @@ namespace NzbDrone.Core.Download.Clients.Pneumatic
var nzbFile = Path.Combine(Settings.NzbFolder, title + ".nzb"); var nzbFile = Path.Combine(Settings.NzbFolder, title + ".nzb");
_logger.Debug("Downloading NZB from: {0} to: {1}", url, nzbFile); _logger.Debug("Downloading NZB from: {0} to: {1}", url, nzbFile);
_httpProvider.DownloadFile(url, nzbFile); _httpClient.DownloadFile(url, nzbFile);
_logger.Debug("NZB Download succeeded, saved to: {0}", nzbFile); _logger.Debug("NZB Download succeeded, saved to: {0}", nzbFile);

View File

@ -18,11 +18,11 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
{ {
public class Sabnzbd : DownloadClientBase<SabnzbdSettings> public class Sabnzbd : DownloadClientBase<SabnzbdSettings>
{ {
private readonly IHttpProvider _httpProvider;
private readonly ISabnzbdProxy _proxy; private readonly ISabnzbdProxy _proxy;
private readonly IHttpClient _httpClient;
public Sabnzbd(ISabnzbdProxy proxy, public Sabnzbd(ISabnzbdProxy proxy,
IHttpProvider httpProvider, IHttpClient httpClient,
IConfigService configService, IConfigService configService,
IDiskProvider diskProvider, IDiskProvider diskProvider,
IParsingService parsingService, IParsingService parsingService,
@ -30,7 +30,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
: base(configService, diskProvider, parsingService, logger) : base(configService, diskProvider, parsingService, logger)
{ {
_proxy = proxy; _proxy = proxy;
_httpProvider = httpProvider; _httpClient = httpClient;
} }
public override DownloadProtocol Protocol public override DownloadProtocol Protocol
@ -48,7 +48,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
var category = Settings.TvCategory; var category = Settings.TvCategory;
var priority = remoteEpisode.IsRecentEpisode() ? Settings.RecentTvPriority : Settings.OlderTvPriority; var priority = remoteEpisode.IsRecentEpisode() ? Settings.RecentTvPriority : Settings.OlderTvPriority;
using (var nzb = _httpProvider.DownloadStream(url)) using (var nzb = _httpClient.Get(new HttpRequest(url)).GetStream())
{ {
_logger.Info("Adding report [{0}] to the queue.", title); _logger.Info("Adding report [{0}] to the queue.", title);
var response = _proxy.DownloadNzb(nzb, title, category, priority, Settings); var response = _proxy.DownloadNzb(nzb, title, category, priority, Settings);
@ -401,7 +401,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
return null; return null;
} }
private ValidationFailure TestGlobalConfig() private ValidationFailure TestGlobalConfig()
{ {
var config = _proxy.GetConfig(Settings); var config = _proxy.GetConfig(Settings);

View File

@ -19,10 +19,10 @@ namespace NzbDrone.Core.Download.Clients.UsenetBlackhole
public class UsenetBlackhole : DownloadClientBase<UsenetBlackholeSettings> public class UsenetBlackhole : DownloadClientBase<UsenetBlackholeSettings>
{ {
private readonly IDiskScanService _diskScanService; private readonly IDiskScanService _diskScanService;
private readonly IHttpProvider _httpProvider; private readonly IHttpClient _httpClient;
public UsenetBlackhole(IDiskScanService diskScanService, public UsenetBlackhole(IDiskScanService diskScanService,
IHttpProvider httpProvider, IHttpClient httpClient,
IConfigService configService, IConfigService configService,
IDiskProvider diskProvider, IDiskProvider diskProvider,
IParsingService parsingService, IParsingService parsingService,
@ -30,7 +30,7 @@ namespace NzbDrone.Core.Download.Clients.UsenetBlackhole
: base(configService, diskProvider, parsingService, logger) : base(configService, diskProvider, parsingService, logger)
{ {
_diskScanService = diskScanService; _diskScanService = diskScanService;
_httpProvider = httpProvider; _httpClient = httpClient;
} }
public override DownloadProtocol Protocol public override DownloadProtocol Protocol
@ -51,7 +51,7 @@ namespace NzbDrone.Core.Download.Clients.UsenetBlackhole
var filename = Path.Combine(Settings.NzbFolder, title + ".nzb"); var filename = Path.Combine(Settings.NzbFolder, title + ".nzb");
_logger.Debug("Downloading NZB from: {0} to: {1}", url, filename); _logger.Debug("Downloading NZB from: {0} to: {1}", url, filename);
_httpProvider.DownloadFile(url, filename); _httpClient.DownloadFile(url, filename);
_logger.Debug("NZB Download succeeded, saved to: {0}", filename); _logger.Debug("NZB Download succeeded, saved to: {0}", filename);
return null; return null;

View File

@ -1,8 +1,5 @@
using NLog; using NzbDrone.Common.Disk;
using NzbDrone.Common;
using NzbDrone.Common.Disk;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Common.Serializer;
namespace NzbDrone.Core.MediaCover namespace NzbDrone.Core.MediaCover
{ {
@ -14,14 +11,12 @@ namespace NzbDrone.Core.MediaCover
public class CoverAlreadyExistsSpecification : ICoverExistsSpecification public class CoverAlreadyExistsSpecification : ICoverExistsSpecification
{ {
private readonly IDiskProvider _diskProvider; private readonly IDiskProvider _diskProvider;
private readonly IHttpProvider _httpProvider; private readonly IHttpClient _httpClient;
private readonly Logger _logger;
public CoverAlreadyExistsSpecification(IDiskProvider diskProvider, IHttpProvider httpProvider, Logger logger) public CoverAlreadyExistsSpecification(IDiskProvider diskProvider, IHttpClient httpClient)
{ {
_diskProvider = diskProvider; _diskProvider = diskProvider;
_httpProvider = httpProvider; _httpClient = httpClient;
_logger = logger;
} }
public bool AlreadyExists(string url, string path) public bool AlreadyExists(string url, string path)
@ -31,22 +26,9 @@ namespace NzbDrone.Core.MediaCover
return false; return false;
} }
var headers = _httpProvider.GetHeader(url); var headers = _httpClient.Head(new HttpRequest(url)).Headers;
var fileSize = _diskProvider.GetFileSize(path);
string sizeString; return fileSize == headers.ContentLength;
if (headers.TryGetValue(HttpProvider.CONTENT_LENGTH_HEADER, out sizeString))
{
int size;
int.TryParse(sizeString, out size);
var fileSize = _diskProvider.GetFileSize(path);
return fileSize == size;
}
_logger.Warn("Couldn't find content-length header {0}", headers.ToJson());
return false;
} }
} }
} }

View File

@ -25,7 +25,7 @@ namespace NzbDrone.Core.MediaCover
IHandleAsync<SeriesDeletedEvent>, IHandleAsync<SeriesDeletedEvent>,
IMapCoversToLocal IMapCoversToLocal
{ {
private readonly IHttpProvider _httpProvider; private readonly IHttpClient _httpClient;
private readonly IDiskProvider _diskProvider; private readonly IDiskProvider _diskProvider;
private readonly ICoverExistsSpecification _coverExistsSpecification; private readonly ICoverExistsSpecification _coverExistsSpecification;
private readonly IConfigFileProvider _configFileProvider; private readonly IConfigFileProvider _configFileProvider;
@ -34,15 +34,15 @@ namespace NzbDrone.Core.MediaCover
private readonly string _coverRootFolder; private readonly string _coverRootFolder;
public MediaCoverService(IHttpProvider httpProvider, public MediaCoverService(IHttpClient httpClient,
IDiskProvider diskProvider, IDiskProvider diskProvider,
IAppFolderInfo appFolderInfo, IAppFolderInfo appFolderInfo,
ICoverExistsSpecification coverExistsSpecification, ICoverExistsSpecification coverExistsSpecification,
IConfigFileProvider configFileProvider, IConfigFileProvider configFileProvider,
IEventAggregator eventAggregator, IEventAggregator eventAggregator,
Logger logger) Logger logger)
{ {
_httpProvider = httpProvider; _httpClient = httpClient;
_diskProvider = diskProvider; _diskProvider = diskProvider;
_coverExistsSpecification = coverExistsSpecification; _coverExistsSpecification = coverExistsSpecification;
_configFileProvider = configFileProvider; _configFileProvider = configFileProvider;
@ -106,7 +106,7 @@ namespace NzbDrone.Core.MediaCover
var fileName = GetCoverPath(series.Id, cover.CoverType); var fileName = GetCoverPath(series.Id, cover.CoverType);
_logger.Info("Downloading {0} for {1} {2}", cover.CoverType, series, cover.Url); _logger.Info("Downloading {0} for {1} {2}", cover.CoverType, series, cover.Url);
_httpProvider.DownloadFile(cover.Url, fileName); _httpClient.DownloadFile(cover.Url, fileName);
} }
public void HandleAsync(SeriesUpdatedEvent message) public void HandleAsync(SeriesUpdatedEvent message)

View File

@ -29,7 +29,7 @@ namespace NzbDrone.Core.Metadata
private readonly IMediaFileService _mediaFileService; private readonly IMediaFileService _mediaFileService;
private readonly IEpisodeService _episodeService; private readonly IEpisodeService _episodeService;
private readonly IDiskProvider _diskProvider; private readonly IDiskProvider _diskProvider;
private readonly IHttpProvider _httpProvider; private readonly IHttpClient _httpClient;
private readonly IConfigService _configService; private readonly IConfigService _configService;
private readonly IEventAggregator _eventAggregator; private readonly IEventAggregator _eventAggregator;
private readonly Logger _logger; private readonly Logger _logger;
@ -40,7 +40,7 @@ namespace NzbDrone.Core.Metadata
IMediaFileService mediaFileService, IMediaFileService mediaFileService,
IEpisodeService episodeService, IEpisodeService episodeService,
IDiskProvider diskProvider, IDiskProvider diskProvider,
IHttpProvider httpProvider, IHttpClient httpClient,
IConfigService configService, IConfigService configService,
IEventAggregator eventAggregator, IEventAggregator eventAggregator,
Logger logger) Logger logger)
@ -51,7 +51,7 @@ namespace NzbDrone.Core.Metadata
_mediaFileService = mediaFileService; _mediaFileService = mediaFileService;
_episodeService = episodeService; _episodeService = episodeService;
_diskProvider = diskProvider; _diskProvider = diskProvider;
_httpProvider = httpProvider; _httpClient = httpClient;
_configService = configService; _configService = configService;
_eventAggregator = eventAggregator; _eventAggregator = eventAggregator;
_logger = logger; _logger = logger;
@ -336,7 +336,7 @@ namespace NzbDrone.Core.Metadata
{ {
try try
{ {
_httpProvider.DownloadFile(url, path); _httpClient.DownloadFile(url, path);
SetFilePermissions(path); SetFilePermissions(path);
} }
catch (WebException e) catch (WebException e)

View File

@ -2,86 +2,93 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Web;
using NLog; using NLog;
using NzbDrone.Common; using NzbDrone.Common;
using NzbDrone.Common.Http;
using NzbDrone.Core.MediaCover; using NzbDrone.Core.MediaCover;
using NzbDrone.Core.MetadataSource.Trakt; using NzbDrone.Core.MetadataSource.Trakt;
using NzbDrone.Core.Tv; using NzbDrone.Core.Tv;
using RestSharp;
using Episode = NzbDrone.Core.Tv.Episode; using Episode = NzbDrone.Core.Tv.Episode;
using NzbDrone.Core.Rest;
namespace NzbDrone.Core.MetadataSource namespace NzbDrone.Core.MetadataSource
{ {
public class TraktProxy : ISearchForNewSeries, IProvideSeriesInfo public class TraktProxy : ISearchForNewSeries, IProvideSeriesInfo
{ {
private readonly Logger _logger; private readonly Logger _logger;
private readonly IHttpClient _httpClient;
private static readonly Regex CollapseSpaceRegex = new Regex(@"\s+", RegexOptions.Compiled); private static readonly Regex CollapseSpaceRegex = new Regex(@"\s+", RegexOptions.Compiled);
private static readonly Regex InvalidSearchCharRegex = new Regex(@"(?:\*|\(|\)|'|!|@|\+)", RegexOptions.Compiled); private static readonly Regex InvalidSearchCharRegex = new Regex(@"(?:\*|\(|\)|'|!|@|\+)", RegexOptions.Compiled);
public TraktProxy(Logger logger)
private readonly HttpRequestBuilder _requestBuilder;
public TraktProxy(Logger logger, IHttpClient httpClient)
{ {
_requestBuilder = new HttpRequestBuilder("http://api.trakt.tv/{path}/{resource}.json/bc3c2c460f22cbb01c264022b540e191");
_logger = logger; _logger = logger;
_httpClient = httpClient;
} }
private IEnumerable<Show> SearchTrakt(string title)
{
HttpRequest request;
var lowerTitle = title.ToLowerInvariant();
if (lowerTitle.StartsWith("tvdb:") || lowerTitle.StartsWith("tvdbid:") || lowerTitle.StartsWith("slug:"))
{
var slug = lowerTitle.Split(':')[1].Trim();
if (slug.IsNullOrWhiteSpace() || slug.Any(char.IsWhiteSpace))
{
return Enumerable.Empty<Show>();
}
request = _requestBuilder.Build("/{slug}/extended");
request.AddSegment("path", "show");
request.AddSegment("resource", "summary");
request.AddSegment("slug", GetSearchTerm(slug));
return new List<Show> { _httpClient.Get<Show>(request).Resource };
}
if (lowerTitle.StartsWith("imdb:") || lowerTitle.StartsWith("imdbid:"))
{
var slug = lowerTitle.Split(':')[1].TrimStart('t').Trim();
if (slug.IsNullOrWhiteSpace() || !slug.All(char.IsDigit) || slug.Length < 7)
{
return Enumerable.Empty<Show>();
}
title = "tt" + slug;
}
request = _requestBuilder.Build("");
request.AddSegment("path", "search");
request.AddSegment("resource", "shows");
request.UriBuilder.SetQueryParam("query", GetSearchTerm(title));
request.UriBuilder.SetQueryParam("seasons", true);
return _httpClient.Get<List<Show>>(request).Resource;
}
public List<Series> SearchForNewSeries(string title) public List<Series> SearchForNewSeries(string title)
{ {
try try
{ {
if (title.StartsWith("imdb:") || title.StartsWith("imdbid:")) var series = SearchTrakt(title.Trim());
{
var slug = title.Split(':')[1].TrimStart('t');
if (slug.IsNullOrWhiteSpace() || !slug.All(char.IsDigit) || slug.Length < 7) return series.Select(MapSeries)
{ .OrderBy(s => title.LevenshteinDistanceClean(s.Title))
return new List<Series>(); .ToList();
}
title = "tt" + slug;
}
if (title.StartsWith("tvdb:") || title.StartsWith("tvdbid:") || title.StartsWith("slug:"))
{
try
{
var slug = title.Split(':')[1];
if (slug.IsNullOrWhiteSpace() || slug.Any(char.IsWhiteSpace))
{
return new List<Series>();
}
var client = BuildClient("show", "summary");
var restRequest = new RestRequest(GetSearchTerm(slug) + "/extended");
var response = client.ExecuteAndValidate<Show>(restRequest);
return new List<Series> { MapSeries(response) };
}
catch (RestException ex)
{
if (ex.Response.StatusCode == HttpStatusCode.NotFound)
{
return new List<Series>();
}
throw;
}
}
else
{
var client = BuildClient("search", "shows");
var restRequest = new RestRequest(GetSearchTerm(title) + "/30/seasons");
var response = client.ExecuteAndValidate<List<Show>>(restRequest);
return response.Select(MapSeries)
.OrderBy(v => title.LevenshteinDistanceClean(v.Title))
.ToList();
}
} }
catch (WebException) catch (HttpException)
{ {
throw new TraktException("Search for '{0}' failed. Unable to communicate with Trakt.", title); throw new TraktException("Search for '{0}' failed. Unable to communicate with Trakt.", title);
} }
@ -94,20 +101,31 @@ namespace NzbDrone.Core.MetadataSource
public Tuple<Series, List<Episode>> GetSeriesInfo(int tvdbSeriesId) public Tuple<Series, List<Episode>> GetSeriesInfo(int tvdbSeriesId)
{ {
var client = BuildClient("show", "summary");
var restRequest = new RestRequest(tvdbSeriesId.ToString() + "/extended"); var request = _requestBuilder.Build("/{tvdbId}/extended");
var response = client.ExecuteAndValidate<Show>(restRequest);
request.AddSegment("path", "show");
request.AddSegment("resource", "summary");
request.AddSegment("tvdbId", tvdbSeriesId.ToString());
var response = _httpClient.Get<Show>(request).Resource;
/*
var client = BuildClient("show", "summary");
var restRequest = new RestRequest(tvdbSeriesId + "/extended");
var response = client.ExecuteAndValidate<Show>(restRequest);*/
var episodes = response.seasons.SelectMany(c => c.episodes).Select(MapEpisode).ToList(); var episodes = response.seasons.SelectMany(c => c.episodes).Select(MapEpisode).ToList();
var series = MapSeries(response); var series = MapSeries(response);
return new Tuple<Series, List<Episode>>(series, episodes); return new Tuple<Series, List<Episode>>(series, episodes);
} }
/*
private static IRestClient BuildClient(string resource, string method) private static IRestClient BuildClient(string resource, string method)
{ {
return RestClientFactory.BuildClient(string.Format("http://api.trakt.tv/{0}/{1}.json/bc3c2c460f22cbb01c264022b540e191", resource, method)); return RestClientFactory.BuildClient(string.Format("http://api.trakt.tv/{0}/{1}.json/bc3c2c460f22cbb01c264022b540e191", resource, method));
} }*/
private static Series MapSeries(Show show) private static Series MapSeries(Show show)
{ {
@ -139,6 +157,18 @@ namespace NzbDrone.Core.MetadataSource
return series; return series;
} }
private static String GetTitleSlug(String url)
{
var slug = url.ToLower().Replace("http://trakt.tv/show/", "");
if (slug.StartsWith("."))
{
slug = "dot" + slug.Substring(1);
}
return slug;
}
private static Episode MapEpisode(Trakt.Episode traktEpisode) private static Episode MapEpisode(Trakt.Episode traktEpisode)
{ {
var episode = new Episode(); var episode = new Episode();
@ -179,13 +209,6 @@ namespace NzbDrone.Core.MetadataSource
return SeriesStatusType.Continuing; return SeriesStatusType.Continuing;
} }
private static DateTime? FromEpoch(long ticks)
{
if (ticks == 0) return null;
return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Unspecified).AddSeconds(ticks);
}
private static DateTime? FromIso(string iso) private static DateTime? FromIso(string iso)
{ {
DateTime result; DateTime result;
@ -213,7 +236,7 @@ namespace NzbDrone.Core.MetadataSource
phrase = InvalidSearchCharRegex.Replace(phrase, ""); phrase = InvalidSearchCharRegex.Replace(phrase, "");
phrase = CollapseSpaceRegex.Replace(phrase, " ").Trim().ToLower(); phrase = CollapseSpaceRegex.Replace(phrase, " ").Trim().ToLower();
phrase = phrase.Trim('-'); phrase = phrase.Trim('-');
phrase = HttpUtility.UrlEncode(phrase); phrase = System.Web.HttpUtility.UrlEncode(phrase);
return phrase; return phrase;
} }
@ -279,23 +302,13 @@ namespace NzbDrone.Core.MetadataSource
{ {
season.Images.Add(new MediaCover.MediaCover(MediaCoverTypes.Poster, traktSeason.images.poster)); season.Images.Add(new MediaCover.MediaCover(MediaCoverTypes.Poster, traktSeason.images.poster));
} }
seasons.Add(season); seasons.Add(season);
} }
return seasons; return seasons;
} }
private static String GetTitleSlug(String url)
{
var slug = url.ToLower().Replace("http://trakt.tv/show/", "");
if (slug.StartsWith("."))
{
slug = "dot" + slug.Substring(1);
}
return slug;
}
} }
} }

View File

@ -1,12 +1,10 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Xml.Linq; using System.Xml.Linq;
using NzbDrone.Core.Rest; using NzbDrone.Common.Http;
using NzbDrone.Core.Indexers; using NzbDrone.Core.Indexers;
using NzbDrone.Core.Tv; using NzbDrone.Core.Tv;
using RestSharp;
namespace NzbDrone.Core.MetadataSource.Tvdb namespace NzbDrone.Core.MetadataSource.Tvdb
{ {
@ -17,37 +15,22 @@ namespace NzbDrone.Core.MetadataSource.Tvdb
public class TvdbProxy : ITvdbProxy public class TvdbProxy : ITvdbProxy
{ {
public Tuple<Series, List<Episode>> GetSeriesInfo(int tvdbSeriesId) private readonly IHttpClient _httpClient;
public TvdbProxy(IHttpClient httpClient)
{ {
var client = BuildClient("series"); _httpClient = httpClient;
var request = new RestRequest(tvdbSeriesId + "/all");
var response = client.Execute(request);
var xml = XDocument.Load(new StringReader(response.Content));
var episodes = xml.Descendants("Episode").Select(MapEpisode).ToList();
var series = MapSeries(xml.Element("Series"));
return new Tuple<Series, List<Episode>>(series, episodes);
} }
public List<Episode> GetEpisodeInfo(int tvdbSeriesId) public List<Episode> GetEpisodeInfo(int tvdbSeriesId)
{ {
return GetSeriesInfo(tvdbSeriesId).Item2; var httpRequest = new HttpRequest("http://thetvdb.com/data/series/{tvdbId}/all/");
} httpRequest.AddSegment("tvdbId", tvdbSeriesId.ToString());
var response = _httpClient.Get(httpRequest);
private static IRestClient BuildClient(string resource) var xml = XDocument.Load(new StringReader(response.Content));
{ var episodes = xml.Descendants("Episode").Select(MapEpisode).ToList();
return RestClientFactory.BuildClient(String.Format("http://thetvdb.com/data/{0}", resource)); return episodes;
}
private static Series MapSeries(XElement item)
{
//TODO: We should map all the data incase we want to actually use it
var series = new Series();
return series;
} }
private static Episode MapEpisode(XElement item) private static Episode MapEpisode(XElement item)

View File

@ -128,6 +128,7 @@
<Compile Include="Configuration\IConfigService.cs" /> <Compile Include="Configuration\IConfigService.cs" />
<Compile Include="Configuration\InvalidConfigFileException.cs" /> <Compile Include="Configuration\InvalidConfigFileException.cs" />
<Compile Include="Configuration\ResetApiKeyCommand.cs" /> <Compile Include="Configuration\ResetApiKeyCommand.cs" />
<Compile Include="DataAugmentation\DailySeries\DailySeries.cs" />
<Compile Include="DataAugmentation\DailySeries\DailySeriesDataProxy.cs" /> <Compile Include="DataAugmentation\DailySeries\DailySeriesDataProxy.cs" />
<Compile Include="DataAugmentation\DailySeries\DailySeriesService.cs" /> <Compile Include="DataAugmentation\DailySeries\DailySeriesService.cs" />
<Compile Include="DataAugmentation\Scene\ISceneMappingProvider.cs" /> <Compile Include="DataAugmentation\Scene\ISceneMappingProvider.cs" />

View File

@ -26,7 +26,7 @@ namespace NzbDrone.Core.Update
private readonly IAppFolderInfo _appFolderInfo; private readonly IAppFolderInfo _appFolderInfo;
private readonly IDiskProvider _diskProvider; private readonly IDiskProvider _diskProvider;
private readonly IHttpProvider _httpProvider; private readonly IHttpClient _httpClient;
private readonly IArchiveService _archiveService; private readonly IArchiveService _archiveService;
private readonly IProcessProvider _processProvider; private readonly IProcessProvider _processProvider;
private readonly IVerifyUpdates _updateVerifier; private readonly IVerifyUpdates _updateVerifier;
@ -36,7 +36,7 @@ namespace NzbDrone.Core.Update
public InstallUpdateService(ICheckUpdateService checkUpdateService, IAppFolderInfo appFolderInfo, public InstallUpdateService(ICheckUpdateService checkUpdateService, IAppFolderInfo appFolderInfo,
IDiskProvider diskProvider, IHttpProvider httpProvider, IDiskProvider diskProvider, IHttpClient httpClient,
IArchiveService archiveService, IProcessProvider processProvider, IArchiveService archiveService, IProcessProvider processProvider,
IVerifyUpdates updateVerifier, IVerifyUpdates updateVerifier,
IConfigFileProvider configFileProvider, IConfigFileProvider configFileProvider,
@ -51,7 +51,7 @@ namespace NzbDrone.Core.Update
_checkUpdateService = checkUpdateService; _checkUpdateService = checkUpdateService;
_appFolderInfo = appFolderInfo; _appFolderInfo = appFolderInfo;
_diskProvider = diskProvider; _diskProvider = diskProvider;
_httpProvider = httpProvider; _httpClient = httpClient;
_archiveService = archiveService; _archiveService = archiveService;
_processProvider = processProvider; _processProvider = processProvider;
_updateVerifier = updateVerifier; _updateVerifier = updateVerifier;
@ -79,7 +79,7 @@ namespace NzbDrone.Core.Update
_logger.ProgressInfo("Downloading update {0}", updatePackage.Version); _logger.ProgressInfo("Downloading update {0}", updatePackage.Version);
_logger.Debug("Downloading update package from [{0}] to [{1}]", updatePackage.Url, packageDestination); _logger.Debug("Downloading update package from [{0}] to [{1}]", updatePackage.Url, packageDestination);
_httpProvider.DownloadFile(updatePackage.Url, packageDestination); _httpClient.DownloadFile(updatePackage.Url, packageDestination);
_logger.ProgressInfo("Verifying update package"); _logger.ProgressInfo("Verifying update package");

View File

@ -1,4 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
namespace NzbDrone.Core.Update namespace NzbDrone.Core.Update
@ -23,7 +24,7 @@ namespace NzbDrone.Core.Update
public List<UpdatePackage> GetRecentUpdatePackages() public List<UpdatePackage> GetRecentUpdatePackages()
{ {
var branch = _configFileProvider.Branch; var branch = _configFileProvider.Branch;
return _updatePackageProvider.GetRecentUpdates(branch); return _updatePackageProvider.GetRecentUpdates(branch, BuildInfo.Version.Major);
} }
} }
} }

View File

@ -6,7 +6,6 @@ namespace NzbDrone.Core.Update
public class UpdatePackage public class UpdatePackage
{ {
public Version Version { get; set; } public Version Version { get; set; }
public String Branch { get; set; }
public DateTime ReleaseDate { get; set; } public DateTime ReleaseDate { get; set; }
public String FileName { get; set; } public String FileName { get; set; }
public String Url { get; set; } public String Url { get; set; }

View File

@ -1,50 +1,51 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using NzbDrone.Common; using NzbDrone.Common.Cloud;
using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.EnvironmentInfo;
using RestSharp; using NzbDrone.Common.Http;
using NzbDrone.Core.Rest;
namespace NzbDrone.Core.Update namespace NzbDrone.Core.Update
{ {
public interface IUpdatePackageProvider public interface IUpdatePackageProvider
{ {
UpdatePackage GetLatestUpdate(string branch, Version currentVersion); UpdatePackage GetLatestUpdate(string branch, Version currentVersion);
List<UpdatePackage> GetRecentUpdates(string branch); List<UpdatePackage> GetRecentUpdates(string branch, int majorVersion);
} }
public class UpdatePackageProvider : IUpdatePackageProvider public class UpdatePackageProvider : IUpdatePackageProvider
{ {
private readonly IHttpClient _httpClient;
private readonly IDroneServicesRequestBuilder _requestBuilder;
public UpdatePackageProvider(IHttpClient httpClient, IDroneServicesRequestBuilder requestBuilder)
{
_httpClient = httpClient;
_requestBuilder = requestBuilder;
}
public UpdatePackage GetLatestUpdate(string branch, Version currentVersion) public UpdatePackage GetLatestUpdate(string branch, Version currentVersion)
{ {
var restClient = RestClientFactory.BuildClient(Services.RootUrl); var request = _requestBuilder.Build("/update/{branch}");
request.UriBuilder.SetQueryParam("version", currentVersion);
request.UriBuilder.SetQueryParam("os", OsInfo.Os.ToString().ToLowerInvariant());
request.AddSegment("branch", branch);
var request = new RestRequest("/v1/update/{branch}"); var update = _httpClient.Get<UpdatePackageAvailable>(request).Resource;
request.AddParameter("version", currentVersion);
request.AddParameter("os", OsInfo.Os.ToString().ToLowerInvariant());
request.AddUrlSegment("branch", branch);
var update = restClient.ExecuteAndValidate<UpdatePackageAvailable>(request);
if (!update.Available) return null; if (!update.Available) return null;
return update.UpdatePackage; return update.UpdatePackage;
} }
public List<UpdatePackage> GetRecentUpdates(string branch) public List<UpdatePackage> GetRecentUpdates(string branch, int majorVersion)
{ {
var restClient = RestClientFactory.BuildClient(Services.RootUrl); var request = _requestBuilder.Build("/update/{branch}/changes");
request.UriBuilder.SetQueryParam("os", OsInfo.Os.ToString().ToLowerInvariant());
request.AddSegment("branch", branch);
var request = new RestRequest("/v1/update/{branch}/changes"); var updates = _httpClient.Get<List<UpdatePackage>>(request);
request.AddParameter("majorVersion", BuildInfo.Version.Major); return updates.Resource;
request.AddParameter("os", OsInfo.Os.ToString().ToLowerInvariant());
request.AddUrlSegment("branch", branch);
var updates = restClient.ExecuteAndValidate<List<UpdatePackage>>(request);
return updates;
} }
} }
} }

View File

@ -8,14 +8,12 @@ namespace NzbDrone.Test.Common
{ {
public abstract class LoggingTest public abstract class LoggingTest
{ {
protected static Logger TestLogger; protected static readonly Logger TestLogger = LogManager.GetLogger("TestLogger");
protected static void InitLogging() protected static void InitLogging()
{ {
new StartupContext(); new StartupContext();
TestLogger = LogManager.GetLogger("TestLogger");
if (LogManager.Configuration == null || LogManager.Configuration is XmlLoggingConfiguration) if (LogManager.Configuration == null || LogManager.Configuration is XmlLoggingConfiguration)
{ {
LogManager.Configuration = new LoggingConfiguration(); LogManager.Configuration = new LoggingConfiguration();
@ -44,8 +42,6 @@ namespace NzbDrone.Test.Common
[TearDown] [TearDown]
public void LoggingDownBase() public void LoggingDownBase()
{ {
//can't use because of a bug in mono with 2.6.2, //can't use because of a bug in mono with 2.6.2,
//https://bugs.launchpad.net/nunitv2/+bug/1076932 //https://bugs.launchpad.net/nunitv2/+bug/1076932
if (BuildInfo.IsDebug && TestContext.CurrentContext.Result.State == TestState.Success) if (BuildInfo.IsDebug && TestContext.CurrentContext.Result.State == TestState.Success)

View File

@ -54,6 +54,9 @@ namespace NzbDrone.Test.Common
if (_mocker == null) if (_mocker == null)
{ {
_mocker = new AutoMoqer(); _mocker = new AutoMoqer();
_mocker.SetConstant<ICacheManager>(new CacheManager());
_mocker.SetConstant<IStartupContext>(new StartupContext(new string[0]));
_mocker.SetConstant(TestLogger);
} }
return _mocker; return _mocker;
@ -89,11 +92,7 @@ namespace NzbDrone.Test.Common
GetType().IsPublic.Should().BeTrue("All Test fixtures should be public to work in mono."); GetType().IsPublic.Should().BeTrue("All Test fixtures should be public to work in mono.");
Mocker.SetConstant<ICacheManager>(new CacheManager());
Mocker.SetConstant(LogManager.GetLogger("TestLogger"));
Mocker.SetConstant<IStartupContext>(new StartupContext(new string[0]));
LogManager.ReconfigExistingLoggers(); LogManager.ReconfigExistingLoggers();
@ -140,7 +139,7 @@ namespace NzbDrone.Test.Common
{ {
if (!OsInfo.IsMono) if (!OsInfo.IsMono)
{ {
throw new IgnoreException("linux specific test"); throw new IgnoreException("mono specific test");
} }
} }