mirror of
				https://github.com/nsnail/Ocelot.git
				synced 2025-11-04 20:30:50 +08:00 
			
		
		
		
	Feature/merge configuration files (#316)
* #296 renamed configuration.json to ocelot.json in preparation * removed things we dont need for tests * another file we dont need * removed some async we dont need * refactoring to consolidate configuration code * removed another pointless abstraction * #296 started writing merge code * #296 coming up with ideas for this config merging * #296 still hacking this idea around * #296 will now do a crappy merge on the configuration * #296 change so tests pass on windows
This commit is contained in:
		@@ -1,22 +1,18 @@
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using Castle.Components.DictionaryAdapter;
 | 
			
		||||
using Microsoft.Extensions.Options;
 | 
			
		||||
using Moq;
 | 
			
		||||
using Ocelot.Cache;
 | 
			
		||||
using Ocelot.Configuration;
 | 
			
		||||
using Ocelot.Configuration.Builder;
 | 
			
		||||
using Ocelot.Configuration.Creator;
 | 
			
		||||
using Ocelot.Configuration.File;
 | 
			
		||||
using Ocelot.Configuration.Validator;
 | 
			
		||||
using Ocelot.Logging;
 | 
			
		||||
using Ocelot.Responses;
 | 
			
		||||
using Shouldly;
 | 
			
		||||
using TestStack.BDDfy;
 | 
			
		||||
using Xunit;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
{
 | 
			
		||||
    using System;
 | 
			
		||||
    using System.Collections.Generic;
 | 
			
		||||
    using Moq;
 | 
			
		||||
    using Ocelot.Cache;
 | 
			
		||||
    using Ocelot.Configuration;
 | 
			
		||||
    using Ocelot.Configuration.Builder;
 | 
			
		||||
    using Ocelot.Configuration.Creator;
 | 
			
		||||
    using Ocelot.Configuration.File;
 | 
			
		||||
    using Ocelot.Configuration.Validator;
 | 
			
		||||
    using Ocelot.Logging;
 | 
			
		||||
    using Ocelot.Responses;
 | 
			
		||||
    using Shouldly;
 | 
			
		||||
    using TestStack.BDDfy;
 | 
			
		||||
    using Xunit;
 | 
			
		||||
    using Ocelot.DependencyInjection;
 | 
			
		||||
    using Ocelot.Errors;
 | 
			
		||||
    using Ocelot.UnitTests.TestData;
 | 
			
		||||
@@ -24,23 +20,22 @@ namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
 | 
			
		||||
    public class FileConfigurationCreatorTests
 | 
			
		||||
    {
 | 
			
		||||
        private readonly Mock<IOptions<FileConfiguration>> _fileConfig;
 | 
			
		||||
        private readonly Mock<IConfigurationValidator> _validator;
 | 
			
		||||
        private Response<IOcelotConfiguration> _config;
 | 
			
		||||
        private Response<IInternalConfiguration> _config;
 | 
			
		||||
        private FileConfiguration _fileConfiguration;
 | 
			
		||||
        private readonly Mock<IOcelotLoggerFactory> _logger;
 | 
			
		||||
        private readonly FileOcelotConfigurationCreator _ocelotConfigurationCreator;
 | 
			
		||||
        private Mock<IClaimsToThingCreator> _claimsToThingCreator;
 | 
			
		||||
        private Mock<IAuthenticationOptionsCreator> _authOptionsCreator;
 | 
			
		||||
        private Mock<IUpstreamTemplatePatternCreator> _upstreamTemplatePatternCreator;
 | 
			
		||||
        private Mock<IRequestIdKeyCreator> _requestIdKeyCreator;
 | 
			
		||||
        private Mock<IServiceProviderConfigurationCreator> _serviceProviderConfigCreator;
 | 
			
		||||
        private Mock<IQoSOptionsCreator> _qosOptionsCreator;
 | 
			
		||||
        private Mock<IReRouteOptionsCreator> _fileReRouteOptionsCreator;
 | 
			
		||||
        private Mock<IRateLimitOptionsCreator> _rateLimitOptions;
 | 
			
		||||
        private Mock<IRegionCreator> _regionCreator;
 | 
			
		||||
        private Mock<IHttpHandlerOptionsCreator> _httpHandlerOptionsCreator;
 | 
			
		||||
        private Mock<IAdministrationPath> _adminPath;
 | 
			
		||||
        private readonly FileInternalConfigurationCreator _internalConfigurationCreator;
 | 
			
		||||
        private readonly Mock<IClaimsToThingCreator> _claimsToThingCreator;
 | 
			
		||||
        private readonly Mock<IAuthenticationOptionsCreator> _authOptionsCreator;
 | 
			
		||||
        private readonly Mock<IUpstreamTemplatePatternCreator> _upstreamTemplatePatternCreator;
 | 
			
		||||
        private readonly Mock<IRequestIdKeyCreator> _requestIdKeyCreator;
 | 
			
		||||
        private readonly Mock<IServiceProviderConfigurationCreator> _serviceProviderConfigCreator;
 | 
			
		||||
        private readonly Mock<IQoSOptionsCreator> _qosOptionsCreator;
 | 
			
		||||
        private readonly Mock<IReRouteOptionsCreator> _fileReRouteOptionsCreator;
 | 
			
		||||
        private readonly Mock<IRateLimitOptionsCreator> _rateLimitOptions;
 | 
			
		||||
        private readonly Mock<IRegionCreator> _regionCreator;
 | 
			
		||||
        private readonly Mock<IHttpHandlerOptionsCreator> _httpHandlerOptionsCreator;
 | 
			
		||||
        private readonly Mock<IAdministrationPath> _adminPath;
 | 
			
		||||
        private readonly Mock<IHeaderFindAndReplaceCreator> _headerFindAndReplaceCreator;
 | 
			
		||||
        private readonly Mock<IDownstreamAddressesCreator> _downstreamAddressesCreator;
 | 
			
		||||
 | 
			
		||||
@@ -48,7 +43,6 @@ namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
        {
 | 
			
		||||
            _logger = new Mock<IOcelotLoggerFactory>();
 | 
			
		||||
            _validator = new Mock<IConfigurationValidator>();
 | 
			
		||||
            _fileConfig = new Mock<IOptions<FileConfiguration>>();
 | 
			
		||||
            _claimsToThingCreator = new Mock<IClaimsToThingCreator>();
 | 
			
		||||
            _authOptionsCreator = new Mock<IAuthenticationOptionsCreator>();
 | 
			
		||||
            _upstreamTemplatePatternCreator = new Mock<IUpstreamTemplatePatternCreator>();
 | 
			
		||||
@@ -63,8 +57,7 @@ namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
            _headerFindAndReplaceCreator = new Mock<IHeaderFindAndReplaceCreator>();
 | 
			
		||||
            _downstreamAddressesCreator = new Mock<IDownstreamAddressesCreator>();
 | 
			
		||||
 | 
			
		||||
            _ocelotConfigurationCreator = new FileOcelotConfigurationCreator( 
 | 
			
		||||
                _fileConfig.Object,
 | 
			
		||||
            _internalConfigurationCreator = new FileInternalConfigurationCreator( 
 | 
			
		||||
                _validator.Object, 
 | 
			
		||||
                _logger.Object,
 | 
			
		||||
                _claimsToThingCreator.Object,
 | 
			
		||||
@@ -262,7 +255,7 @@ namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
                .And(x => x.GivenTheConfigIsValid())
 | 
			
		||||
                .And(x => x.GivenTheFollowingRegionIsReturned("region"))
 | 
			
		||||
                .When(x => x.WhenICreateTheConfig())
 | 
			
		||||
                .Then(x => x.ThenTheRegionCreatorIsCalledCorrectly("region"))
 | 
			
		||||
                .Then(x => x.ThenTheRegionCreatorIsCalledCorrectly())
 | 
			
		||||
                .And(x => x.ThenTheHeaderFindAndReplaceCreatorIsCalledCorrectly())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
@@ -800,14 +793,11 @@ namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
        private void GivenTheConfigIs(FileConfiguration fileConfiguration)
 | 
			
		||||
        {
 | 
			
		||||
            _fileConfiguration = fileConfiguration;
 | 
			
		||||
            _fileConfig
 | 
			
		||||
                .Setup(x => x.Value)
 | 
			
		||||
                .Returns(_fileConfiguration);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WhenICreateTheConfig()
 | 
			
		||||
        {
 | 
			
		||||
            _config = _ocelotConfigurationCreator.Create(_fileConfiguration).Result;
 | 
			
		||||
            _config = _internalConfigurationCreator.Create(_fileConfiguration).Result;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheReRoutesAre(List<ReRoute> expectedReRoutes)
 | 
			
		||||
@@ -928,7 +918,7 @@ namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
                .Returns(region);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheRegionCreatorIsCalledCorrectly(string expected)
 | 
			
		||||
        private void ThenTheRegionCreatorIsCalledCorrectly()
 | 
			
		||||
        {
 | 
			
		||||
            _regionCreator
 | 
			
		||||
                .Verify(x => x.Create(_fileConfiguration.ReRoutes[0]), Times.Once);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,60 +0,0 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using Moq;
 | 
			
		||||
using Ocelot.Configuration;
 | 
			
		||||
using Ocelot.Configuration.File;
 | 
			
		||||
using Ocelot.Responses;
 | 
			
		||||
using Shouldly;
 | 
			
		||||
using TestStack.BDDfy;
 | 
			
		||||
using Xunit;
 | 
			
		||||
using Newtonsoft.Json;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using Ocelot.Configuration.Provider;
 | 
			
		||||
using Ocelot.Configuration.Repository;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
{
 | 
			
		||||
    public class FileConfigurationProviderTests
 | 
			
		||||
    {
 | 
			
		||||
        private readonly IFileConfigurationProvider _provider;
 | 
			
		||||
        private Mock<IFileConfigurationRepository> _repo;
 | 
			
		||||
        private FileConfiguration _result;
 | 
			
		||||
        private FileConfiguration _fileConfiguration;
 | 
			
		||||
 | 
			
		||||
        public FileConfigurationProviderTests()
 | 
			
		||||
        {
 | 
			
		||||
            _repo = new Mock<IFileConfigurationRepository>();
 | 
			
		||||
            _provider = new FileConfigurationProvider(_repo.Object);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_return_file_configuration()
 | 
			
		||||
        {
 | 
			
		||||
            var config = new FileConfiguration();
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenTheConfigurationIs(config))
 | 
			
		||||
                .When(x => x.WhenIGetTheReRoutes())
 | 
			
		||||
                .Then(x => x.ThenTheRepoIsCalledCorrectly())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenTheConfigurationIs(FileConfiguration fileConfiguration)
 | 
			
		||||
        {
 | 
			
		||||
            _fileConfiguration = fileConfiguration;
 | 
			
		||||
            _repo
 | 
			
		||||
                .Setup(x => x.Get())
 | 
			
		||||
                .ReturnsAsync(new OkResponse<FileConfiguration>(fileConfiguration));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WhenIGetTheReRoutes()
 | 
			
		||||
        {
 | 
			
		||||
            _result = _provider.Get().Result.Data;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheRepoIsCalledCorrectly()
 | 
			
		||||
        {
 | 
			
		||||
            _repo
 | 
			
		||||
                .Verify(x => x.Get(), Times.Once);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -18,12 +18,16 @@ namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
        private IFileConfigurationRepository _repo;
 | 
			
		||||
        private FileConfiguration _result;
 | 
			
		||||
        private FileConfiguration _fileConfiguration;
 | 
			
		||||
        private string _environmentName = "DEV";
 | 
			
		||||
 | 
			
		||||
        // This is a bit dirty and it is dev.dev so that the ConfigurationBuilderExtensionsTests
 | 
			
		||||
        // cant pick it up if they run in parralel..sigh these are not really unit 
 | 
			
		||||
        // tests but whatever...
 | 
			
		||||
        private string _environmentName = "DEV.DEV";
 | 
			
		||||
 | 
			
		||||
        public FileConfigurationRepositoryTests()
 | 
			
		||||
        {
 | 
			
		||||
            _hostingEnvironment.Setup(he => he.EnvironmentName).Returns(_environmentName);
 | 
			
		||||
            _repo = new FileConfigurationRepository(_hostingEnvironment.Object);
 | 
			
		||||
            _repo = new DiskFileConfigurationRepository(_hostingEnvironment.Object);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
@@ -75,7 +79,7 @@ namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
        {
 | 
			
		||||
            _environmentName = null;
 | 
			
		||||
            _hostingEnvironment.Setup(he => he.EnvironmentName).Returns(_environmentName);
 | 
			
		||||
            _repo = new FileConfigurationRepository(_hostingEnvironment.Object);
 | 
			
		||||
            _repo = new DiskFileConfigurationRepository(_hostingEnvironment.Object);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenIHaveAConfiguration(FileConfiguration fileConfiguration)
 | 
			
		||||
@@ -113,7 +117,7 @@ namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
 | 
			
		||||
        private void GivenTheConfigurationIs(FileConfiguration fileConfiguration)
 | 
			
		||||
        {
 | 
			
		||||
            var configurationPath = $"{AppContext.BaseDirectory}/configuration{(string.IsNullOrEmpty(_environmentName) ? string.Empty : ".")}{_environmentName}.json";
 | 
			
		||||
            var configurationPath = $"{AppContext.BaseDirectory}/ocelot{(string.IsNullOrEmpty(_environmentName) ? string.Empty : ".")}{_environmentName}.json";
 | 
			
		||||
 | 
			
		||||
            var jsonConfiguration = JsonConvert.SerializeObject(fileConfiguration);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -18,19 +18,19 @@ namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
    public class FileConfigurationSetterTests
 | 
			
		||||
    {
 | 
			
		||||
        private FileConfiguration _fileConfiguration;
 | 
			
		||||
        private FileConfigurationSetter _configSetter;
 | 
			
		||||
        private Mock<IOcelotConfigurationRepository> _configRepo;
 | 
			
		||||
        private Mock<IOcelotConfigurationCreator> _configCreator;
 | 
			
		||||
        private Response<IOcelotConfiguration> _configuration;
 | 
			
		||||
        private FileAndInternalConfigurationSetter _configSetter;
 | 
			
		||||
        private Mock<IInternalConfigurationRepository> _configRepo;
 | 
			
		||||
        private Mock<IInternalConfigurationCreator> _configCreator;
 | 
			
		||||
        private Response<IInternalConfiguration> _configuration;
 | 
			
		||||
        private object _result; 
 | 
			
		||||
        private Mock<IFileConfigurationRepository> _repo;
 | 
			
		||||
 | 
			
		||||
        public FileConfigurationSetterTests()
 | 
			
		||||
        {
 | 
			
		||||
            _repo = new Mock<IFileConfigurationRepository>();
 | 
			
		||||
            _configRepo = new Mock<IOcelotConfigurationRepository>();
 | 
			
		||||
            _configCreator = new Mock<IOcelotConfigurationCreator>();
 | 
			
		||||
            _configSetter = new FileConfigurationSetter(_configRepo.Object, _configCreator.Object, _repo.Object);
 | 
			
		||||
            _configRepo = new Mock<IInternalConfigurationRepository>();
 | 
			
		||||
            _configCreator = new Mock<IInternalConfigurationCreator>();
 | 
			
		||||
            _configSetter = new FileAndInternalConfigurationSetter(_configRepo.Object, _configCreator.Object, _repo.Object);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
@@ -38,11 +38,11 @@ namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
        {
 | 
			
		||||
            var fileConfig = new FileConfiguration();
 | 
			
		||||
            var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build();
 | 
			
		||||
            var config = new OcelotConfiguration(new List<ReRoute>(), string.Empty, serviceProviderConfig, "asdf");
 | 
			
		||||
            var config = new InternalConfiguration(new List<ReRoute>(), string.Empty, serviceProviderConfig, "asdf");
 | 
			
		||||
 | 
			
		||||
            this.Given(x => GivenTheFollowingConfiguration(fileConfig))
 | 
			
		||||
                .And(x => GivenTheRepoReturns(new OkResponse()))
 | 
			
		||||
                .And(x => GivenTheCreatorReturns(new OkResponse<IOcelotConfiguration>(config)))
 | 
			
		||||
                .And(x => GivenTheCreatorReturns(new OkResponse<IInternalConfiguration>(config)))
 | 
			
		||||
                .When(x => WhenISetTheConfiguration())
 | 
			
		||||
                .Then(x => ThenTheConfigurationRepositoryIsCalledCorrectly())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
@@ -67,7 +67,7 @@ namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
 | 
			
		||||
            this.Given(x => GivenTheFollowingConfiguration(fileConfig))
 | 
			
		||||
                .And(x => GivenTheRepoReturns(new OkResponse()))
 | 
			
		||||
                .And(x => GivenTheCreatorReturns(new ErrorResponse<IOcelotConfiguration>(It.IsAny<Error>())))
 | 
			
		||||
                .And(x => GivenTheCreatorReturns(new ErrorResponse<IInternalConfiguration>(It.IsAny<Error>())))
 | 
			
		||||
                .When(x => WhenISetTheConfiguration())
 | 
			
		||||
                .And(x => ThenAnErrorResponseIsReturned())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
@@ -85,7 +85,7 @@ namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
            _result.ShouldBeOfType<ErrorResponse>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenTheCreatorReturns(Response<IOcelotConfiguration> configuration)
 | 
			
		||||
        private void GivenTheCreatorReturns(Response<IInternalConfiguration> configuration)
 | 
			
		||||
        {
 | 
			
		||||
            _configuration = configuration;
 | 
			
		||||
            _configCreator
 | 
			
		||||
 
 | 
			
		||||
@@ -1,76 +0,0 @@
 | 
			
		||||
using Ocelot.Configuration.Authentication;
 | 
			
		||||
using Shouldly;
 | 
			
		||||
using TestStack.BDDfy;
 | 
			
		||||
using Xunit;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
{
 | 
			
		||||
    public class HashMatcherTests
 | 
			
		||||
    {
 | 
			
		||||
        private string _password;
 | 
			
		||||
        private string _hash;
 | 
			
		||||
        private string _salt;
 | 
			
		||||
        private bool _result;
 | 
			
		||||
        private HashMatcher _hashMatcher;
 | 
			
		||||
 | 
			
		||||
        public HashMatcherTests()
 | 
			
		||||
        {
 | 
			
		||||
            _hashMatcher = new HashMatcher();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_match_hash()
 | 
			
		||||
        {   
 | 
			
		||||
            var hash = "kE/mxd1hO9h9Sl2VhGhwJUd9xZEv4NP6qXoN39nIqM4=";
 | 
			
		||||
            var salt = "zzWITpnDximUNKYLiUam/w==";
 | 
			
		||||
            var password = "secret";
 | 
			
		||||
 | 
			
		||||
            this.Given(x => GivenThePassword(password))
 | 
			
		||||
                .And(x => GivenTheHash(hash))
 | 
			
		||||
                .And(x => GivenTheSalt(salt))
 | 
			
		||||
                .When(x => WhenIMatch())
 | 
			
		||||
                .Then(x => ThenTheResultIs(true))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_not_match_hash()
 | 
			
		||||
        {
 | 
			
		||||
            var hash = "kE/mxd1hO9h9Sl2VhGhwJUd9xZEv4NP6qXoN39nIqM4=";
 | 
			
		||||
            var salt = "zzWITpnDximUNKYLiUam/w==";
 | 
			
		||||
            var password = "secret1";
 | 
			
		||||
 | 
			
		||||
            this.Given(x => GivenThePassword(password))
 | 
			
		||||
                .And(x => GivenTheHash(hash))
 | 
			
		||||
                .And(x => GivenTheSalt(salt))
 | 
			
		||||
                .When(x => WhenIMatch())
 | 
			
		||||
                .Then(x => ThenTheResultIs(false))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenThePassword(string password)
 | 
			
		||||
        {
 | 
			
		||||
            _password = password;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenTheHash(string hash)
 | 
			
		||||
        {
 | 
			
		||||
            _hash = hash;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenTheSalt(string salt)
 | 
			
		||||
        {
 | 
			
		||||
            _salt = salt;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WhenIMatch()
 | 
			
		||||
        {
 | 
			
		||||
            _result = _hashMatcher.Match(_password, _salt, _hash);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheResultIs(bool expected)
 | 
			
		||||
        {
 | 
			
		||||
            _result.ShouldBe(expected);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -149,6 +149,7 @@ namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
                .Then(x => ThenTheFollowingDownstreamIsReturned(downstream))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_add_trace_id_header()
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,5 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Ocelot.Configuration;
 | 
			
		||||
using Ocelot.Configuration.Builder;
 | 
			
		||||
using Ocelot.Configuration.Repository;
 | 
			
		||||
@@ -14,14 +12,14 @@ namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
{
 | 
			
		||||
    public class InMemoryConfigurationRepositoryTests
 | 
			
		||||
    {
 | 
			
		||||
        private readonly InMemoryOcelotConfigurationRepository _repo;
 | 
			
		||||
        private IOcelotConfiguration _config;
 | 
			
		||||
        private readonly InMemoryInternalConfigurationRepository _repo;
 | 
			
		||||
        private IInternalConfiguration _config;
 | 
			
		||||
        private Response _result;
 | 
			
		||||
        private Response<IOcelotConfiguration> _getResult;
 | 
			
		||||
        private Response<IInternalConfiguration> _getResult;
 | 
			
		||||
 | 
			
		||||
        public InMemoryConfigurationRepositoryTests()
 | 
			
		||||
        {
 | 
			
		||||
            _repo = new InMemoryOcelotConfigurationRepository();
 | 
			
		||||
            _repo = new InMemoryInternalConfigurationRepository();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
@@ -49,7 +47,7 @@ namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
 | 
			
		||||
        private void WhenIGetTheConfiguration()
 | 
			
		||||
        {
 | 
			
		||||
            _getResult = _repo.Get().Result;
 | 
			
		||||
            _getResult = _repo.Get();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenThereIsASavedConfiguration()
 | 
			
		||||
@@ -58,14 +56,14 @@ namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
            WhenIAddOrReplaceTheConfig();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenTheConfigurationIs(IOcelotConfiguration config)
 | 
			
		||||
        private void GivenTheConfigurationIs(IInternalConfiguration config)
 | 
			
		||||
        {
 | 
			
		||||
            _config = config;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WhenIAddOrReplaceTheConfig()
 | 
			
		||||
        {
 | 
			
		||||
            _result = _repo.AddOrReplace(_config).Result;
 | 
			
		||||
            _result = _repo.AddOrReplace(_config);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenNoErrorsAreReturned()
 | 
			
		||||
@@ -73,7 +71,7 @@ namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
            _result.IsError.ShouldBeFalse();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        class FakeConfig : IOcelotConfiguration
 | 
			
		||||
        class FakeConfig : IInternalConfiguration
 | 
			
		||||
        {
 | 
			
		||||
            private readonly string _downstreamTemplatePath;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,80 +0,0 @@
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using Moq;
 | 
			
		||||
using Ocelot.Configuration;
 | 
			
		||||
using Ocelot.Configuration.Builder;
 | 
			
		||||
using Ocelot.Configuration.Creator;
 | 
			
		||||
using Ocelot.Configuration.Provider;
 | 
			
		||||
using Ocelot.Configuration.Repository;
 | 
			
		||||
using Ocelot.Errors;
 | 
			
		||||
using Ocelot.Responses;
 | 
			
		||||
using Shouldly;
 | 
			
		||||
using TestStack.BDDfy;
 | 
			
		||||
using Xunit;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
{
 | 
			
		||||
    public class OcelotConfigurationProviderTests
 | 
			
		||||
    {
 | 
			
		||||
        private readonly IOcelotConfigurationProvider _ocelotConfigurationProvider;
 | 
			
		||||
        private readonly Mock<IOcelotConfigurationRepository> _configurationRepository;
 | 
			
		||||
        private Response<IOcelotConfiguration> _result;
 | 
			
		||||
 | 
			
		||||
        public OcelotConfigurationProviderTests()
 | 
			
		||||
        {
 | 
			
		||||
            _configurationRepository = new Mock<IOcelotConfigurationRepository>();
 | 
			
		||||
            _ocelotConfigurationProvider = new OcelotConfigurationProvider(_configurationRepository.Object);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_get_config()
 | 
			
		||||
        {
 | 
			
		||||
            var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build();
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenTheRepoReturns(new OkResponse<IOcelotConfiguration>(new OcelotConfiguration(new List<ReRoute>(), string.Empty, serviceProviderConfig, ""))))
 | 
			
		||||
                .When(x => x.WhenIGetTheConfig())
 | 
			
		||||
                .Then(x => x.TheFollowingIsReturned(new OkResponse<IOcelotConfiguration>(new OcelotConfiguration(new List<ReRoute>(), string.Empty, serviceProviderConfig, ""))))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_return_error()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.GivenTheRepoReturns(new ErrorResponse<IOcelotConfiguration>(new List<Error>
 | 
			
		||||
                    {
 | 
			
		||||
                        new AnyError()
 | 
			
		||||
                    })))
 | 
			
		||||
              .When(x => x.WhenIGetTheConfig())
 | 
			
		||||
              .Then(x => x.TheFollowingIsReturned(
 | 
			
		||||
                    new ErrorResponse<IOcelotConfiguration>(new List<Error>
 | 
			
		||||
                    {
 | 
			
		||||
                        new AnyError()
 | 
			
		||||
                    })))
 | 
			
		||||
              .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenTheRepoReturns(Response<IOcelotConfiguration> config)
 | 
			
		||||
        {
 | 
			
		||||
            _configurationRepository
 | 
			
		||||
                .Setup(x => x.Get())
 | 
			
		||||
                .ReturnsAsync(config);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WhenIGetTheConfig()
 | 
			
		||||
        {
 | 
			
		||||
            _result = _ocelotConfigurationProvider.Get().Result;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void TheFollowingIsReturned(Response<IOcelotConfiguration> expected)
 | 
			
		||||
        {
 | 
			
		||||
            _result.IsError.ShouldBe(expected.IsError);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        class AnyError : Error
 | 
			
		||||
        {
 | 
			
		||||
            public AnyError() 
 | 
			
		||||
                : base("blamo", OcelotErrorCode.UnknownError)
 | 
			
		||||
            {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -8,32 +8,30 @@ using Ocelot.Responses;
 | 
			
		||||
using TestStack.BDDfy;
 | 
			
		||||
using Xunit;
 | 
			
		||||
using Shouldly;
 | 
			
		||||
using Ocelot.Configuration.Provider;
 | 
			
		||||
using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
using Ocelot.Raft;
 | 
			
		||||
using Rafty.Concensus;
 | 
			
		||||
using Newtonsoft.Json;
 | 
			
		||||
using Rafty.FiniteStateMachine;
 | 
			
		||||
using Ocelot.Configuration;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.UnitTests.Controllers
 | 
			
		||||
{
 | 
			
		||||
    using Ocelot.Configuration.Repository;
 | 
			
		||||
 | 
			
		||||
    public class FileConfigurationControllerTests
 | 
			
		||||
    {
 | 
			
		||||
        private FileConfigurationController _controller;
 | 
			
		||||
        private Mock<IFileConfigurationProvider> _configGetter;
 | 
			
		||||
        private Mock<IFileConfigurationSetter> _configSetter;
 | 
			
		||||
        private readonly FileConfigurationController _controller;
 | 
			
		||||
        private readonly Mock<IFileConfigurationRepository> _repo;
 | 
			
		||||
        private readonly Mock<IFileConfigurationSetter> _setter;
 | 
			
		||||
        private IActionResult _result;
 | 
			
		||||
        private FileConfiguration _fileConfiguration;
 | 
			
		||||
        private Mock<IServiceProvider> _provider;
 | 
			
		||||
        private readonly Mock<IServiceProvider> _provider;
 | 
			
		||||
        private Mock<INode> _node;
 | 
			
		||||
 | 
			
		||||
        public FileConfigurationControllerTests()
 | 
			
		||||
        {
 | 
			
		||||
            _provider = new Mock<IServiceProvider>();
 | 
			
		||||
            _configGetter = new Mock<IFileConfigurationProvider>();
 | 
			
		||||
            _configSetter = new Mock<IFileConfigurationSetter>();
 | 
			
		||||
            _controller = new FileConfigurationController(_configGetter.Object, _configSetter.Object, _provider.Object);
 | 
			
		||||
            _repo = new Mock<IFileConfigurationRepository>();
 | 
			
		||||
            _setter = new Mock<IFileConfigurationSetter>();
 | 
			
		||||
            _controller = new FileConfigurationController(_repo.Object, _setter.Object, _provider.Object);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        [Fact]
 | 
			
		||||
@@ -140,14 +138,14 @@ namespace Ocelot.UnitTests.Controllers
 | 
			
		||||
 | 
			
		||||
        private void GivenTheConfigSetterReturns(Response response)
 | 
			
		||||
        {
 | 
			
		||||
            _configSetter
 | 
			
		||||
            _setter
 | 
			
		||||
                .Setup(x => x.Set(It.IsAny<FileConfiguration>()))
 | 
			
		||||
                .ReturnsAsync(response);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheConfigrationSetterIsCalledCorrectly()
 | 
			
		||||
        {
 | 
			
		||||
            _configSetter
 | 
			
		||||
            _setter
 | 
			
		||||
                .Verify(x => x.Set(_fileConfiguration), Times.Once);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -168,7 +166,7 @@ namespace Ocelot.UnitTests.Controllers
 | 
			
		||||
 | 
			
		||||
        private void GivenTheGetConfigurationReturns(Ocelot.Responses.Response<FileConfiguration> fileConfiguration)
 | 
			
		||||
        {
 | 
			
		||||
            _configGetter
 | 
			
		||||
            _repo
 | 
			
		||||
                .Setup(x => x.Get())
 | 
			
		||||
                .ReturnsAsync(fileConfiguration);
 | 
			
		||||
        }
 | 
			
		||||
@@ -180,7 +178,7 @@ namespace Ocelot.UnitTests.Controllers
 | 
			
		||||
 | 
			
		||||
        private void TheTheGetFileConfigurationIsCalledCorrectly()
 | 
			
		||||
        {
 | 
			
		||||
               _configGetter
 | 
			
		||||
               _repo
 | 
			
		||||
                .Verify(x => x.Get(), Times.Once);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,25 +1,213 @@
 | 
			
		||||
using Microsoft.Extensions.Configuration;
 | 
			
		||||
using Ocelot.DependencyInjection;
 | 
			
		||||
using Shouldly;
 | 
			
		||||
using TestStack.BDDfy;
 | 
			
		||||
using Xunit;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.UnitTests.DependencyInjection
 | 
			
		||||
namespace Ocelot.UnitTests.DependencyInjection
 | 
			
		||||
{
 | 
			
		||||
    using System.Collections.Generic;
 | 
			
		||||
    using System.IO;
 | 
			
		||||
    using Newtonsoft.Json;
 | 
			
		||||
    using Ocelot.Configuration.File;
 | 
			
		||||
    using Microsoft.Extensions.Configuration;
 | 
			
		||||
    using Ocelot.DependencyInjection;
 | 
			
		||||
    using Shouldly;
 | 
			
		||||
    using TestStack.BDDfy;
 | 
			
		||||
    using Xunit;
 | 
			
		||||
 | 
			
		||||
    public class ConfigurationBuilderExtensionsTests
 | 
			
		||||
    {
 | 
			
		||||
        private IConfigurationRoot _configuration;
 | 
			
		||||
        private string _result;
 | 
			
		||||
        private IConfigurationRoot _configRoot;
 | 
			
		||||
        private FileConfiguration _globalConfig;
 | 
			
		||||
        private FileConfiguration _reRouteA;
 | 
			
		||||
        private FileConfiguration _reRouteB;
 | 
			
		||||
        private FileConfiguration _aggregate;
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_add_base_url_to_config()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => GivenTheBaseUrl("test"))
 | 
			
		||||
                .When(x => WhenIGet("BaseUrl"))
 | 
			
		||||
                .Then(x => ThenTheResultIs("test"))
 | 
			
		||||
            this.Given(_ => GivenTheBaseUrl("test"))
 | 
			
		||||
                .When(_ => WhenIGet("BaseUrl"))
 | 
			
		||||
                .Then(_ => ThenTheResultIs("test"))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_merge_files()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(_ => GivenMultipleConfigurationFiles())
 | 
			
		||||
                .When(_ => WhenIAddOcelotConfiguration())
 | 
			
		||||
                .Then(_ => ThenTheConfigsAreMerged())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenMultipleConfigurationFiles()
 | 
			
		||||
        {
 | 
			
		||||
            _globalConfig = new FileConfiguration
 | 
			
		||||
            {
 | 
			
		||||
                GlobalConfiguration = new FileGlobalConfiguration
 | 
			
		||||
                {
 | 
			
		||||
                    BaseUrl = "BaseUrl",
 | 
			
		||||
                    RateLimitOptions = new FileRateLimitOptions
 | 
			
		||||
                    {
 | 
			
		||||
                        HttpStatusCode = 500,
 | 
			
		||||
                        ClientIdHeader = "ClientIdHeader",
 | 
			
		||||
                        DisableRateLimitHeaders = true,
 | 
			
		||||
                        QuotaExceededMessage = "QuotaExceededMessage",
 | 
			
		||||
                        RateLimitCounterPrefix = "RateLimitCounterPrefix"
 | 
			
		||||
                    },
 | 
			
		||||
                    ServiceDiscoveryProvider = new FileServiceDiscoveryProvider
 | 
			
		||||
                    {
 | 
			
		||||
                        Host = "Host",
 | 
			
		||||
                        Port = 80,
 | 
			
		||||
                        Type = "Type"
 | 
			
		||||
                    },
 | 
			
		||||
                    RequestIdKey = "RequestIdKey"
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            _reRouteA = new FileConfiguration
 | 
			
		||||
            {
 | 
			
		||||
                ReRoutes = new List<FileReRoute>
 | 
			
		||||
                {
 | 
			
		||||
                    new FileReRoute
 | 
			
		||||
                    {
 | 
			
		||||
                        DownstreamScheme = "DownstreamScheme",
 | 
			
		||||
                        DownstreamPathTemplate = "DownstreamPathTemplate",
 | 
			
		||||
                        Key = "Key",
 | 
			
		||||
                        UpstreamHost = "UpstreamHost",
 | 
			
		||||
                        UpstreamHttpMethod = new List<string>
 | 
			
		||||
                        {
 | 
			
		||||
                            "UpstreamHttpMethod"
 | 
			
		||||
                        },
 | 
			
		||||
                        DownstreamHostAndPorts = new List<FileHostAndPort>
 | 
			
		||||
                        {
 | 
			
		||||
                            new FileHostAndPort
 | 
			
		||||
                            {
 | 
			
		||||
                                Host = "Host",
 | 
			
		||||
                                Port = 80
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            _reRouteB = new FileConfiguration
 | 
			
		||||
            {
 | 
			
		||||
                ReRoutes = new List<FileReRoute>
 | 
			
		||||
                {
 | 
			
		||||
                    new FileReRoute
 | 
			
		||||
                    {
 | 
			
		||||
                        DownstreamScheme = "DownstreamSchemeB",
 | 
			
		||||
                        DownstreamPathTemplate = "DownstreamPathTemplateB",
 | 
			
		||||
                        Key = "KeyB",
 | 
			
		||||
                        UpstreamHost = "UpstreamHostB",
 | 
			
		||||
                        UpstreamHttpMethod = new List<string>
 | 
			
		||||
                        {
 | 
			
		||||
                            "UpstreamHttpMethodB"
 | 
			
		||||
                        },
 | 
			
		||||
                        DownstreamHostAndPorts = new List<FileHostAndPort>
 | 
			
		||||
                        {
 | 
			
		||||
                            new FileHostAndPort
 | 
			
		||||
                            {
 | 
			
		||||
                                Host = "HostB",
 | 
			
		||||
                                Port = 80
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    },
 | 
			
		||||
                    new FileReRoute
 | 
			
		||||
                    {
 | 
			
		||||
                        DownstreamScheme = "DownstreamSchemeBB",
 | 
			
		||||
                        DownstreamPathTemplate = "DownstreamPathTemplateBB",
 | 
			
		||||
                        Key = "KeyBB",
 | 
			
		||||
                        UpstreamHost = "UpstreamHostBB",
 | 
			
		||||
                        UpstreamHttpMethod = new List<string>
 | 
			
		||||
                        {
 | 
			
		||||
                            "UpstreamHttpMethodBB"
 | 
			
		||||
                        },
 | 
			
		||||
                        DownstreamHostAndPorts = new List<FileHostAndPort>
 | 
			
		||||
                        {
 | 
			
		||||
                            new FileHostAndPort
 | 
			
		||||
                            {
 | 
			
		||||
                                Host = "HostBB",
 | 
			
		||||
                                Port = 80
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            _aggregate = new FileConfiguration
 | 
			
		||||
            {
 | 
			
		||||
                Aggregates = new List<FileAggregateReRoute>
 | 
			
		||||
                {
 | 
			
		||||
                    new FileAggregateReRoute
 | 
			
		||||
                    {
 | 
			
		||||
                        ReRouteKeys = new List<string> 
 | 
			
		||||
                        {
 | 
			
		||||
                            "KeyB",
 | 
			
		||||
                            "KeyBB"
 | 
			
		||||
                        },
 | 
			
		||||
                        UpstreamPathTemplate = "UpstreamPathTemplate",
 | 
			
		||||
                    },
 | 
			
		||||
                    new FileAggregateReRoute
 | 
			
		||||
                    {
 | 
			
		||||
                        ReRouteKeys = new List<string> 
 | 
			
		||||
                        {
 | 
			
		||||
                            "KeyB",
 | 
			
		||||
                            "KeyBB"
 | 
			
		||||
                        },
 | 
			
		||||
                        UpstreamPathTemplate = "UpstreamPathTemplate",
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            File.WriteAllText("ocelot.global.json", JsonConvert.SerializeObject(_globalConfig));
 | 
			
		||||
            File.WriteAllText("ocelot.reRoutesA.json", JsonConvert.SerializeObject(_reRouteA));
 | 
			
		||||
            File.WriteAllText("ocelot.reRoutesB.json", JsonConvert.SerializeObject(_reRouteB));
 | 
			
		||||
            File.WriteAllText("ocelot.aggregates.json", JsonConvert.SerializeObject(_aggregate));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WhenIAddOcelotConfiguration()
 | 
			
		||||
        {
 | 
			
		||||
            IConfigurationBuilder builder = new ConfigurationBuilder();
 | 
			
		||||
            builder.AddOcelot();
 | 
			
		||||
            _configRoot = builder.Build();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheConfigsAreMerged()
 | 
			
		||||
        {
 | 
			
		||||
            var fc = (FileConfiguration)_configRoot.Get(typeof(FileConfiguration));
 | 
			
		||||
 | 
			
		||||
            fc.GlobalConfiguration.BaseUrl.ShouldBe(_globalConfig.GlobalConfiguration.BaseUrl);
 | 
			
		||||
            fc.GlobalConfiguration.RateLimitOptions.ClientIdHeader.ShouldBe(_globalConfig.GlobalConfiguration.RateLimitOptions.ClientIdHeader);
 | 
			
		||||
            fc.GlobalConfiguration.RateLimitOptions.DisableRateLimitHeaders.ShouldBe(_globalConfig.GlobalConfiguration.RateLimitOptions.DisableRateLimitHeaders);
 | 
			
		||||
            fc.GlobalConfiguration.RateLimitOptions.HttpStatusCode.ShouldBe(_globalConfig.GlobalConfiguration.RateLimitOptions.HttpStatusCode);
 | 
			
		||||
            fc.GlobalConfiguration.RateLimitOptions.QuotaExceededMessage.ShouldBe(_globalConfig.GlobalConfiguration.RateLimitOptions.QuotaExceededMessage);
 | 
			
		||||
            fc.GlobalConfiguration.RateLimitOptions.RateLimitCounterPrefix.ShouldBe(_globalConfig.GlobalConfiguration.RateLimitOptions.RateLimitCounterPrefix);
 | 
			
		||||
            fc.GlobalConfiguration.RequestIdKey.ShouldBe(_globalConfig.GlobalConfiguration.RequestIdKey);
 | 
			
		||||
            fc.GlobalConfiguration.ServiceDiscoveryProvider.Host.ShouldBe(_globalConfig.GlobalConfiguration.ServiceDiscoveryProvider.Host);
 | 
			
		||||
            fc.GlobalConfiguration.ServiceDiscoveryProvider.Port.ShouldBe(_globalConfig.GlobalConfiguration.ServiceDiscoveryProvider.Port);
 | 
			
		||||
            fc.GlobalConfiguration.ServiceDiscoveryProvider.Type.ShouldBe(_globalConfig.GlobalConfiguration.ServiceDiscoveryProvider.Type);
 | 
			
		||||
 | 
			
		||||
            fc.ReRoutes.Count.ShouldBe(_reRouteA.ReRoutes.Count + _reRouteB.ReRoutes.Count);
 | 
			
		||||
 | 
			
		||||
            fc.ReRoutes.ShouldContain(x => x.DownstreamPathTemplate == _reRouteA.ReRoutes[0].DownstreamPathTemplate);
 | 
			
		||||
            fc.ReRoutes.ShouldContain(x => x.DownstreamPathTemplate == _reRouteB.ReRoutes[0].DownstreamPathTemplate);
 | 
			
		||||
            fc.ReRoutes.ShouldContain(x => x.DownstreamPathTemplate == _reRouteB.ReRoutes[1].DownstreamPathTemplate);
 | 
			
		||||
 | 
			
		||||
            fc.ReRoutes.ShouldContain(x => x.DownstreamScheme == _reRouteA.ReRoutes[0].DownstreamScheme);
 | 
			
		||||
            fc.ReRoutes.ShouldContain(x => x.DownstreamScheme == _reRouteB.ReRoutes[0].DownstreamScheme);
 | 
			
		||||
            fc.ReRoutes.ShouldContain(x => x.DownstreamScheme == _reRouteB.ReRoutes[1].DownstreamScheme);
 | 
			
		||||
 | 
			
		||||
            fc.ReRoutes.ShouldContain(x => x.Key == _reRouteA.ReRoutes[0].Key);
 | 
			
		||||
            fc.ReRoutes.ShouldContain(x => x.Key == _reRouteB.ReRoutes[0].Key);
 | 
			
		||||
            fc.ReRoutes.ShouldContain(x => x.Key == _reRouteB.ReRoutes[1].Key);
 | 
			
		||||
 | 
			
		||||
            fc.ReRoutes.ShouldContain(x => x.UpstreamHost == _reRouteA.ReRoutes[0].UpstreamHost);
 | 
			
		||||
            fc.ReRoutes.ShouldContain(x => x.UpstreamHost == _reRouteB.ReRoutes[0].UpstreamHost);
 | 
			
		||||
            fc.ReRoutes.ShouldContain(x => x.UpstreamHost == _reRouteB.ReRoutes[1].UpstreamHost);
 | 
			
		||||
 | 
			
		||||
            fc.Aggregates.Count.ShouldBe(_aggregate.Aggregates.Count);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenTheBaseUrl(string baseUrl)
 | 
			
		||||
        {
 | 
			
		||||
            #pragma warning disable CS0618
 | 
			
		||||
 
 | 
			
		||||
@@ -325,8 +325,8 @@ namespace Ocelot.UnitTests.DependencyInjection
 | 
			
		||||
            var outputCache = _services.Single(x => x.ServiceType == typeof(IOcelotCache<CachedResponse>));
 | 
			
		||||
            var outputCacheManager = _services.Single(x => x.ServiceType == typeof(ICacheManager<CachedResponse>));
 | 
			
		||||
            var instance = (ICacheManager<CachedResponse>)outputCacheManager.ImplementationInstance;
 | 
			
		||||
            var ocelotConfigCache = _services.Single(x => x.ServiceType == typeof(IOcelotCache<IOcelotConfiguration>));
 | 
			
		||||
            var ocelotConfigCacheManager = _services.Single(x => x.ServiceType == typeof(ICacheManager<IOcelotConfiguration>));
 | 
			
		||||
            var ocelotConfigCache = _services.Single(x => x.ServiceType == typeof(IOcelotCache<IInternalConfiguration>));
 | 
			
		||||
            var ocelotConfigCacheManager = _services.Single(x => x.ServiceType == typeof(ICacheManager<IInternalConfiguration>));
 | 
			
		||||
            var fileConfigCache = _services.Single(x => x.ServiceType == typeof(IOcelotCache<FileConfiguration>));
 | 
			
		||||
            var fileConfigCacheManager = _services.Single(x => x.ServiceType == typeof(ICacheManager<FileConfiguration>));
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,4 @@
 | 
			
		||||
using Ocelot.Middleware;
 | 
			
		||||
using Ocelot.Middleware.Multiplexer;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.UnitTests.DownstreamRouteFinder
 | 
			
		||||
namespace Ocelot.UnitTests.DownstreamRouteFinder
 | 
			
		||||
{
 | 
			
		||||
    using System.Collections.Generic;
 | 
			
		||||
    using System.Threading.Tasks;
 | 
			
		||||
@@ -9,7 +6,6 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
 | 
			
		||||
    using Moq;
 | 
			
		||||
    using Ocelot.Configuration;
 | 
			
		||||
    using Ocelot.Configuration.Builder;
 | 
			
		||||
    using Ocelot.Configuration.Provider;
 | 
			
		||||
    using Ocelot.DownstreamRouteFinder;
 | 
			
		||||
    using Ocelot.DownstreamRouteFinder.Finder;
 | 
			
		||||
    using Ocelot.DownstreamRouteFinder.Middleware;
 | 
			
		||||
@@ -19,23 +15,26 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
 | 
			
		||||
    using Shouldly;
 | 
			
		||||
    using TestStack.BDDfy;
 | 
			
		||||
    using Xunit;
 | 
			
		||||
    using Ocelot.Configuration.Repository;
 | 
			
		||||
    using Ocelot.Middleware;
 | 
			
		||||
    using Ocelot.Middleware.Multiplexer;
 | 
			
		||||
 | 
			
		||||
    public class DownstreamRouteFinderMiddlewareTests
 | 
			
		||||
    {
 | 
			
		||||
        private readonly Mock<IDownstreamRouteFinder> _finder;
 | 
			
		||||
        private readonly Mock<IOcelotConfigurationProvider> _provider;
 | 
			
		||||
        private readonly Mock<IInternalConfigurationRepository> _repo;
 | 
			
		||||
        private Response<DownstreamRoute> _downstreamRoute;
 | 
			
		||||
        private IOcelotConfiguration _config;
 | 
			
		||||
        private IInternalConfiguration _config;
 | 
			
		||||
        private Mock<IOcelotLoggerFactory> _loggerFactory;
 | 
			
		||||
        private Mock<IOcelotLogger> _logger;
 | 
			
		||||
        private DownstreamRouteFinderMiddleware _middleware;
 | 
			
		||||
        private DownstreamContext _downstreamContext;
 | 
			
		||||
        private readonly DownstreamRouteFinderMiddleware _middleware;
 | 
			
		||||
        private readonly DownstreamContext _downstreamContext;
 | 
			
		||||
        private OcelotRequestDelegate _next;
 | 
			
		||||
        private readonly Mock<IMultiplexer> _multiplexer;
 | 
			
		||||
 | 
			
		||||
        public DownstreamRouteFinderMiddlewareTests()
 | 
			
		||||
        {
 | 
			
		||||
            _provider = new Mock<IOcelotConfigurationProvider>();
 | 
			
		||||
            _repo = new Mock<IInternalConfigurationRepository>();
 | 
			
		||||
            _finder = new Mock<IDownstreamRouteFinder>();
 | 
			
		||||
            _downstreamContext = new DownstreamContext(new DefaultHttpContext());
 | 
			
		||||
            _loggerFactory = new Mock<IOcelotLoggerFactory>();
 | 
			
		||||
@@ -43,13 +42,13 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
 | 
			
		||||
            _loggerFactory.Setup(x => x.CreateLogger<DownstreamRouteFinderMiddleware>()).Returns(_logger.Object);
 | 
			
		||||
            _next = context => Task.CompletedTask;
 | 
			
		||||
            _multiplexer = new Mock<IMultiplexer>();
 | 
			
		||||
            _middleware = new DownstreamRouteFinderMiddleware(_next, _loggerFactory.Object, _finder.Object, _provider.Object, _multiplexer.Object);
 | 
			
		||||
            _middleware = new DownstreamRouteFinderMiddleware(_next, _loggerFactory.Object, _finder.Object, _repo.Object, _multiplexer.Object);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_call_scoped_data_repository_correctly()
 | 
			
		||||
        {
 | 
			
		||||
            var config = new OcelotConfiguration(null, null, new ServiceProviderConfigurationBuilder().Build(), "");
 | 
			
		||||
            var config = new InternalConfiguration(null, null, new ServiceProviderConfigurationBuilder().Build(), "");
 | 
			
		||||
 | 
			
		||||
            var downstreamReRoute = new DownstreamReRouteBuilder()
 | 
			
		||||
                .WithDownstreamPathTemplate("any old string")
 | 
			
		||||
@@ -74,19 +73,19 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
 | 
			
		||||
            _middleware.Invoke(_downstreamContext).GetAwaiter().GetType();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenTheFollowingConfig(IOcelotConfiguration config)
 | 
			
		||||
        private void GivenTheFollowingConfig(IInternalConfiguration config)
 | 
			
		||||
        {
 | 
			
		||||
            _config = config;
 | 
			
		||||
            _provider
 | 
			
		||||
            _repo
 | 
			
		||||
                .Setup(x => x.Get())
 | 
			
		||||
                .ReturnsAsync(new OkResponse<IOcelotConfiguration>(_config));
 | 
			
		||||
                .Returns(new OkResponse<IInternalConfiguration>(_config));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenTheDownStreamRouteFinderReturns(DownstreamRoute downstreamRoute)
 | 
			
		||||
        {
 | 
			
		||||
            _downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
 | 
			
		||||
            _finder
 | 
			
		||||
                .Setup(x => x.FindDownstreamRoute(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<IOcelotConfiguration>(), It.IsAny<string>()))
 | 
			
		||||
                .Setup(x => x.FindDownstreamRoute(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<IInternalConfiguration>(), It.IsAny<string>()))
 | 
			
		||||
                .Returns(_downstreamRoute);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,8 +2,6 @@
 | 
			
		||||
using Moq;
 | 
			
		||||
using Ocelot.Configuration;
 | 
			
		||||
using Ocelot.Configuration.Builder;
 | 
			
		||||
using Ocelot.Configuration.Creator;
 | 
			
		||||
using Ocelot.Configuration.Provider;
 | 
			
		||||
using Ocelot.DownstreamRouteFinder;
 | 
			
		||||
using Ocelot.DownstreamRouteFinder.Finder;
 | 
			
		||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
 | 
			
		||||
@@ -23,7 +21,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
 | 
			
		||||
        private string _upstreamUrlPath;
 | 
			
		||||
        private Response<DownstreamRoute> _result;
 | 
			
		||||
        private List<ReRoute> _reRoutesConfig;
 | 
			
		||||
        private OcelotConfiguration _config;
 | 
			
		||||
        private InternalConfiguration _config;
 | 
			
		||||
        private Response<UrlMatch> _match;
 | 
			
		||||
        private string _upstreamHttpMethod;
 | 
			
		||||
        private string _upstreamHost;
 | 
			
		||||
@@ -711,7 +709,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
 | 
			
		||||
        private void GivenTheConfigurationIs(List<ReRoute> reRoutesConfig, string adminPath, ServiceProviderConfiguration serviceProviderConfig)
 | 
			
		||||
        {
 | 
			
		||||
            _reRoutesConfig = reRoutesConfig;
 | 
			
		||||
            _config = new OcelotConfiguration(_reRoutesConfig, adminPath, serviceProviderConfig, "");
 | 
			
		||||
            _config = new InternalConfiguration(_reRoutesConfig, adminPath, serviceProviderConfig, "");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenThereIsAnUpstreamUrlPath(string upstreamUrlPath)
 | 
			
		||||
 
 | 
			
		||||
@@ -9,17 +9,17 @@ namespace Ocelot.UnitTests.Errors
 | 
			
		||||
    using TestStack.BDDfy;
 | 
			
		||||
    using Xunit;
 | 
			
		||||
    using Microsoft.AspNetCore.Http;
 | 
			
		||||
    using Ocelot.Configuration.Provider;
 | 
			
		||||
    using Moq;
 | 
			
		||||
    using Ocelot.Configuration;
 | 
			
		||||
    using Ocelot.Errors;
 | 
			
		||||
    using Ocelot.Infrastructure.RequestData;
 | 
			
		||||
    using Ocelot.Middleware;
 | 
			
		||||
    using Ocelot.Configuration.Repository;
 | 
			
		||||
 | 
			
		||||
    public class ExceptionHandlerMiddlewareTests
 | 
			
		||||
    {
 | 
			
		||||
        bool _shouldThrowAnException;
 | 
			
		||||
        private readonly Mock<IOcelotConfigurationProvider> _provider;
 | 
			
		||||
        private readonly Mock<IInternalConfigurationRepository> _configRepo;
 | 
			
		||||
        private readonly Mock<IRequestScopedDataRepository> _repo;
 | 
			
		||||
        private Mock<IOcelotLoggerFactory> _loggerFactory;
 | 
			
		||||
        private Mock<IOcelotLogger> _logger;
 | 
			
		||||
@@ -29,7 +29,7 @@ namespace Ocelot.UnitTests.Errors
 | 
			
		||||
 | 
			
		||||
        public ExceptionHandlerMiddlewareTests()
 | 
			
		||||
        {
 | 
			
		||||
            _provider = new Mock<IOcelotConfigurationProvider>();
 | 
			
		||||
            _configRepo = new Mock<IInternalConfigurationRepository>();
 | 
			
		||||
            _repo = new Mock<IRequestScopedDataRepository>();
 | 
			
		||||
            _downstreamContext = new DownstreamContext(new DefaultHttpContext());
 | 
			
		||||
            _loggerFactory = new Mock<IOcelotLoggerFactory>();
 | 
			
		||||
@@ -45,13 +45,13 @@ namespace Ocelot.UnitTests.Errors
 | 
			
		||||
 | 
			
		||||
                context.HttpContext.Response.StatusCode = (int)HttpStatusCode.OK;
 | 
			
		||||
            };
 | 
			
		||||
            _middleware = new ExceptionHandlerMiddleware(_next, _loggerFactory.Object, _provider.Object, _repo.Object);
 | 
			
		||||
            _middleware = new ExceptionHandlerMiddleware(_next, _loggerFactory.Object, _configRepo.Object, _repo.Object);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void NoDownstreamException()
 | 
			
		||||
        {
 | 
			
		||||
            var config = new OcelotConfiguration(null, null, null, null);
 | 
			
		||||
            var config = new InternalConfiguration(null, null, null, null);
 | 
			
		||||
 | 
			
		||||
            this.Given(_ => GivenAnExceptionWillNotBeThrownDownstream())
 | 
			
		||||
                .And(_ => GivenTheConfigurationIs(config))
 | 
			
		||||
@@ -64,7 +64,7 @@ namespace Ocelot.UnitTests.Errors
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void DownstreamException()
 | 
			
		||||
        {
 | 
			
		||||
            var config = new OcelotConfiguration(null, null, null, null);
 | 
			
		||||
            var config = new InternalConfiguration(null, null, null, null);
 | 
			
		||||
 | 
			
		||||
            this.Given(_ => GivenAnExceptionWillBeThrownDownstream())
 | 
			
		||||
                .And(_ => GivenTheConfigurationIs(config))
 | 
			
		||||
@@ -76,7 +76,7 @@ namespace Ocelot.UnitTests.Errors
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void ShouldSetRequestId()
 | 
			
		||||
        {
 | 
			
		||||
            var config = new OcelotConfiguration(null, null, null, "requestidkey");
 | 
			
		||||
            var config = new InternalConfiguration(null, null, null, "requestidkey");
 | 
			
		||||
 | 
			
		||||
            this.Given(_ => GivenAnExceptionWillNotBeThrownDownstream())
 | 
			
		||||
                .And(_ => GivenTheConfigurationIs(config))
 | 
			
		||||
@@ -89,7 +89,7 @@ namespace Ocelot.UnitTests.Errors
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void ShouldSetAspDotNetRequestId()
 | 
			
		||||
        {
 | 
			
		||||
            var config = new OcelotConfiguration(null, null, null, null);
 | 
			
		||||
            var config = new InternalConfiguration(null, null, null, null);
 | 
			
		||||
 | 
			
		||||
            this.Given(_ => GivenAnExceptionWillNotBeThrownDownstream())
 | 
			
		||||
                .And(_ => GivenTheConfigurationIs(config))
 | 
			
		||||
@@ -133,8 +133,8 @@ namespace Ocelot.UnitTests.Errors
 | 
			
		||||
        private void GivenTheConfigThrows()
 | 
			
		||||
        {
 | 
			
		||||
            var ex = new Exception("outer", new Exception("inner"));
 | 
			
		||||
             _provider
 | 
			
		||||
                .Setup(x => x.Get()).ThrowsAsync(ex);
 | 
			
		||||
             _configRepo
 | 
			
		||||
                .Setup(x => x.Get()).Throws(ex);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenAnExceptionIsThrown()
 | 
			
		||||
@@ -144,9 +144,9 @@ namespace Ocelot.UnitTests.Errors
 | 
			
		||||
 | 
			
		||||
        private void GivenTheConfigReturnsError()
 | 
			
		||||
        {
 | 
			
		||||
            var response = new Responses.ErrorResponse<IOcelotConfiguration>(new FakeError());
 | 
			
		||||
            _provider
 | 
			
		||||
                .Setup(x => x.Get()).ReturnsAsync(response);
 | 
			
		||||
            var response = new Responses.ErrorResponse<IInternalConfiguration>(new FakeError());
 | 
			
		||||
            _configRepo
 | 
			
		||||
                .Setup(x => x.Get()).Returns(response);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void TheRequestIdIsSet(string key, string value)
 | 
			
		||||
@@ -154,11 +154,11 @@ namespace Ocelot.UnitTests.Errors
 | 
			
		||||
            _repo.Verify(x => x.Add(key, value), Times.Once);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenTheConfigurationIs(IOcelotConfiguration config)
 | 
			
		||||
        private void GivenTheConfigurationIs(IInternalConfiguration config)
 | 
			
		||||
        {
 | 
			
		||||
            var response = new Responses.OkResponse<IOcelotConfiguration>(config);
 | 
			
		||||
            _provider
 | 
			
		||||
                .Setup(x => x.Get()).ReturnsAsync(response);
 | 
			
		||||
            var response = new Responses.OkResponse<IInternalConfiguration>(config);
 | 
			
		||||
            _configRepo
 | 
			
		||||
                .Setup(x => x.Get()).Returns(response);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenAnExceptionWillNotBeThrownDownstream()
 | 
			
		||||
 
 | 
			
		||||
@@ -28,12 +28,6 @@
 | 
			
		||||
  <Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
 | 
			
		||||
   <ItemGroup>
 | 
			
		||||
    <None Update="idsrv3test.pfx">
 | 
			
		||||
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 | 
			
		||||
    </None>
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.6" />
 | 
			
		||||
    <PackageReference Include="Microsoft.AspNetCore.TestHost" Version="2.0.2" />
 | 
			
		||||
 
 | 
			
		||||
@@ -1 +0,0 @@
 | 
			
		||||
{"ReRoutes":[{"DownstreamPathTemplate":"/test/test/{test}","UpstreamPathTemplate":null,"UpstreamHttpMethod":null,"AuthenticationOptions":{"Provider":null,"ProviderRootUrl":null,"ApiName":null,"RequireHttps":false,"AllowedScopes":[],"ApiSecret":null},"AddHeadersToRequest":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{},"AddQueriesToRequest":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0},"ReRouteIsCaseSensitive":false,"ServiceName":null,"DownstreamScheme":"https","DownstreamHost":"localhost","DownstreamPort":80,"QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancer":null}],"GlobalConfiguration":{"RequestIdKey":null,"ServiceDiscoveryProvider":{"Provider":"consul","Host":"blah","Port":198},"AdministrationPath":"testy"}}
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							
		Reference in New Issue
	
	Block a user