Feature/test for #441 (#444)

* #441 added a test for this change

* #441 bit of tidying up and fixing of erros
This commit is contained in:
Tom Pallister 2018-07-01 08:56:06 +01:00 committed by GitHub
parent 2832cb1bf4
commit a87bc92c60
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 105 additions and 67 deletions

View File

@ -61,7 +61,7 @@
downstreamRoute = new OkResponse<DownstreamRoute>(new DownstreamRoute(new List<PlaceholderNameAndValue>(), reRoute)); downstreamRoute = new OkResponse<DownstreamRoute>(new DownstreamRoute(new List<PlaceholderNameAndValue>(), reRoute));
_cache.AddOrUpdate(loadBalancerKey, downstreamRoute, (x, y) => downstreamRoute); _cache.AddOrUpdate(loadBalancerKey, downstreamRoute, (x, y) => downstreamRoute);
return downstreamRoute; return downstreamRoute;
} }

View File

@ -20,7 +20,7 @@ namespace Ocelot.LoadBalancer.LoadBalancers
public async Task<Response<ServiceHostAndPort>> Lease(DownstreamContext downstreamContext) public async Task<Response<ServiceHostAndPort>> Lease(DownstreamContext downstreamContext)
{ {
var services = await _services(); var services = await _services();
//todo first or default could be null..
if (services == null || services.Count == 0) if (services == null || services.Count == 0)
{ {
return new ErrorResponse<ServiceHostAndPort>(new ServicesAreEmptyError("There were no services in NoLoadBalancer")); return new ErrorResponse<ServiceHostAndPort>(new ServicesAreEmptyError("There were no services in NoLoadBalancer"));

View File

@ -99,6 +99,7 @@ namespace Ocelot.Raft
} }
} }
} }
_sempaphore.Release(); _sempaphore.Release();
return result; return result;
} }
@ -120,6 +121,7 @@ namespace Ocelot.Raft
} }
} }
} }
_sempaphore.Release(); _sempaphore.Release();
return result; return result;
} }
@ -135,6 +137,7 @@ namespace Ocelot.Raft
TypeNameHandling = TypeNameHandling.All TypeNameHandling = TypeNameHandling.All
}; };
var data = JsonConvert.SerializeObject(log, jsonSerializerSettings); var data = JsonConvert.SerializeObject(log, jsonSerializerSettings);
//todo - sql injection dont copy this.. //todo - sql injection dont copy this..
var sql = $"insert into logs (data) values ('{data}')"; var sql = $"insert into logs (data) values ('{data}')";
_logger.LogInformation($"id: {_nodeId.Id}, sql: {sql}"); _logger.LogInformation($"id: {_nodeId.Id}, sql: {sql}");
@ -162,6 +165,7 @@ namespace Ocelot.Raft
using (var connection = new SqliteConnection($"Data Source={_path};")) using (var connection = new SqliteConnection($"Data Source={_path};"))
{ {
connection.Open(); connection.Open();
//todo - sql injection dont copy this.. //todo - sql injection dont copy this..
var sql = $"select data from logs where id = {index};"; var sql = $"select data from logs where id = {index};";
_logger.LogInformation($"id: {_nodeId.Id} sql: {sql}"); _logger.LogInformation($"id: {_nodeId.Id} sql: {sql}");
@ -188,6 +192,7 @@ namespace Ocelot.Raft
} }
} }
} }
_sempaphore.Release(); _sempaphore.Release();
} }
@ -197,6 +202,7 @@ namespace Ocelot.Raft
using (var connection = new SqliteConnection($"Data Source={_path};")) using (var connection = new SqliteConnection($"Data Source={_path};"))
{ {
connection.Open(); connection.Open();
//todo - sql injection dont copy this.. //todo - sql injection dont copy this..
var sql = $"select data from logs where id = {index};"; var sql = $"select data from logs where id = {index};";
using (var command = new SqliteCommand(sql, connection)) using (var command = new SqliteCommand(sql, connection))
@ -227,6 +233,7 @@ namespace Ocelot.Raft
using (var connection = new SqliteConnection($"Data Source={_path};")) using (var connection = new SqliteConnection($"Data Source={_path};"))
{ {
connection.Open(); connection.Open();
//todo - sql injection dont copy this.. //todo - sql injection dont copy this..
var sql = $"select data from logs where id = {index}"; var sql = $"select data from logs where id = {index}";
using (var command = new SqliteCommand(sql, connection)) using (var command = new SqliteCommand(sql, connection))
@ -251,6 +258,7 @@ namespace Ocelot.Raft
using (var connection = new SqliteConnection($"Data Source={_path};")) using (var connection = new SqliteConnection($"Data Source={_path};"))
{ {
connection.Open(); connection.Open();
//todo - sql injection dont copy this.. //todo - sql injection dont copy this..
var sql = $"select id, data from logs where id >= {index}"; var sql = $"select id, data from logs where id >= {index}";
using (var command = new SqliteCommand(sql, connection)) using (var command = new SqliteCommand(sql, connection))
@ -267,10 +275,10 @@ namespace Ocelot.Raft
}; };
var log = JsonConvert.DeserializeObject<LogEntry>(data, jsonSerializerSettings); var log = JsonConvert.DeserializeObject<LogEntry>(data, jsonSerializerSettings);
logsToReturn.Add((id, log)); logsToReturn.Add((id, log));
} }
} }
} }
_sempaphore.Release(); _sempaphore.Release();
return logsToReturn; return logsToReturn;
} }
@ -283,6 +291,7 @@ namespace Ocelot.Raft
using (var connection = new SqliteConnection($"Data Source={_path};")) using (var connection = new SqliteConnection($"Data Source={_path};"))
{ {
connection.Open(); connection.Open();
//todo - sql injection dont copy this.. //todo - sql injection dont copy this..
var sql = $"select data from logs where id = {index}"; var sql = $"select data from logs where id = {index}";
using (var command = new SqliteCommand(sql, connection)) using (var command = new SqliteCommand(sql, connection))
@ -299,15 +308,18 @@ namespace Ocelot.Raft
} }
} }
} }
_sempaphore.Release(); _sempaphore.Release();
return result; return result;
} }
public async Task Remove(int indexOfCommand) public async Task Remove(int indexOfCommand)
{ {
_sempaphore.Wait(); _sempaphore.Wait();
using (var connection = new SqliteConnection($"Data Source={_path};")) using (var connection = new SqliteConnection($"Data Source={_path};"))
{ {
connection.Open(); connection.Open();
//todo - sql injection dont copy this.. //todo - sql injection dont copy this..
var deleteSql = $"delete from logs where id >= {indexOfCommand};"; var deleteSql = $"delete from logs where id >= {indexOfCommand};";
_logger.LogInformation($"id: {_nodeId.Id} Remove {deleteSql}"); _logger.LogInformation($"id: {_nodeId.Id} Remove {deleteSql}");
@ -316,6 +328,7 @@ namespace Ocelot.Raft
var result = await deleteCommand.ExecuteNonQueryAsync(); var result = await deleteCommand.ExecuteNonQueryAsync();
} }
} }
_sempaphore.Release(); _sempaphore.Release();
} }
} }

