mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-06-19 08:38:14 +08:00
hacked together load balancing reroutes in fileconfig (#211)
* hacked together load balancing reroutes in fileconfig * some renaming and refactoring * more renames * hacked away the old config json * test for issue 213 * renamed key * dont share ports * oops * updated docs * mvoed docs around * port being used
This commit is contained in:
@ -1,285 +1,285 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Ocelot.LoadBalancer.LoadBalancers;
|
||||
using Ocelot.Responses;
|
||||
using Ocelot.Values;
|
||||
using Shouldly;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.LoadBalancer
|
||||
{
|
||||
public class LeastConnectionTests
|
||||
{
|
||||
private HostAndPort _hostAndPort;
|
||||
private Response<HostAndPort> _result;
|
||||
private LeastConnection _leastConnection;
|
||||
private List<Service> _services;
|
||||
private Random _random;
|
||||
|
||||
public LeastConnectionTests()
|
||||
{
|
||||
_random = new Random();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_be_able_to_lease_and_release_concurrently()
|
||||
{
|
||||
var serviceName = "products";
|
||||
|
||||
var availableServices = new List<Service>
|
||||
{
|
||||
new Service(serviceName, new HostAndPort("127.0.0.1", 80), string.Empty, string.Empty, new string[0]),
|
||||
new Service(serviceName, new HostAndPort("127.0.0.2", 80), string.Empty, string.Empty, new string[0]),
|
||||
};
|
||||
|
||||
_services = availableServices;
|
||||
_leastConnection = new LeastConnection(() => Task.FromResult(_services), serviceName);
|
||||
|
||||
var tasks = new Task[100];
|
||||
|
||||
for(var i = 0; i < tasks.Length; i++)
|
||||
{
|
||||
tasks[i] = LeaseDelayAndRelease();
|
||||
}
|
||||
|
||||
Task.WaitAll(tasks);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_handle_service_returning_to_available()
|
||||
{
|
||||
var serviceName = "products";
|
||||
|
||||
var availableServices = new List<Service>
|
||||
{
|
||||
new Service(serviceName, new HostAndPort("127.0.0.1", 80), string.Empty, string.Empty, new string[0]),
|
||||
new Service(serviceName, new HostAndPort("127.0.0.2", 80), string.Empty, string.Empty, new string[0]),
|
||||
};
|
||||
|
||||
_leastConnection = new LeastConnection(() => Task.FromResult(availableServices), serviceName);
|
||||
|
||||
var hostAndPortOne = _leastConnection.Lease().Result;
|
||||
hostAndPortOne.Data.DownstreamHost.ShouldBe("127.0.0.1");
|
||||
var hostAndPortTwo = _leastConnection.Lease().Result;
|
||||
hostAndPortTwo.Data.DownstreamHost.ShouldBe("127.0.0.2");
|
||||
_leastConnection.Release(hostAndPortOne.Data);
|
||||
_leastConnection.Release(hostAndPortTwo.Data);
|
||||
|
||||
availableServices = new List<Service>
|
||||
{
|
||||
new Service(serviceName, new HostAndPort("127.0.0.1", 80), string.Empty, string.Empty, new string[0]),
|
||||
};
|
||||
|
||||
hostAndPortOne = _leastConnection.Lease().Result;
|
||||
hostAndPortOne.Data.DownstreamHost.ShouldBe("127.0.0.1");
|
||||
hostAndPortTwo = _leastConnection.Lease().Result;
|
||||
hostAndPortTwo.Data.DownstreamHost.ShouldBe("127.0.0.1");
|
||||
_leastConnection.Release(hostAndPortOne.Data);
|
||||
_leastConnection.Release(hostAndPortTwo.Data);
|
||||
|
||||
availableServices = new List<Service>
|
||||
{
|
||||
new Service(serviceName, new HostAndPort("127.0.0.1", 80), string.Empty, string.Empty, new string[0]),
|
||||
new Service(serviceName, new HostAndPort("127.0.0.2", 80), string.Empty, string.Empty, new string[0]),
|
||||
};
|
||||
|
||||
hostAndPortOne = _leastConnection.Lease().Result;
|
||||
hostAndPortOne.Data.DownstreamHost.ShouldBe("127.0.0.1");
|
||||
hostAndPortTwo = _leastConnection.Lease().Result;
|
||||
hostAndPortTwo.Data.DownstreamHost.ShouldBe("127.0.0.2");
|
||||
_leastConnection.Release(hostAndPortOne.Data);
|
||||
_leastConnection.Release(hostAndPortTwo.Data);
|
||||
|
||||
}
|
||||
|
||||
private async Task LeaseDelayAndRelease()
|
||||
{
|
||||
var hostAndPort = await _leastConnection.Lease();
|
||||
await Task.Delay(_random.Next(1, 100));
|
||||
_leastConnection.Release(hostAndPort.Data);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_get_next_url()
|
||||
{
|
||||
var serviceName = "products";
|
||||
|
||||
var hostAndPort = new HostAndPort("localhost", 80);
|
||||
|
||||
var availableServices = new List<Service>
|
||||
{
|
||||
new Service(serviceName, hostAndPort, string.Empty, string.Empty, new string[0])
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenAHostAndPort(hostAndPort))
|
||||
.And(x => x.GivenTheLoadBalancerStarts(availableServices, serviceName))
|
||||
.When(x => x.WhenIGetTheNextHostAndPort())
|
||||
.Then(x => x.ThenTheNextHostAndPortIsReturned())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_serve_from_service_with_least_connections()
|
||||
{
|
||||
var serviceName = "products";
|
||||
|
||||
var availableServices = new List<Service>
|
||||
{
|
||||
new Service(serviceName, new HostAndPort("127.0.0.1", 80), string.Empty, string.Empty, new string[0]),
|
||||
new Service(serviceName, new HostAndPort("127.0.0.2", 80), string.Empty, string.Empty, new string[0]),
|
||||
new Service(serviceName, new HostAndPort("127.0.0.3", 80), string.Empty, string.Empty, new string[0])
|
||||
};
|
||||
|
||||
_services = availableServices;
|
||||
_leastConnection = new LeastConnection(() => Task.FromResult(_services), serviceName);
|
||||
|
||||
var response = _leastConnection.Lease().Result;
|
||||
|
||||
response.Data.DownstreamHost.ShouldBe(availableServices[0].HostAndPort.DownstreamHost);
|
||||
|
||||
response = _leastConnection.Lease().Result;
|
||||
|
||||
response.Data.DownstreamHost.ShouldBe(availableServices[1].HostAndPort.DownstreamHost);
|
||||
|
||||
response = _leastConnection.Lease().Result;
|
||||
|
||||
response.Data.DownstreamHost.ShouldBe(availableServices[2].HostAndPort.DownstreamHost);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_build_connections_per_service()
|
||||
{
|
||||
var serviceName = "products";
|
||||
|
||||
var availableServices = new List<Service>
|
||||
{
|
||||
new Service(serviceName, new HostAndPort("127.0.0.1", 80), string.Empty, string.Empty, new string[0]),
|
||||
new Service(serviceName, new HostAndPort("127.0.0.2", 80), string.Empty, string.Empty, new string[0]),
|
||||
};
|
||||
|
||||
_services = availableServices;
|
||||
_leastConnection = new LeastConnection(() => Task.FromResult(_services), serviceName);
|
||||
|
||||
var response = _leastConnection.Lease().Result;
|
||||
|
||||
response.Data.DownstreamHost.ShouldBe(availableServices[0].HostAndPort.DownstreamHost);
|
||||
|
||||
response = _leastConnection.Lease().Result;
|
||||
|
||||
response.Data.DownstreamHost.ShouldBe(availableServices[1].HostAndPort.DownstreamHost);
|
||||
|
||||
response = _leastConnection.Lease().Result;
|
||||
|
||||
response.Data.DownstreamHost.ShouldBe(availableServices[0].HostAndPort.DownstreamHost);
|
||||
|
||||
response = _leastConnection.Lease().Result;
|
||||
|
||||
response.Data.DownstreamHost.ShouldBe(availableServices[1].HostAndPort.DownstreamHost);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_release_connection()
|
||||
{
|
||||
var serviceName = "products";
|
||||
|
||||
var availableServices = new List<Service>
|
||||
{
|
||||
new Service(serviceName, new HostAndPort("127.0.0.1", 80), string.Empty, string.Empty, new string[0]),
|
||||
new Service(serviceName, new HostAndPort("127.0.0.2", 80), string.Empty, string.Empty, new string[0]),
|
||||
};
|
||||
|
||||
_services = availableServices;
|
||||
_leastConnection = new LeastConnection(() => Task.FromResult(_services), serviceName);
|
||||
|
||||
var response = _leastConnection.Lease().Result;
|
||||
|
||||
response.Data.DownstreamHost.ShouldBe(availableServices[0].HostAndPort.DownstreamHost);
|
||||
|
||||
response = _leastConnection.Lease().Result;
|
||||
|
||||
response.Data.DownstreamHost.ShouldBe(availableServices[1].HostAndPort.DownstreamHost);
|
||||
|
||||
response = _leastConnection.Lease().Result;
|
||||
|
||||
response.Data.DownstreamHost.ShouldBe(availableServices[0].HostAndPort.DownstreamHost);
|
||||
|
||||
response = _leastConnection.Lease().Result;
|
||||
|
||||
response.Data.DownstreamHost.ShouldBe(availableServices[1].HostAndPort.DownstreamHost);
|
||||
|
||||
//release this so 2 should have 1 connection and we should get 2 back as our next host and port
|
||||
_leastConnection.Release(availableServices[1].HostAndPort);
|
||||
|
||||
response = _leastConnection.Lease().Result;
|
||||
|
||||
response.Data.DownstreamHost.ShouldBe(availableServices[1].HostAndPort.DownstreamHost);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_error_if_services_are_null()
|
||||
{
|
||||
var serviceName = "products";
|
||||
|
||||
var hostAndPort = new HostAndPort("localhost", 80);
|
||||
this.Given(x => x.GivenAHostAndPort(hostAndPort))
|
||||
.And(x => x.GivenTheLoadBalancerStarts(null, serviceName))
|
||||
.When(x => x.WhenIGetTheNextHostAndPort())
|
||||
.Then(x => x.ThenServiceAreNullErrorIsReturned())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_error_if_services_are_empty()
|
||||
{
|
||||
var serviceName = "products";
|
||||
|
||||
var hostAndPort = new HostAndPort("localhost", 80);
|
||||
this.Given(x => x.GivenAHostAndPort(hostAndPort))
|
||||
.And(x => x.GivenTheLoadBalancerStarts(new List<Service>(), serviceName))
|
||||
.When(x => x.WhenIGetTheNextHostAndPort())
|
||||
.Then(x => x.ThenServiceAreEmptyErrorIsReturned())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void ThenServiceAreNullErrorIsReturned()
|
||||
{
|
||||
_result.IsError.ShouldBeTrue();
|
||||
_result.Errors[0].ShouldBeOfType<ServicesAreNullError>();
|
||||
}
|
||||
|
||||
private void ThenServiceAreEmptyErrorIsReturned()
|
||||
{
|
||||
_result.IsError.ShouldBeTrue();
|
||||
_result.Errors[0].ShouldBeOfType<ServicesAreEmptyError>();
|
||||
}
|
||||
|
||||
private void GivenTheLoadBalancerStarts(List<Service> services, string serviceName)
|
||||
{
|
||||
_services = services;
|
||||
_leastConnection = new LeastConnection(() => Task.FromResult(_services), serviceName);
|
||||
}
|
||||
|
||||
private void WhenTheLoadBalancerStarts(List<Service> services, string serviceName)
|
||||
{
|
||||
GivenTheLoadBalancerStarts(services, serviceName);
|
||||
}
|
||||
|
||||
private void GivenAHostAndPort(HostAndPort hostAndPort)
|
||||
{
|
||||
_hostAndPort = hostAndPort;
|
||||
}
|
||||
|
||||
private void WhenIGetTheNextHostAndPort()
|
||||
{
|
||||
_result = _leastConnection.Lease().Result;
|
||||
}
|
||||
|
||||
private void ThenTheNextHostAndPortIsReturned()
|
||||
{
|
||||
_result.Data.DownstreamHost.ShouldBe(_hostAndPort.DownstreamHost);
|
||||
_result.Data.DownstreamPort.ShouldBe(_hostAndPort.DownstreamPort);
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Ocelot.LoadBalancer.LoadBalancers;
|
||||
using Ocelot.Responses;
|
||||
using Ocelot.Values;
|
||||
using Shouldly;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.LoadBalancer
|
||||
{
|
||||
public class LeastConnectionTests
|
||||
{
|
||||
private ServiceHostAndPort _hostAndPort;
|
||||
private Response<ServiceHostAndPort> _result;
|
||||
private LeastConnection _leastConnection;
|
||||
private List<Service> _services;
|
||||
private Random _random;
|
||||
|
||||
public LeastConnectionTests()
|
||||
{
|
||||
_random = new Random();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_be_able_to_lease_and_release_concurrently()
|
||||
{
|
||||
var serviceName = "products";
|
||||
|
||||
var availableServices = new List<Service>
|
||||
{
|
||||
new Service(serviceName, new ServiceHostAndPort("127.0.0.1", 80), string.Empty, string.Empty, new string[0]),
|
||||
new Service(serviceName, new ServiceHostAndPort("127.0.0.2", 80), string.Empty, string.Empty, new string[0]),
|
||||
};
|
||||
|
||||
_services = availableServices;
|
||||
_leastConnection = new LeastConnection(() => Task.FromResult(_services), serviceName);
|
||||
|
||||
var tasks = new Task[100];
|
||||
|
||||
for(var i = 0; i < tasks.Length; i++)
|
||||
{
|
||||
tasks[i] = LeaseDelayAndRelease();
|
||||
}
|
||||
|
||||
Task.WaitAll(tasks);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_handle_service_returning_to_available()
|
||||
{
|
||||
var serviceName = "products";
|
||||
|
||||
var availableServices = new List<Service>
|
||||
{
|
||||
new Service(serviceName, new ServiceHostAndPort("127.0.0.1", 80), string.Empty, string.Empty, new string[0]),
|
||||
new Service(serviceName, new ServiceHostAndPort("127.0.0.2", 80), string.Empty, string.Empty, new string[0]),
|
||||
};
|
||||
|
||||
_leastConnection = new LeastConnection(() => Task.FromResult(availableServices), serviceName);
|
||||
|
||||
var hostAndPortOne = _leastConnection.Lease().Result;
|
||||
hostAndPortOne.Data.DownstreamHost.ShouldBe("127.0.0.1");
|
||||
var hostAndPortTwo = _leastConnection.Lease().Result;
|
||||
hostAndPortTwo.Data.DownstreamHost.ShouldBe("127.0.0.2");
|
||||
_leastConnection.Release(hostAndPortOne.Data);
|
||||
_leastConnection.Release(hostAndPortTwo.Data);
|
||||
|
||||
availableServices = new List<Service>
|
||||
{
|
||||
new Service(serviceName, new ServiceHostAndPort("127.0.0.1", 80), string.Empty, string.Empty, new string[0]),
|
||||
};
|
||||
|
||||
hostAndPortOne = _leastConnection.Lease().Result;
|
||||
hostAndPortOne.Data.DownstreamHost.ShouldBe("127.0.0.1");
|
||||
hostAndPortTwo = _leastConnection.Lease().Result;
|
||||
hostAndPortTwo.Data.DownstreamHost.ShouldBe("127.0.0.1");
|
||||
_leastConnection.Release(hostAndPortOne.Data);
|
||||
_leastConnection.Release(hostAndPortTwo.Data);
|
||||
|
||||
availableServices = new List<Service>
|
||||
{
|
||||
new Service(serviceName, new ServiceHostAndPort("127.0.0.1", 80), string.Empty, string.Empty, new string[0]),
|
||||
new Service(serviceName, new ServiceHostAndPort("127.0.0.2", 80), string.Empty, string.Empty, new string[0]),
|
||||
};
|
||||
|
||||
hostAndPortOne = _leastConnection.Lease().Result;
|
||||
hostAndPortOne.Data.DownstreamHost.ShouldBe("127.0.0.1");
|
||||
hostAndPortTwo = _leastConnection.Lease().Result;
|
||||
hostAndPortTwo.Data.DownstreamHost.ShouldBe("127.0.0.2");
|
||||
_leastConnection.Release(hostAndPortOne.Data);
|
||||
_leastConnection.Release(hostAndPortTwo.Data);
|
||||
|
||||
}
|
||||
|
||||
private async Task LeaseDelayAndRelease()
|
||||
{
|
||||
var hostAndPort = await _leastConnection.Lease();
|
||||
await Task.Delay(_random.Next(1, 100));
|
||||
_leastConnection.Release(hostAndPort.Data);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_get_next_url()
|
||||
{
|
||||
var serviceName = "products";
|
||||
|
||||
var hostAndPort = new ServiceHostAndPort("localhost", 80);
|
||||
|
||||
var availableServices = new List<Service>
|
||||
{
|
||||
new Service(serviceName, hostAndPort, string.Empty, string.Empty, new string[0])
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenAHostAndPort(hostAndPort))
|
||||
.And(x => x.GivenTheLoadBalancerStarts(availableServices, serviceName))
|
||||
.When(x => x.WhenIGetTheNextHostAndPort())
|
||||
.Then(x => x.ThenTheNextHostAndPortIsReturned())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_serve_from_service_with_least_connections()
|
||||
{
|
||||
var serviceName = "products";
|
||||
|
||||
var availableServices = new List<Service>
|
||||
{
|
||||
new Service(serviceName, new ServiceHostAndPort("127.0.0.1", 80), string.Empty, string.Empty, new string[0]),
|
||||
new Service(serviceName, new ServiceHostAndPort("127.0.0.2", 80), string.Empty, string.Empty, new string[0]),
|
||||
new Service(serviceName, new ServiceHostAndPort("127.0.0.3", 80), string.Empty, string.Empty, new string[0])
|
||||
};
|
||||
|
||||
_services = availableServices;
|
||||
_leastConnection = new LeastConnection(() => Task.FromResult(_services), serviceName);
|
||||
|
||||
var response = _leastConnection.Lease().Result;
|
||||
|
||||
response.Data.DownstreamHost.ShouldBe(availableServices[0].HostAndPort.DownstreamHost);
|
||||
|
||||
response = _leastConnection.Lease().Result;
|
||||
|
||||
response.Data.DownstreamHost.ShouldBe(availableServices[1].HostAndPort.DownstreamHost);
|
||||
|
||||
response = _leastConnection.Lease().Result;
|
||||
|
||||
response.Data.DownstreamHost.ShouldBe(availableServices[2].HostAndPort.DownstreamHost);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_build_connections_per_service()
|
||||
{
|
||||
var serviceName = "products";
|
||||
|
||||
var availableServices = new List<Service>
|
||||
{
|
||||
new Service(serviceName, new ServiceHostAndPort("127.0.0.1", 80), string.Empty, string.Empty, new string[0]),
|
||||
new Service(serviceName, new ServiceHostAndPort("127.0.0.2", 80), string.Empty, string.Empty, new string[0]),
|
||||
};
|
||||
|
||||
_services = availableServices;
|
||||
_leastConnection = new LeastConnection(() => Task.FromResult(_services), serviceName);
|
||||
|
||||
var response = _leastConnection.Lease().Result;
|
||||
|
||||
response.Data.DownstreamHost.ShouldBe(availableServices[0].HostAndPort.DownstreamHost);
|
||||
|
||||
response = _leastConnection.Lease().Result;
|
||||
|
||||
response.Data.DownstreamHost.ShouldBe(availableServices[1].HostAndPort.DownstreamHost);
|
||||
|
||||
response = _leastConnection.Lease().Result;
|
||||
|
||||
response.Data.DownstreamHost.ShouldBe(availableServices[0].HostAndPort.DownstreamHost);
|
||||
|
||||
response = _leastConnection.Lease().Result;
|
||||
|
||||
response.Data.DownstreamHost.ShouldBe(availableServices[1].HostAndPort.DownstreamHost);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_release_connection()
|
||||
{
|
||||
var serviceName = "products";
|
||||
|
||||
var availableServices = new List<Service>
|
||||
{
|
||||
new Service(serviceName, new ServiceHostAndPort("127.0.0.1", 80), string.Empty, string.Empty, new string[0]),
|
||||
new Service(serviceName, new ServiceHostAndPort("127.0.0.2", 80), string.Empty, string.Empty, new string[0]),
|
||||
};
|
||||
|
||||
_services = availableServices;
|
||||
_leastConnection = new LeastConnection(() => Task.FromResult(_services), serviceName);
|
||||
|
||||
var response = _leastConnection.Lease().Result;
|
||||
|
||||
response.Data.DownstreamHost.ShouldBe(availableServices[0].HostAndPort.DownstreamHost);
|
||||
|
||||
response = _leastConnection.Lease().Result;
|
||||
|
||||
response.Data.DownstreamHost.ShouldBe(availableServices[1].HostAndPort.DownstreamHost);
|
||||
|
||||
response = _leastConnection.Lease().Result;
|
||||
|
||||
response.Data.DownstreamHost.ShouldBe(availableServices[0].HostAndPort.DownstreamHost);
|
||||
|
||||
response = _leastConnection.Lease().Result;
|
||||
|
||||
response.Data.DownstreamHost.ShouldBe(availableServices[1].HostAndPort.DownstreamHost);
|
||||
|
||||
//release this so 2 should have 1 connection and we should get 2 back as our next host and port
|
||||
_leastConnection.Release(availableServices[1].HostAndPort);
|
||||
|
||||
response = _leastConnection.Lease().Result;
|
||||
|
||||
response.Data.DownstreamHost.ShouldBe(availableServices[1].HostAndPort.DownstreamHost);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_error_if_services_are_null()
|
||||
{
|
||||
var serviceName = "products";
|
||||
|
||||
var hostAndPort = new ServiceHostAndPort("localhost", 80);
|
||||
this.Given(x => x.GivenAHostAndPort(hostAndPort))
|
||||
.And(x => x.GivenTheLoadBalancerStarts(null, serviceName))
|
||||
.When(x => x.WhenIGetTheNextHostAndPort())
|
||||
.Then(x => x.ThenServiceAreNullErrorIsReturned())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_error_if_services_are_empty()
|
||||
{
|
||||
var serviceName = "products";
|
||||
|
||||
var hostAndPort = new ServiceHostAndPort("localhost", 80);
|
||||
this.Given(x => x.GivenAHostAndPort(hostAndPort))
|
||||
.And(x => x.GivenTheLoadBalancerStarts(new List<Service>(), serviceName))
|
||||
.When(x => x.WhenIGetTheNextHostAndPort())
|
||||
.Then(x => x.ThenServiceAreEmptyErrorIsReturned())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void ThenServiceAreNullErrorIsReturned()
|
||||
{
|
||||
_result.IsError.ShouldBeTrue();
|
||||
_result.Errors[0].ShouldBeOfType<ServicesAreNullError>();
|
||||
}
|
||||
|
||||
private void ThenServiceAreEmptyErrorIsReturned()
|
||||
{
|
||||
_result.IsError.ShouldBeTrue();
|
||||
_result.Errors[0].ShouldBeOfType<ServicesAreEmptyError>();
|
||||
}
|
||||
|
||||
private void GivenTheLoadBalancerStarts(List<Service> services, string serviceName)
|
||||
{
|
||||
_services = services;
|
||||
_leastConnection = new LeastConnection(() => Task.FromResult(_services), serviceName);
|
||||
}
|
||||
|
||||
private void WhenTheLoadBalancerStarts(List<Service> services, string serviceName)
|
||||
{
|
||||
GivenTheLoadBalancerStarts(services, serviceName);
|
||||
}
|
||||
|
||||
private void GivenAHostAndPort(ServiceHostAndPort hostAndPort)
|
||||
{
|
||||
_hostAndPort = hostAndPort;
|
||||
}
|
||||
|
||||
private void WhenIGetTheNextHostAndPort()
|
||||
{
|
||||
_result = _leastConnection.Lease().Result;
|
||||
}
|
||||
|
||||
private void ThenTheNextHostAndPortIsReturned()
|
||||
{
|
||||
_result.Data.DownstreamHost.ShouldBe(_hostAndPort.DownstreamHost);
|
||||
_result.Data.DownstreamPort.ShouldBe(_hostAndPort.DownstreamPort);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,125 +1,125 @@
|
||||
using Moq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.LoadBalancer.LoadBalancers;
|
||||
using Ocelot.ServiceDiscovery;
|
||||
using Shouldly;
|
||||
using System.Collections.Generic;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.LoadBalancer
|
||||
{
|
||||
public class LoadBalancerFactoryTests
|
||||
{
|
||||
private ReRoute _reRoute;
|
||||
private LoadBalancerFactory _factory;
|
||||
private ILoadBalancer _result;
|
||||
private Mock<IServiceDiscoveryProviderFactory> _serviceProviderFactory;
|
||||
private Mock<IServiceDiscoveryProvider> _serviceProvider;
|
||||
private ServiceProviderConfiguration _serviceProviderConfig;
|
||||
|
||||
public LoadBalancerFactoryTests()
|
||||
{
|
||||
_serviceProviderFactory = new Mock<IServiceDiscoveryProviderFactory>();
|
||||
_serviceProvider = new Mock<IServiceDiscoveryProvider>();
|
||||
_factory = new LoadBalancerFactory(_serviceProviderFactory.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_no_load_balancer()
|
||||
{
|
||||
var reRoute = new ReRouteBuilder()
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenAReRoute(reRoute))
|
||||
.And(x => GivenAServiceProviderConfig(new ServiceProviderConfigurationBuilder().Build()))
|
||||
.And(x => x.GivenTheServiceProviderFactoryReturns())
|
||||
.When(x => x.WhenIGetTheLoadBalancer())
|
||||
.Then(x => x.ThenTheLoadBalancerIsReturned<NoLoadBalancer>())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_round_robin_load_balancer()
|
||||
{
|
||||
var reRoute = new ReRouteBuilder()
|
||||
.WithLoadBalancer("RoundRobin")
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenAReRoute(reRoute))
|
||||
.And(x => GivenAServiceProviderConfig(new ServiceProviderConfigurationBuilder().Build()))
|
||||
.And(x => x.GivenTheServiceProviderFactoryReturns())
|
||||
.When(x => x.WhenIGetTheLoadBalancer())
|
||||
.Then(x => x.ThenTheLoadBalancerIsReturned<RoundRobin>())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_round_least_connection_balancer()
|
||||
{
|
||||
var reRoute = new ReRouteBuilder()
|
||||
.WithLoadBalancer("LeastConnection")
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenAReRoute(reRoute))
|
||||
.And(x => GivenAServiceProviderConfig(new ServiceProviderConfigurationBuilder().Build()))
|
||||
.And(x => x.GivenTheServiceProviderFactoryReturns())
|
||||
.When(x => x.WhenIGetTheLoadBalancer())
|
||||
.Then(x => x.ThenTheLoadBalancerIsReturned<LeastConnection>())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_call_service_provider()
|
||||
{
|
||||
var reRoute = new ReRouteBuilder()
|
||||
.WithLoadBalancer("RoundRobin")
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenAReRoute(reRoute))
|
||||
.And(x => GivenAServiceProviderConfig(new ServiceProviderConfigurationBuilder().Build()))
|
||||
.And(x => x.GivenTheServiceProviderFactoryReturns())
|
||||
.When(x => x.WhenIGetTheLoadBalancer())
|
||||
.Then(x => x.ThenTheServiceProviderIsCalledCorrectly())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenAServiceProviderConfig(ServiceProviderConfiguration serviceProviderConfig)
|
||||
{
|
||||
_serviceProviderConfig = serviceProviderConfig;
|
||||
}
|
||||
|
||||
private void GivenTheServiceProviderFactoryReturns()
|
||||
{
|
||||
_serviceProviderFactory
|
||||
.Setup(x => x.Get(It.IsAny<ServiceProviderConfiguration>(), It.IsAny<ReRoute>()))
|
||||
.Returns(_serviceProvider.Object);
|
||||
}
|
||||
|
||||
private void ThenTheServiceProviderIsCalledCorrectly()
|
||||
{
|
||||
_serviceProviderFactory
|
||||
.Verify(x => x.Get(It.IsAny<ServiceProviderConfiguration>(), It.IsAny<ReRoute>()), Times.Once);
|
||||
}
|
||||
|
||||
private void GivenAReRoute(ReRoute reRoute)
|
||||
{
|
||||
_reRoute = reRoute;
|
||||
}
|
||||
|
||||
private void WhenIGetTheLoadBalancer()
|
||||
{
|
||||
_result = _factory.Get(_reRoute, _serviceProviderConfig).Result;
|
||||
}
|
||||
|
||||
private void ThenTheLoadBalancerIsReturned<T>()
|
||||
{
|
||||
_result.ShouldBeOfType<T>();
|
||||
}
|
||||
}
|
||||
using Moq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.LoadBalancer.LoadBalancers;
|
||||
using Ocelot.ServiceDiscovery;
|
||||
using Shouldly;
|
||||
using System.Collections.Generic;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.LoadBalancer
|
||||
{
|
||||
public class LoadBalancerFactoryTests
|
||||
{
|
||||
private ReRoute _reRoute;
|
||||
private LoadBalancerFactory _factory;
|
||||
private ILoadBalancer _result;
|
||||
private Mock<IServiceDiscoveryProviderFactory> _serviceProviderFactory;
|
||||
private Mock<IServiceDiscoveryProvider> _serviceProvider;
|
||||
private ServiceProviderConfiguration _serviceProviderConfig;
|
||||
|
||||
public LoadBalancerFactoryTests()
|
||||
{
|
||||
_serviceProviderFactory = new Mock<IServiceDiscoveryProviderFactory>();
|
||||
_serviceProvider = new Mock<IServiceDiscoveryProvider>();
|
||||
_factory = new LoadBalancerFactory(_serviceProviderFactory.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_no_load_balancer()
|
||||
{
|
||||
var reRoute = new ReRouteBuilder()
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenAReRoute(reRoute))
|
||||
.And(x => GivenAServiceProviderConfig(new ServiceProviderConfigurationBuilder().Build()))
|
||||
.And(x => x.GivenTheServiceProviderFactoryReturns())
|
||||
.When(x => x.WhenIGetTheLoadBalancer())
|
||||
.Then(x => x.ThenTheLoadBalancerIsReturned<NoLoadBalancer>())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_round_robin_load_balancer()
|
||||
{
|
||||
var reRoute = new ReRouteBuilder()
|
||||
.WithLoadBalancer("RoundRobin")
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenAReRoute(reRoute))
|
||||
.And(x => GivenAServiceProviderConfig(new ServiceProviderConfigurationBuilder().Build()))
|
||||
.And(x => x.GivenTheServiceProviderFactoryReturns())
|
||||
.When(x => x.WhenIGetTheLoadBalancer())
|
||||
.Then(x => x.ThenTheLoadBalancerIsReturned<RoundRobin>())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_round_least_connection_balancer()
|
||||
{
|
||||
var reRoute = new ReRouteBuilder()
|
||||
.WithLoadBalancer("LeastConnection")
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenAReRoute(reRoute))
|
||||
.And(x => GivenAServiceProviderConfig(new ServiceProviderConfigurationBuilder().Build()))
|
||||
.And(x => x.GivenTheServiceProviderFactoryReturns())
|
||||
.When(x => x.WhenIGetTheLoadBalancer())
|
||||
.Then(x => x.ThenTheLoadBalancerIsReturned<LeastConnection>())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_call_service_provider()
|
||||
{
|
||||
var reRoute = new ReRouteBuilder()
|
||||
.WithLoadBalancer("RoundRobin")
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenAReRoute(reRoute))
|
||||
.And(x => GivenAServiceProviderConfig(new ServiceProviderConfigurationBuilder().Build()))
|
||||
.And(x => x.GivenTheServiceProviderFactoryReturns())
|
||||
.When(x => x.WhenIGetTheLoadBalancer())
|
||||
.Then(x => x.ThenTheServiceProviderIsCalledCorrectly())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenAServiceProviderConfig(ServiceProviderConfiguration serviceProviderConfig)
|
||||
{
|
||||
_serviceProviderConfig = serviceProviderConfig;
|
||||
}
|
||||
|
||||
private void GivenTheServiceProviderFactoryReturns()
|
||||
{
|
||||
_serviceProviderFactory
|
||||
.Setup(x => x.Get(It.IsAny<ServiceProviderConfiguration>(), It.IsAny<ReRoute>()))
|
||||
.Returns(_serviceProvider.Object);
|
||||
}
|
||||
|
||||
private void ThenTheServiceProviderIsCalledCorrectly()
|
||||
{
|
||||
_serviceProviderFactory
|
||||
.Verify(x => x.Get(It.IsAny<ServiceProviderConfiguration>(), It.IsAny<ReRoute>()), Times.Once);
|
||||
}
|
||||
|
||||
private void GivenAReRoute(ReRoute reRoute)
|
||||
{
|
||||
_reRoute = reRoute;
|
||||
}
|
||||
|
||||
private void WhenIGetTheLoadBalancer()
|
||||
{
|
||||
_result = _factory.Get(_reRoute, _serviceProviderConfig).Result;
|
||||
}
|
||||
|
||||
private void ThenTheLoadBalancerIsReturned<T>()
|
||||
{
|
||||
_result.ShouldBeOfType<T>();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,165 +1,165 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Moq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.LoadBalancer.LoadBalancers;
|
||||
using Ocelot.Responses;
|
||||
using Ocelot.Values;
|
||||
using Shouldly;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.LoadBalancer
|
||||
{
|
||||
public class LoadBalancerHouseTests
|
||||
{
|
||||
private ReRoute _reRoute;
|
||||
private ILoadBalancer _loadBalancer;
|
||||
private readonly LoadBalancerHouse _loadBalancerHouse;
|
||||
private Response _addResult;
|
||||
private Response<ILoadBalancer> _getResult;
|
||||
private string _key;
|
||||
private Mock<ILoadBalancerFactory> _factory;
|
||||
private ServiceProviderConfiguration _serviceProviderConfig;
|
||||
|
||||
public LoadBalancerHouseTests()
|
||||
{
|
||||
_factory = new Mock<ILoadBalancerFactory>();
|
||||
_loadBalancerHouse = new LoadBalancerHouse(_factory.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_store_load_balancer_on_first_request()
|
||||
{
|
||||
var reRoute = new ReRouteBuilder().WithReRouteKey("test").Build();
|
||||
|
||||
this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer()))
|
||||
.Then(x => x.ThenItIsAdded())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_not_store_load_balancer_on_second_request()
|
||||
{
|
||||
var reRoute = new ReRouteBuilder().WithLoadBalancer("FakeLoadBalancer").WithReRouteKey("test").Build();
|
||||
|
||||
this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer()))
|
||||
.When(x => x.WhenWeGetTheLoadBalancer(reRoute))
|
||||
.Then(x => x.ThenItIsReturned())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_store_load_balancers_by_key()
|
||||
{
|
||||
var reRoute = new ReRouteBuilder().WithReRouteKey("test").Build();
|
||||
var reRouteTwo = new ReRouteBuilder().WithReRouteKey("testtwo").Build();
|
||||
|
||||
this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer()))
|
||||
.And(x => x.GivenThereIsALoadBalancer(reRouteTwo, new FakeRoundRobinLoadBalancer()))
|
||||
.When(x => x.WhenWeGetTheLoadBalancer(reRoute))
|
||||
.Then(x => x.ThenTheLoadBalancerIs<FakeLoadBalancer>())
|
||||
.When(x => x.WhenWeGetTheLoadBalancer(reRouteTwo))
|
||||
.Then(x => x.ThenTheLoadBalancerIs<FakeRoundRobinLoadBalancer>())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_error_if_exception()
|
||||
{
|
||||
var reRoute = new ReRouteBuilder().Build();
|
||||
|
||||
this.When(x => x.WhenWeGetTheLoadBalancer(reRoute))
|
||||
.Then(x => x.ThenAnErrorIsReturned())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_get_new_load_balancer_if_reroute_load_balancer_has_changed()
|
||||
{
|
||||
var reRoute = new ReRouteBuilder().WithLoadBalancer("FakeLoadBalancer").WithReRouteKey("test").Build();
|
||||
|
||||
var reRouteTwo = new ReRouteBuilder().WithLoadBalancer("LeastConnection").WithReRouteKey("test").Build();
|
||||
|
||||
this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer()))
|
||||
.When(x => x.WhenWeGetTheLoadBalancer(reRoute))
|
||||
.Then(x => x.ThenTheLoadBalancerIs<FakeLoadBalancer>())
|
||||
.When(x => x.WhenIGetTheReRouteWithTheSameKeyButDifferentLoadBalancer(reRouteTwo))
|
||||
.Then(x => x.ThenTheLoadBalancerIs<LeastConnection>())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void WhenIGetTheReRouteWithTheSameKeyButDifferentLoadBalancer(ReRoute reRoute)
|
||||
{
|
||||
_reRoute = reRoute;
|
||||
_factory.Setup(x => x.Get(_reRoute, _serviceProviderConfig)).ReturnsAsync(new LeastConnection(null, null));
|
||||
_getResult = _loadBalancerHouse.Get(_reRoute, _serviceProviderConfig).Result;
|
||||
}
|
||||
|
||||
private void ThenAnErrorIsReturned()
|
||||
{
|
||||
_getResult.IsError.ShouldBeTrue();
|
||||
_getResult.Errors[0].ShouldBeOfType<UnableToFindLoadBalancerError>();
|
||||
}
|
||||
|
||||
private void ThenTheLoadBalancerIs<T>()
|
||||
{
|
||||
_getResult.Data.ShouldBeOfType<T>();
|
||||
}
|
||||
|
||||
private void ThenItIsAdded()
|
||||
{
|
||||
_getResult.IsError.ShouldBe(false);
|
||||
_getResult.ShouldBeOfType<OkResponse<ILoadBalancer>>();
|
||||
_getResult.Data.ShouldBe(_loadBalancer);
|
||||
_factory.Verify(x => x.Get(_reRoute, _serviceProviderConfig), Times.Once);
|
||||
}
|
||||
|
||||
|
||||
private void GivenThereIsALoadBalancer(ReRoute reRoute, ILoadBalancer loadBalancer)
|
||||
{
|
||||
_reRoute = reRoute;
|
||||
_loadBalancer = loadBalancer;
|
||||
_factory.Setup(x => x.Get(_reRoute, _serviceProviderConfig)).ReturnsAsync(loadBalancer);
|
||||
_getResult = _loadBalancerHouse.Get(reRoute, _serviceProviderConfig).Result;
|
||||
}
|
||||
|
||||
private void WhenWeGetTheLoadBalancer(ReRoute reRoute)
|
||||
{
|
||||
_getResult = _loadBalancerHouse.Get(reRoute, _serviceProviderConfig).Result;
|
||||
}
|
||||
|
||||
private void ThenItIsReturned()
|
||||
{
|
||||
_getResult.Data.ShouldBe(_loadBalancer);
|
||||
_factory.Verify(x => x.Get(_reRoute, _serviceProviderConfig), Times.Once);
|
||||
}
|
||||
|
||||
class FakeLoadBalancer : ILoadBalancer
|
||||
{
|
||||
public Task<Response<HostAndPort>> Lease()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Release(HostAndPort hostAndPort)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
class FakeRoundRobinLoadBalancer : ILoadBalancer
|
||||
{
|
||||
public Task<Response<HostAndPort>> Lease()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Release(HostAndPort hostAndPort)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Moq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.LoadBalancer.LoadBalancers;
|
||||
using Ocelot.Responses;
|
||||
using Ocelot.Values;
|
||||
using Shouldly;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.LoadBalancer
|
||||
{
|
||||
public class LoadBalancerHouseTests
|
||||
{
|
||||
private ReRoute _reRoute;
|
||||
private ILoadBalancer _loadBalancer;
|
||||
private readonly LoadBalancerHouse _loadBalancerHouse;
|
||||
private Response _addResult;
|
||||
private Response<ILoadBalancer> _getResult;
|
||||
private string _key;
|
||||
private Mock<ILoadBalancerFactory> _factory;
|
||||
private ServiceProviderConfiguration _serviceProviderConfig;
|
||||
|
||||
public LoadBalancerHouseTests()
|
||||
{
|
||||
_factory = new Mock<ILoadBalancerFactory>();
|
||||
_loadBalancerHouse = new LoadBalancerHouse(_factory.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_store_load_balancer_on_first_request()
|
||||
{
|
||||
var reRoute = new ReRouteBuilder().WithReRouteKey("test").Build();
|
||||
|
||||
this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer()))
|
||||
.Then(x => x.ThenItIsAdded())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_not_store_load_balancer_on_second_request()
|
||||
{
|
||||
var reRoute = new ReRouteBuilder().WithLoadBalancer("FakeLoadBalancer").WithReRouteKey("test").Build();
|
||||
|
||||
this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer()))
|
||||
.When(x => x.WhenWeGetTheLoadBalancer(reRoute))
|
||||
.Then(x => x.ThenItIsReturned())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_store_load_balancers_by_key()
|
||||
{
|
||||
var reRoute = new ReRouteBuilder().WithReRouteKey("test").Build();
|
||||
var reRouteTwo = new ReRouteBuilder().WithReRouteKey("testtwo").Build();
|
||||
|
||||
this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer()))
|
||||
.And(x => x.GivenThereIsALoadBalancer(reRouteTwo, new FakeRoundRobinLoadBalancer()))
|
||||
.When(x => x.WhenWeGetTheLoadBalancer(reRoute))
|
||||
.Then(x => x.ThenTheLoadBalancerIs<FakeLoadBalancer>())
|
||||
.When(x => x.WhenWeGetTheLoadBalancer(reRouteTwo))
|
||||
.Then(x => x.ThenTheLoadBalancerIs<FakeRoundRobinLoadBalancer>())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_error_if_exception()
|
||||
{
|
||||
var reRoute = new ReRouteBuilder().Build();
|
||||
|
||||
this.When(x => x.WhenWeGetTheLoadBalancer(reRoute))
|
||||
.Then(x => x.ThenAnErrorIsReturned())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_get_new_load_balancer_if_reroute_load_balancer_has_changed()
|
||||
{
|
||||
var reRoute = new ReRouteBuilder().WithLoadBalancer("FakeLoadBalancer").WithReRouteKey("test").Build();
|
||||
|
||||
var reRouteTwo = new ReRouteBuilder().WithLoadBalancer("LeastConnection").WithReRouteKey("test").Build();
|
||||
|
||||
this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer()))
|
||||
.When(x => x.WhenWeGetTheLoadBalancer(reRoute))
|
||||
.Then(x => x.ThenTheLoadBalancerIs<FakeLoadBalancer>())
|
||||
.When(x => x.WhenIGetTheReRouteWithTheSameKeyButDifferentLoadBalancer(reRouteTwo))
|
||||
.Then(x => x.ThenTheLoadBalancerIs<LeastConnection>())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void WhenIGetTheReRouteWithTheSameKeyButDifferentLoadBalancer(ReRoute reRoute)
|
||||
{
|
||||
_reRoute = reRoute;
|
||||
_factory.Setup(x => x.Get(_reRoute, _serviceProviderConfig)).ReturnsAsync(new LeastConnection(null, null));
|
||||
_getResult = _loadBalancerHouse.Get(_reRoute, _serviceProviderConfig).Result;
|
||||
}
|
||||
|
||||
private void ThenAnErrorIsReturned()
|
||||
{
|
||||
_getResult.IsError.ShouldBeTrue();
|
||||
_getResult.Errors[0].ShouldBeOfType<UnableToFindLoadBalancerError>();
|
||||
}
|
||||
|
||||
private void ThenTheLoadBalancerIs<T>()
|
||||
{
|
||||
_getResult.Data.ShouldBeOfType<T>();
|
||||
}
|
||||
|
||||
private void ThenItIsAdded()
|
||||
{
|
||||
_getResult.IsError.ShouldBe(false);
|
||||
_getResult.ShouldBeOfType<OkResponse<ILoadBalancer>>();
|
||||
_getResult.Data.ShouldBe(_loadBalancer);
|
||||
_factory.Verify(x => x.Get(_reRoute, _serviceProviderConfig), Times.Once);
|
||||
}
|
||||
|
||||
|
||||
private void GivenThereIsALoadBalancer(ReRoute reRoute, ILoadBalancer loadBalancer)
|
||||
{
|
||||
_reRoute = reRoute;
|
||||
_loadBalancer = loadBalancer;
|
||||
_factory.Setup(x => x.Get(_reRoute, _serviceProviderConfig)).ReturnsAsync(loadBalancer);
|
||||
_getResult = _loadBalancerHouse.Get(reRoute, _serviceProviderConfig).Result;
|
||||
}
|
||||
|
||||
private void WhenWeGetTheLoadBalancer(ReRoute reRoute)
|
||||
{
|
||||
_getResult = _loadBalancerHouse.Get(reRoute, _serviceProviderConfig).Result;
|
||||
}
|
||||
|
||||
private void ThenItIsReturned()
|
||||
{
|
||||
_getResult.Data.ShouldBe(_loadBalancer);
|
||||
_factory.Verify(x => x.Get(_reRoute, _serviceProviderConfig), Times.Once);
|
||||
}
|
||||
|
||||
class FakeLoadBalancer : ILoadBalancer
|
||||
{
|
||||
public Task<Response<ServiceHostAndPort>> Lease()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Release(ServiceHostAndPort hostAndPort)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
class FakeRoundRobinLoadBalancer : ILoadBalancer
|
||||
{
|
||||
public Task<Response<ServiceHostAndPort>> Lease()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Release(ServiceHostAndPort hostAndPort)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,209 +1,209 @@
|
||||
namespace Ocelot.UnitTests.LoadBalancer
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Moq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.Configuration.Provider;
|
||||
using Ocelot.DownstreamRouteFinder;
|
||||
using Ocelot.Errors;
|
||||
using Ocelot.LoadBalancer.LoadBalancers;
|
||||
using Ocelot.LoadBalancer.Middleware;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Responses;
|
||||
using Ocelot.Values;
|
||||
using Shouldly;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class LoadBalancerMiddlewareTests : ServerHostedMiddlewareTest
|
||||
{
|
||||
private readonly Mock<ILoadBalancerHouse> _loadBalancerHouse;
|
||||
private readonly Mock<ILoadBalancer> _loadBalancer;
|
||||
private HostAndPort _hostAndPort;
|
||||
private OkResponse<DownstreamRoute> _downstreamRoute;
|
||||
private ErrorResponse<ILoadBalancer> _getLoadBalancerHouseError;
|
||||
private ErrorResponse<HostAndPort> _getHostAndPortError;
|
||||
private HttpRequestMessage _downstreamRequest;
|
||||
private ServiceProviderConfiguration _config;
|
||||
|
||||
public LoadBalancerMiddlewareTests()
|
||||
{
|
||||
_loadBalancerHouse = new Mock<ILoadBalancerHouse>();
|
||||
_loadBalancer = new Mock<ILoadBalancer>();
|
||||
_loadBalancerHouse = new Mock<ILoadBalancerHouse>();
|
||||
_downstreamRequest = new HttpRequestMessage(HttpMethod.Get, "");
|
||||
|
||||
ScopedRepository
|
||||
.Setup(sr => sr.Get<HttpRequestMessage>("DownstreamRequest"))
|
||||
.Returns(new OkResponse<HttpRequestMessage>(_downstreamRequest));
|
||||
|
||||
GivenTheTestServerIsConfigured();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_call_scoped_data_repository_correctly()
|
||||
{
|
||||
var downstreamRoute = new DownstreamRoute(new List<Ocelot.DownstreamRouteFinder.UrlMatcher.PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder()
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build());
|
||||
|
||||
var serviceProviderConfig = new ServiceProviderConfigurationBuilder()
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamUrlIs("http://my.url/abc?q=123"))
|
||||
.And(x => GivenTheConfigurationIs(serviceProviderConfig))
|
||||
.And(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||
.And(x => x.GivenTheLoadBalancerHouseReturns())
|
||||
.And(x => x.GivenTheLoadBalancerReturns())
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheDownstreamUrlIsReplacedWith("http://127.0.0.1:80/abc?q=123"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_set_pipeline_error_if_cannot_get_load_balancer()
|
||||
{
|
||||
var downstreamRoute = new DownstreamRoute(new List<Ocelot.DownstreamRouteFinder.UrlMatcher.PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder()
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build());
|
||||
|
||||
var serviceProviderConfig = new ServiceProviderConfigurationBuilder()
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamUrlIs("http://my.url/abc?q=123"))
|
||||
.And(x => GivenTheConfigurationIs(serviceProviderConfig))
|
||||
.And(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||
.And(x => x.GivenTheLoadBalancerHouseReturnsAnError())
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenAnErrorStatingLoadBalancerCouldNotBeFoundIsSetOnPipeline())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_set_pipeline_error_if_cannot_get_least()
|
||||
{
|
||||
var downstreamRoute = new DownstreamRoute(new List<Ocelot.DownstreamRouteFinder.UrlMatcher.PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder()
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build());
|
||||
|
||||
var serviceProviderConfig = new ServiceProviderConfigurationBuilder()
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamUrlIs("http://my.url/abc?q=123"))
|
||||
.And(x => GivenTheConfigurationIs(serviceProviderConfig))
|
||||
.And(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||
.And(x => x.GivenTheLoadBalancerHouseReturns())
|
||||
.And(x => x.GivenTheLoadBalancerReturnsAnError())
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenAnErrorStatingHostAndPortCouldNotBeFoundIsSetOnPipeline())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenTheConfigurationIs(ServiceProviderConfiguration config)
|
||||
{
|
||||
_config = config;
|
||||
ScopedRepository
|
||||
.Setup(x => x.Get<ServiceProviderConfiguration>("ServiceProviderConfiguration")).Returns(new OkResponse<ServiceProviderConfiguration>(config));
|
||||
}
|
||||
|
||||
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
|
||||
{
|
||||
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
|
||||
services.AddLogging();
|
||||
services.AddSingleton(_loadBalancerHouse.Object);
|
||||
services.AddSingleton(ScopedRepository.Object);
|
||||
}
|
||||
|
||||
protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app)
|
||||
{
|
||||
app.UseLoadBalancingMiddleware();
|
||||
}
|
||||
|
||||
private void GivenTheDownStreamUrlIs(string downstreamUrl)
|
||||
{
|
||||
_downstreamRequest.RequestUri = new System.Uri(downstreamUrl);
|
||||
}
|
||||
|
||||
private void GivenTheLoadBalancerReturnsAnError()
|
||||
{
|
||||
_getHostAndPortError = new ErrorResponse<HostAndPort>(new List<Error>() { new ServicesAreNullError($"services were null for bah") });
|
||||
_loadBalancer
|
||||
.Setup(x => x.Lease())
|
||||
.ReturnsAsync(_getHostAndPortError);
|
||||
}
|
||||
|
||||
private void GivenTheLoadBalancerReturns()
|
||||
{
|
||||
_hostAndPort = new HostAndPort("127.0.0.1", 80);
|
||||
_loadBalancer
|
||||
.Setup(x => x.Lease())
|
||||
.ReturnsAsync(new OkResponse<HostAndPort>(_hostAndPort));
|
||||
}
|
||||
|
||||
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
|
||||
{
|
||||
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
|
||||
ScopedRepository
|
||||
.Setup(x => x.Get<DownstreamRoute>(It.IsAny<string>()))
|
||||
.Returns(_downstreamRoute);
|
||||
}
|
||||
|
||||
private void GivenTheLoadBalancerHouseReturns()
|
||||
{
|
||||
_loadBalancerHouse
|
||||
.Setup(x => x.Get(It.IsAny<ReRoute>(), It.IsAny<ServiceProviderConfiguration>()))
|
||||
.ReturnsAsync(new OkResponse<ILoadBalancer>(_loadBalancer.Object));
|
||||
}
|
||||
|
||||
private void GivenTheLoadBalancerHouseReturnsAnError()
|
||||
{
|
||||
_getLoadBalancerHouseError = new ErrorResponse<ILoadBalancer>(new List<Ocelot.Errors.Error>()
|
||||
{
|
||||
new UnableToFindLoadBalancerError($"unabe to find load balancer for bah")
|
||||
});
|
||||
|
||||
_loadBalancerHouse
|
||||
.Setup(x => x.Get(It.IsAny<ReRoute>(), It.IsAny<ServiceProviderConfiguration>()))
|
||||
.ReturnsAsync(_getLoadBalancerHouseError);
|
||||
}
|
||||
|
||||
private void ThenAnErrorStatingLoadBalancerCouldNotBeFoundIsSetOnPipeline()
|
||||
{
|
||||
ScopedRepository
|
||||
.Verify(x => x.Add("OcelotMiddlewareError", true), Times.Once);
|
||||
|
||||
ScopedRepository
|
||||
.Verify(x => x.Add("OcelotMiddlewareErrors", _getLoadBalancerHouseError.Errors), Times.Once);
|
||||
}
|
||||
|
||||
private void ThenAnErrorSayingReleaseFailedIsSetOnThePipeline()
|
||||
{
|
||||
ScopedRepository
|
||||
.Verify(x => x.Add("OcelotMiddlewareError", true), Times.Once);
|
||||
|
||||
ScopedRepository
|
||||
.Verify(x => x.Add("OcelotMiddlewareErrors", It.IsAny<List<Error>>()), Times.Once);
|
||||
}
|
||||
|
||||
private void ThenAnErrorStatingHostAndPortCouldNotBeFoundIsSetOnPipeline()
|
||||
{
|
||||
ScopedRepository
|
||||
.Verify(x => x.Add("OcelotMiddlewareError", true), Times.Once);
|
||||
|
||||
ScopedRepository
|
||||
.Verify(x => x.Add("OcelotMiddlewareErrors", _getHostAndPortError.Errors), Times.Once);
|
||||
}
|
||||
|
||||
private void ThenTheDownstreamUrlIsReplacedWith(string expectedUri)
|
||||
{
|
||||
_downstreamRequest.RequestUri.OriginalString.ShouldBe(expectedUri);
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace Ocelot.UnitTests.LoadBalancer
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Moq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.Configuration.Provider;
|
||||
using Ocelot.DownstreamRouteFinder;
|
||||
using Ocelot.Errors;
|
||||
using Ocelot.LoadBalancer.LoadBalancers;
|
||||
using Ocelot.LoadBalancer.Middleware;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Responses;
|
||||
using Ocelot.Values;
|
||||
using Shouldly;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class LoadBalancerMiddlewareTests : ServerHostedMiddlewareTest
|
||||
{
|
||||
private readonly Mock<ILoadBalancerHouse> _loadBalancerHouse;
|
||||
private readonly Mock<ILoadBalancer> _loadBalancer;
|
||||
private ServiceHostAndPort _hostAndPort;
|
||||
private OkResponse<DownstreamRoute> _downstreamRoute;
|
||||
private ErrorResponse<ILoadBalancer> _getLoadBalancerHouseError;
|
||||
private ErrorResponse<ServiceHostAndPort> _getHostAndPortError;
|
||||
private HttpRequestMessage _downstreamRequest;
|
||||
private ServiceProviderConfiguration _config;
|
||||
|
||||
public LoadBalancerMiddlewareTests()
|
||||
{
|
||||
_loadBalancerHouse = new Mock<ILoadBalancerHouse>();
|
||||
_loadBalancer = new Mock<ILoadBalancer>();
|
||||
_loadBalancerHouse = new Mock<ILoadBalancerHouse>();
|
||||
_downstreamRequest = new HttpRequestMessage(HttpMethod.Get, "");
|
||||
|
||||
ScopedRepository
|
||||
.Setup(sr => sr.Get<HttpRequestMessage>("DownstreamRequest"))
|
||||
.Returns(new OkResponse<HttpRequestMessage>(_downstreamRequest));
|
||||
|
||||
GivenTheTestServerIsConfigured();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_call_scoped_data_repository_correctly()
|
||||
{
|
||||
var downstreamRoute = new DownstreamRoute(new List<Ocelot.DownstreamRouteFinder.UrlMatcher.PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder()
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build());
|
||||
|
||||
var serviceProviderConfig = new ServiceProviderConfigurationBuilder()
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamUrlIs("http://my.url/abc?q=123"))
|
||||
.And(x => GivenTheConfigurationIs(serviceProviderConfig))
|
||||
.And(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||
.And(x => x.GivenTheLoadBalancerHouseReturns())
|
||||
.And(x => x.GivenTheLoadBalancerReturns())
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheDownstreamUrlIsReplacedWith("http://127.0.0.1:80/abc?q=123"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_set_pipeline_error_if_cannot_get_load_balancer()
|
||||
{
|
||||
var downstreamRoute = new DownstreamRoute(new List<Ocelot.DownstreamRouteFinder.UrlMatcher.PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder()
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build());
|
||||
|
||||
var serviceProviderConfig = new ServiceProviderConfigurationBuilder()
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamUrlIs("http://my.url/abc?q=123"))
|
||||
.And(x => GivenTheConfigurationIs(serviceProviderConfig))
|
||||
.And(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||
.And(x => x.GivenTheLoadBalancerHouseReturnsAnError())
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenAnErrorStatingLoadBalancerCouldNotBeFoundIsSetOnPipeline())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_set_pipeline_error_if_cannot_get_least()
|
||||
{
|
||||
var downstreamRoute = new DownstreamRoute(new List<Ocelot.DownstreamRouteFinder.UrlMatcher.PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder()
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build());
|
||||
|
||||
var serviceProviderConfig = new ServiceProviderConfigurationBuilder()
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamUrlIs("http://my.url/abc?q=123"))
|
||||
.And(x => GivenTheConfigurationIs(serviceProviderConfig))
|
||||
.And(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||
.And(x => x.GivenTheLoadBalancerHouseReturns())
|
||||
.And(x => x.GivenTheLoadBalancerReturnsAnError())
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenAnErrorStatingHostAndPortCouldNotBeFoundIsSetOnPipeline())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenTheConfigurationIs(ServiceProviderConfiguration config)
|
||||
{
|
||||
_config = config;
|
||||
ScopedRepository
|
||||
.Setup(x => x.Get<ServiceProviderConfiguration>("ServiceProviderConfiguration")).Returns(new OkResponse<ServiceProviderConfiguration>(config));
|
||||
}
|
||||
|
||||
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
|
||||
{
|
||||
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
|
||||
services.AddLogging();
|
||||
services.AddSingleton(_loadBalancerHouse.Object);
|
||||
services.AddSingleton(ScopedRepository.Object);
|
||||
}
|
||||
|
||||
protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app)
|
||||
{
|
||||
app.UseLoadBalancingMiddleware();
|
||||
}
|
||||
|
||||
private void GivenTheDownStreamUrlIs(string downstreamUrl)
|
||||
{
|
||||
_downstreamRequest.RequestUri = new System.Uri(downstreamUrl);
|
||||
}
|
||||
|
||||
private void GivenTheLoadBalancerReturnsAnError()
|
||||
{
|
||||
_getHostAndPortError = new ErrorResponse<ServiceHostAndPort>(new List<Error>() { new ServicesAreNullError($"services were null for bah") });
|
||||
_loadBalancer
|
||||
.Setup(x => x.Lease())
|
||||
.ReturnsAsync(_getHostAndPortError);
|
||||
}
|
||||
|
||||
private void GivenTheLoadBalancerReturns()
|
||||
{
|
||||
_hostAndPort = new ServiceHostAndPort("127.0.0.1", 80);
|
||||
_loadBalancer
|
||||
.Setup(x => x.Lease())
|
||||
.ReturnsAsync(new OkResponse<ServiceHostAndPort>(_hostAndPort));
|
||||
}
|
||||
|
||||
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
|
||||
{
|
||||
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
|
||||
ScopedRepository
|
||||
.Setup(x => x.Get<DownstreamRoute>(It.IsAny<string>()))
|
||||
.Returns(_downstreamRoute);
|
||||
}
|
||||
|
||||
private void GivenTheLoadBalancerHouseReturns()
|
||||
{
|
||||
_loadBalancerHouse
|
||||
.Setup(x => x.Get(It.IsAny<ReRoute>(), It.IsAny<ServiceProviderConfiguration>()))
|
||||
.ReturnsAsync(new OkResponse<ILoadBalancer>(_loadBalancer.Object));
|
||||
}
|
||||
|
||||
private void GivenTheLoadBalancerHouseReturnsAnError()
|
||||
{
|
||||
_getLoadBalancerHouseError = new ErrorResponse<ILoadBalancer>(new List<Ocelot.Errors.Error>()
|
||||
{
|
||||
new UnableToFindLoadBalancerError($"unabe to find load balancer for bah")
|
||||
});
|
||||
|
||||
_loadBalancerHouse
|
||||
.Setup(x => x.Get(It.IsAny<ReRoute>(), It.IsAny<ServiceProviderConfiguration>()))
|
||||
.ReturnsAsync(_getLoadBalancerHouseError);
|
||||
}
|
||||
|
||||
private void ThenAnErrorStatingLoadBalancerCouldNotBeFoundIsSetOnPipeline()
|
||||
{
|
||||
ScopedRepository
|
||||
.Verify(x => x.Add("OcelotMiddlewareError", true), Times.Once);
|
||||
|
||||
ScopedRepository
|
||||
.Verify(x => x.Add("OcelotMiddlewareErrors", _getLoadBalancerHouseError.Errors), Times.Once);
|
||||
}
|
||||
|
||||
private void ThenAnErrorSayingReleaseFailedIsSetOnThePipeline()
|
||||
{
|
||||
ScopedRepository
|
||||
.Verify(x => x.Add("OcelotMiddlewareError", true), Times.Once);
|
||||
|
||||
ScopedRepository
|
||||
.Verify(x => x.Add("OcelotMiddlewareErrors", It.IsAny<List<Error>>()), Times.Once);
|
||||
}
|
||||
|
||||
private void ThenAnErrorStatingHostAndPortCouldNotBeFoundIsSetOnPipeline()
|
||||
{
|
||||
ScopedRepository
|
||||
.Verify(x => x.Add("OcelotMiddlewareError", true), Times.Once);
|
||||
|
||||
ScopedRepository
|
||||
.Verify(x => x.Add("OcelotMiddlewareErrors", _getHostAndPortError.Errors), Times.Once);
|
||||
}
|
||||
|
||||
private void ThenTheDownstreamUrlIsReplacedWith(string expectedUri)
|
||||
{
|
||||
_downstreamRequest.RequestUri.OriginalString.ShouldBe(expectedUri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,48 +1,48 @@
|
||||
using System.Collections.Generic;
|
||||
using Ocelot.LoadBalancer.LoadBalancers;
|
||||
using Ocelot.Responses;
|
||||
using Ocelot.Values;
|
||||
using Shouldly;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.LoadBalancer
|
||||
{
|
||||
public class NoLoadBalancerTests
|
||||
{
|
||||
private List<Service> _services;
|
||||
private NoLoadBalancer _loadBalancer;
|
||||
private Response<HostAndPort> _result;
|
||||
|
||||
[Fact]
|
||||
public void should_return_host_and_port()
|
||||
{
|
||||
var hostAndPort = new HostAndPort("127.0.0.1", 80);
|
||||
|
||||
var services = new List<Service>
|
||||
{
|
||||
new Service("product", hostAndPort, string.Empty, string.Empty, new string[0])
|
||||
};
|
||||
this.Given(x => x.GivenServices(services))
|
||||
.When(x => x.WhenIGetTheNextHostAndPort())
|
||||
.Then(x => x.ThenTheHostAndPortIs(hostAndPort))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenServices(List<Service> services)
|
||||
{
|
||||
_services = services;
|
||||
}
|
||||
|
||||
private void WhenIGetTheNextHostAndPort()
|
||||
{
|
||||
_loadBalancer = new NoLoadBalancer(_services);
|
||||
_result = _loadBalancer.Lease().Result;
|
||||
}
|
||||
|
||||
private void ThenTheHostAndPortIs(HostAndPort expected)
|
||||
{
|
||||
_result.Data.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
using System.Collections.Generic;
|
||||
using Ocelot.LoadBalancer.LoadBalancers;
|
||||
using Ocelot.Responses;
|
||||
using Ocelot.Values;
|
||||
using Shouldly;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.LoadBalancer
|
||||
{
|
||||
public class NoLoadBalancerTests
|
||||
{
|
||||
private List<Service> _services;
|
||||
private NoLoadBalancer _loadBalancer;
|
||||
private Response<ServiceHostAndPort> _result;
|
||||
|
||||
[Fact]
|
||||
public void should_return_host_and_port()
|
||||
{
|
||||
var hostAndPort = new ServiceHostAndPort("127.0.0.1", 80);
|
||||
|
||||
var services = new List<Service>
|
||||
{
|
||||
new Service("product", hostAndPort, string.Empty, string.Empty, new string[0])
|
||||
};
|
||||
this.Given(x => x.GivenServices(services))
|
||||
.When(x => x.WhenIGetTheNextHostAndPort())
|
||||
.Then(x => x.ThenTheHostAndPortIs(hostAndPort))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenServices(List<Service> services)
|
||||
{
|
||||
_services = services;
|
||||
}
|
||||
|
||||
private void WhenIGetTheNextHostAndPort()
|
||||
{
|
||||
_loadBalancer = new NoLoadBalancer(_services);
|
||||
_result = _loadBalancer.Lease().Result;
|
||||
}
|
||||
|
||||
private void ThenTheHostAndPortIs(ServiceHostAndPort expected)
|
||||
{
|
||||
_result.Data.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,69 +1,69 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Ocelot.LoadBalancer.LoadBalancers;
|
||||
using Ocelot.Responses;
|
||||
using Ocelot.Values;
|
||||
using Shouldly;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ocelot.UnitTests.LoadBalancer
|
||||
{
|
||||
public class RoundRobinTests
|
||||
{
|
||||
private readonly RoundRobin _roundRobin;
|
||||
private readonly List<Service> _services;
|
||||
private Response<HostAndPort> _hostAndPort;
|
||||
|
||||
public RoundRobinTests()
|
||||
{
|
||||
_services = new List<Service>
|
||||
{
|
||||
new Service("product", new HostAndPort("127.0.0.1", 5000), string.Empty, string.Empty, new string[0]),
|
||||
new Service("product", new HostAndPort("127.0.0.1", 5001), string.Empty, string.Empty, new string[0]),
|
||||
new Service("product", new HostAndPort("127.0.0.1", 5001), string.Empty, string.Empty, new string[0])
|
||||
};
|
||||
|
||||
_roundRobin = new RoundRobin(() => Task.FromResult(_services));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_get_next_address()
|
||||
{
|
||||
this.Given(x => x.GivenIGetTheNextAddress())
|
||||
.Then(x => x.ThenTheNextAddressIndexIs(0))
|
||||
.Given(x => x.GivenIGetTheNextAddress())
|
||||
.Then(x => x.ThenTheNextAddressIndexIs(1))
|
||||
.Given(x => x.GivenIGetTheNextAddress())
|
||||
.Then(x => x.ThenTheNextAddressIndexIs(2))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_go_back_to_first_address_after_finished_last()
|
||||
{
|
||||
var stopWatch = Stopwatch.StartNew();
|
||||
|
||||
while (stopWatch.ElapsedMilliseconds < 1000)
|
||||
{
|
||||
var address = _roundRobin.Lease().Result;
|
||||
address.Data.ShouldBe(_services[0].HostAndPort);
|
||||
address = _roundRobin.Lease().Result;
|
||||
address.Data.ShouldBe(_services[1].HostAndPort);
|
||||
address = _roundRobin.Lease().Result;
|
||||
address.Data.ShouldBe(_services[2].HostAndPort);
|
||||
}
|
||||
}
|
||||
|
||||
private void GivenIGetTheNextAddress()
|
||||
{
|
||||
_hostAndPort = _roundRobin.Lease().Result;
|
||||
}
|
||||
|
||||
private void ThenTheNextAddressIndexIs(int index)
|
||||
{
|
||||
_hostAndPort.Data.ShouldBe(_services[index].HostAndPort);
|
||||
}
|
||||
}
|
||||
}
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Ocelot.LoadBalancer.LoadBalancers;
|
||||
using Ocelot.Responses;
|
||||
using Ocelot.Values;
|
||||
using Shouldly;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ocelot.UnitTests.LoadBalancer
|
||||
{
|
||||
public class RoundRobinTests
|
||||
{
|
||||
private readonly RoundRobin _roundRobin;
|
||||
private readonly List<Service> _services;
|
||||
private Response<ServiceHostAndPort> _hostAndPort;
|
||||
|
||||
public RoundRobinTests()
|
||||
{
|
||||
_services = new List<Service>
|
||||
{
|
||||
new Service("product", new ServiceHostAndPort("127.0.0.1", 5000), string.Empty, string.Empty, new string[0]),
|
||||
new Service("product", new ServiceHostAndPort("127.0.0.1", 5001), string.Empty, string.Empty, new string[0]),
|
||||
new Service("product", new ServiceHostAndPort("127.0.0.1", 5001), string.Empty, string.Empty, new string[0])
|
||||
};
|
||||
|
||||
_roundRobin = new RoundRobin(() => Task.FromResult(_services));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_get_next_address()
|
||||
{
|
||||
this.Given(x => x.GivenIGetTheNextAddress())
|
||||
.Then(x => x.ThenTheNextAddressIndexIs(0))
|
||||
.Given(x => x.GivenIGetTheNextAddress())
|
||||
.Then(x => x.ThenTheNextAddressIndexIs(1))
|
||||
.Given(x => x.GivenIGetTheNextAddress())
|
||||
.Then(x => x.ThenTheNextAddressIndexIs(2))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_go_back_to_first_address_after_finished_last()
|
||||
{
|
||||
var stopWatch = Stopwatch.StartNew();
|
||||
|
||||
while (stopWatch.ElapsedMilliseconds < 1000)
|
||||
{
|
||||
var address = _roundRobin.Lease().Result;
|
||||
address.Data.ShouldBe(_services[0].HostAndPort);
|
||||
address = _roundRobin.Lease().Result;
|
||||
address.Data.ShouldBe(_services[1].HostAndPort);
|
||||
address = _roundRobin.Lease().Result;
|
||||
address.Data.ShouldBe(_services[2].HostAndPort);
|
||||
}
|
||||
}
|
||||
|
||||
private void GivenIGetTheNextAddress()
|
||||
{
|
||||
_hostAndPort = _roundRobin.Lease().Result;
|
||||
}
|
||||
|
||||
private void ThenTheNextAddressIndexIs(int index)
|
||||
{
|
||||
_hostAndPort.Data.ShouldBe(_services[index].HostAndPort);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user