View File

@ -1,16 +1,10 @@
using System; namespace Ocelot.Requester
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
namespace Ocelot.Requester
{ {
using System;
public interface IHttpClientCache public interface IHttpClientCache
{ {
bool Exists(string id);
IHttpClient Get(string id); IHttpClient Get(string id);
void Remove(string id);
void Set(string id, IHttpClient handler, TimeSpan expirationTime); void Set(string id, IHttpClient handler, TimeSpan expirationTime);
} }
} }

View File

@ -1,21 +1,20 @@
using Microsoft.Extensions.Caching.Memory; namespace Ocelot.Requester
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
namespace Ocelot.Requester
{ {
using System;
using System.Collections.Concurrent;
public class MemoryHttpClientCache : IHttpClientCache public class MemoryHttpClientCache : IHttpClientCache
{ {
private readonly ConcurrentDictionary<string, ConcurrentQueue<IHttpClient>> _httpClientsCache = new ConcurrentDictionary<string, ConcurrentQueue<IHttpClient>>(); private readonly ConcurrentDictionary<string, ConcurrentQueue<IHttpClient>> _httpClientsCache;
public MemoryHttpClientCache()
{
_httpClientsCache = new ConcurrentDictionary<string, ConcurrentQueue<IHttpClient>>();
}
public void Set(string id, IHttpClient client, TimeSpan expirationTime) public void Set(string id, IHttpClient client, TimeSpan expirationTime)
{ {
ConcurrentQueue<IHttpClient> connectionQueue; if (_httpClientsCache.TryGetValue(id, out var connectionQueue))
if (_httpClientsCache.TryGetValue(id, out connectionQueue))
{ {
connectionQueue.Enqueue(client); connectionQueue.Enqueue(client);
} }
@ -27,28 +26,15 @@ namespace Ocelot.Requester
} }
} }
public bool Exists(string id)
{
ConcurrentQueue<IHttpClient> connectionQueue;
return _httpClientsCache.TryGetValue(id, out connectionQueue);
}
public IHttpClient Get(string id) public IHttpClient Get(string id)
{ {
IHttpClient client= null; IHttpClient client= null;
ConcurrentQueue<IHttpClient> connectionQueue; if (_httpClientsCache.TryGetValue(id, out var connectionQueue))
if (_httpClientsCache.TryGetValue(id, out connectionQueue))
{ {
connectionQueue.TryDequeue(out client); connectionQueue.TryDequeue(out client);
} }
return client; return client;
} }
public void Remove(string id)
{
ConcurrentQueue<IHttpClient> connectionQueue;
_httpClientsCache.TryRemove(id, out connectionQueue);
}
} }
} }

View File

@ -45,7 +45,6 @@ namespace Ocelot.UnitTests.Middleware
services.AddDiscoveryClient(new DiscoveryOptions services.AddDiscoveryClient(new DiscoveryOptions
{ {
ClientType = DiscoveryClientType.EUREKA, ClientType = DiscoveryClientType.EUREKA,
//options can not be null
ClientOptions = new EurekaClientOptions() ClientOptions = new EurekaClientOptions()
{ {
ShouldFetchRegistry = false, ShouldFetchRegistry = false,

View File

@ -23,15 +23,18 @@ namespace Ocelot.UnitTests.Requester
{ {
public class HttpClientBuilderTests : IDisposable public class HttpClientBuilderTests : IDisposable
{ {
private readonly HttpClientBuilder _builder; private HttpClientBuilder _builder;
private readonly Mock<IDelegatingHandlerHandlerFactory> _factory; private readonly Mock<IDelegatingHandlerHandlerFactory> _factory;
private IHttpClient _httpClient; private IHttpClient _httpClient;
private HttpResponseMessage _response; private HttpResponseMessage _response;
private DownstreamContext _context; private DownstreamContext _context;
private readonly Mock<IHttpClientCache> _cacheHandlers; private readonly Mock<IHttpClientCache> _cacheHandlers;
private Mock<IOcelotLogger> _logger; private readonly Mock<IOcelotLogger> _logger;
private int _count; private int _count;
private IWebHost _host; private IWebHost _host;
private IHttpClient _againHttpClient;
private IHttpClient _firstHttpClient;
private MemoryHttpClientCache _realCache;
public HttpClientBuilderTests() public HttpClientBuilderTests()
{ {
@ -61,6 +64,47 @@ namespace Ocelot.UnitTests.Requester
.BDDfy(); .BDDfy();
} }
[Fact]
public void should_get_from_cache()
{
var qosOptions = new QoSOptionsBuilder()
.Build();
var reRoute = new DownstreamReRouteBuilder()
.WithQosOptions(qosOptions)
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true))
.WithLoadBalancerKey("")
.WithQosOptions(new QoSOptionsBuilder().Build())
.Build();
this.Given(x => GivenARealCache())
.And(x => GivenTheFactoryReturns())
.And(x => GivenARequest(reRoute))
.And(x => WhenIBuildTheFirstTime())
.And(x => WhenISave())
.And(x => WhenIBuildAgain())
.And(x => WhenISave())
.When(x => WhenIBuildAgain())
.Then(x => ThenTheHttpClientIsFromTheCache())
.BDDfy();
}
private void GivenARealCache()
{
_realCache = new MemoryHttpClientCache();
_builder = new HttpClientBuilder(_factory.Object, _realCache, _logger.Object);
}
private void ThenTheHttpClientIsFromTheCache()
{
_againHttpClient.ShouldBe(_firstHttpClient);
}
private void WhenISave()
{
_builder.Save();
}
[Fact] [Fact]
public void should_log_if_ignoring_ssl_errors() public void should_log_if_ignoring_ssl_errors()
{ {
@ -302,6 +346,17 @@ namespace Ocelot.UnitTests.Requester
_httpClient = _builder.Create(_context); _httpClient = _builder.Create(_context);
} }
private void WhenIBuildTheFirstTime()
{
_firstHttpClient = _builder.Create(_context);
}
private void WhenIBuildAgain()
{
_builder = new HttpClientBuilder(_factory.Object, _realCache, _logger.Object);
_againHttpClient = _builder.Create(_context);
}
private void ThenTheHttpClientShouldNotBeNull() private void ThenTheHttpClientShouldNotBeNull()
{ {
_httpClient.ShouldNotBeNull(); _httpClient.ShouldNotBeNull();

View File

@ -1,33 +1,24 @@
using System; namespace Ocelot.UnitTests.ServiceDiscovery
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Consul;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Moq;
using Ocelot.Infrastructure.Consul;
using Ocelot.Logging;
using Ocelot.ServiceDiscovery.Configuration;
using Ocelot.ServiceDiscovery.Providers;
using Ocelot.Values;
using Xunit;
using TestStack.BDDfy;
using Shouldly;
using static Ocelot.Infrastructure.Wait;
namespace Ocelot.UnitTests.ServiceDiscovery
{ {
using System;
using System.Collections.Generic;
using Moq;
using Ocelot.Logging;
using Ocelot.ServiceDiscovery.Providers;
using Ocelot.Values;
using Xunit;
using TestStack.BDDfy;
using Shouldly;
using static Ocelot.Infrastructure.Wait;
public class PollingConsulServiceDiscoveryProviderTests public class PollingConsulServiceDiscoveryProviderTests
{ {
private readonly int _delay; private readonly int _delay;
private PollingConsulServiceDiscoveryProvider _provider; private PollingConsulServiceDiscoveryProvider _provider;
private readonly string _serviceName; private readonly List<Service> _services;
private List<Service> _services;
private readonly Mock<IOcelotLoggerFactory> _factory; private readonly Mock<IOcelotLoggerFactory> _factory;
private readonly Mock<IOcelotLogger> _logger; private readonly Mock<IOcelotLogger> _logger;
private Mock<IServiceDiscoveryProvider> _consulServiceDiscoveryProvider; private readonly Mock<IServiceDiscoveryProvider> _consulServiceDiscoveryProvider;
private List<Service> _result; private List<Service> _result;
public PollingConsulServiceDiscoveryProviderTests() public PollingConsulServiceDiscoveryProviderTests()
@ -64,7 +55,7 @@ namespace Ocelot.UnitTests.ServiceDiscovery
private void WhenIGetTheServices(int expected) private void WhenIGetTheServices(int expected)
{ {
_provider = new PollingConsulServiceDiscoveryProvider(_delay, _serviceName, _factory.Object, _consulServiceDiscoveryProvider.Object); _provider = new PollingConsulServiceDiscoveryProvider(_delay, "", _factory.Object, _consulServiceDiscoveryProvider.Object);
var result = WaitFor(3000).Until(() => { var result = WaitFor(3000).Until(() => {
try try