mirror of
				https://github.com/nsnail/Ocelot.git
				synced 2025-11-04 15:50:49 +08:00 
			
		
		
		
	Rename all ReRoute to Route to move closer to YARP +semver: breaking
This commit is contained in:
		@@ -1,334 +1,334 @@
 | 
			
		||||
namespace Ocelot.UnitTests.DependencyInjection
 | 
			
		||||
{
 | 
			
		||||
    using Microsoft.AspNetCore.Hosting;
 | 
			
		||||
    using Microsoft.Extensions.Configuration;
 | 
			
		||||
    using Moq;
 | 
			
		||||
    using Newtonsoft.Json;
 | 
			
		||||
    using Ocelot.Configuration.File;
 | 
			
		||||
    using Ocelot.DependencyInjection;
 | 
			
		||||
    using Shouldly;
 | 
			
		||||
    using System.Collections.Generic;
 | 
			
		||||
    using System.IO;
 | 
			
		||||
    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;
 | 
			
		||||
        private FileConfiguration _envSpecific;
 | 
			
		||||
        private Mock<IWebHostEnvironment> _hostingEnvironment;
 | 
			
		||||
 | 
			
		||||
        public ConfigurationBuilderExtensionsTests()
 | 
			
		||||
        {
 | 
			
		||||
            _hostingEnvironment = new Mock<IWebHostEnvironment>();
 | 
			
		||||
            // Clean up config files before each test
 | 
			
		||||
            var subConfigFiles = new DirectoryInfo(".").GetFiles("ocelot.*.json");
 | 
			
		||||
 | 
			
		||||
            foreach (var config in subConfigFiles)
 | 
			
		||||
            {
 | 
			
		||||
                config.Delete();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_add_base_url_to_config()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(_ => GivenTheBaseUrl("test"))
 | 
			
		||||
                .When(_ => WhenIGet("BaseUrl"))
 | 
			
		||||
                .Then(_ => ThenTheResultIs("test"))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_merge_files()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(_ => GivenMultipleConfigurationFiles("", false))
 | 
			
		||||
                .And(_ => GivenTheEnvironmentIs(null))
 | 
			
		||||
                .When(_ => WhenIAddOcelotConfiguration())
 | 
			
		||||
                .Then(_ => ThenTheConfigsAreMerged())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_merge_files_except_env()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(_ => GivenMultipleConfigurationFiles("", true))
 | 
			
		||||
                .And(_ => GivenTheEnvironmentIs("Env"))
 | 
			
		||||
                .When(_ => WhenIAddOcelotConfiguration())
 | 
			
		||||
                .Then(_ => ThenTheConfigsAreMerged())
 | 
			
		||||
                .And(_ => NotContainsEnvSpecificConfig())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_merge_files_in_specific_folder()
 | 
			
		||||
        {
 | 
			
		||||
            string configFolder = "ConfigFiles";
 | 
			
		||||
            this.Given(_ => GivenMultipleConfigurationFiles(configFolder, false))
 | 
			
		||||
                .When(_ => WhenIAddOcelotConfigurationWithSpecificFolder(configFolder))
 | 
			
		||||
                .Then(_ => ThenTheConfigsAreMerged())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenMultipleConfigurationFiles(string folder, bool addEnvSpecificConfig)
 | 
			
		||||
        {
 | 
			
		||||
            if (!string.IsNullOrEmpty(folder))
 | 
			
		||||
            {
 | 
			
		||||
                Directory.CreateDirectory(folder);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            _globalConfig = new FileConfiguration
 | 
			
		||||
            {
 | 
			
		||||
                GlobalConfiguration = new FileGlobalConfiguration
 | 
			
		||||
                {
 | 
			
		||||
                    BaseUrl = "BaseUrl",
 | 
			
		||||
                    RateLimitOptions = new FileRateLimitOptions
 | 
			
		||||
                    {
 | 
			
		||||
                        HttpStatusCode = 500,
 | 
			
		||||
                        ClientIdHeader = "ClientIdHeader",
 | 
			
		||||
                        DisableRateLimitHeaders = true,
 | 
			
		||||
                        QuotaExceededMessage = "QuotaExceededMessage",
 | 
			
		||||
                        RateLimitCounterPrefix = "RateLimitCounterPrefix"
 | 
			
		||||
                    },
 | 
			
		||||
                    ServiceDiscoveryProvider = new FileServiceDiscoveryProvider
 | 
			
		||||
                    {
 | 
			
		||||
                        Scheme = "https",
 | 
			
		||||
                        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",
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            _envSpecific = new FileConfiguration
 | 
			
		||||
            {
 | 
			
		||||
                ReRoutes = new List<FileReRoute>
 | 
			
		||||
                    {
 | 
			
		||||
                        new FileReRoute
 | 
			
		||||
                        {
 | 
			
		||||
                            DownstreamScheme = "DownstreamSchemeSpec",
 | 
			
		||||
                            DownstreamPathTemplate = "DownstreamPathTemplateSpec",
 | 
			
		||||
                            Key = "KeySpec",
 | 
			
		||||
                            UpstreamHost = "UpstreamHostSpec",
 | 
			
		||||
                            UpstreamHttpMethod = new List<string>
 | 
			
		||||
                            {
 | 
			
		||||
                                "UpstreamHttpMethodSpec"
 | 
			
		||||
                            },
 | 
			
		||||
                            DownstreamHostAndPorts = new List<FileHostAndPort>
 | 
			
		||||
                            {
 | 
			
		||||
                                new FileHostAndPort
 | 
			
		||||
                                {
 | 
			
		||||
                                    Host = "HostSpec",
 | 
			
		||||
                                    Port = 80
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            string globalFilename = Path.Combine(folder, "ocelot.global.json");
 | 
			
		||||
            string reroutesAFilename = Path.Combine(folder, "ocelot.reRoutesA.json");
 | 
			
		||||
            string reroutesBFilename = Path.Combine(folder, "ocelot.reRoutesB.json");
 | 
			
		||||
            string aggregatesFilename = Path.Combine(folder, "ocelot.aggregates.json");
 | 
			
		||||
 | 
			
		||||
            File.WriteAllText(globalFilename, JsonConvert.SerializeObject(_globalConfig));
 | 
			
		||||
            File.WriteAllText(reroutesAFilename, JsonConvert.SerializeObject(_reRouteA));
 | 
			
		||||
            File.WriteAllText(reroutesBFilename, JsonConvert.SerializeObject(_reRouteB));
 | 
			
		||||
            File.WriteAllText(aggregatesFilename, JsonConvert.SerializeObject(_aggregate));
 | 
			
		||||
 | 
			
		||||
            if (addEnvSpecificConfig)
 | 
			
		||||
            {
 | 
			
		||||
                string envSpecificFilename = Path.Combine(folder, "ocelot.Env.json");
 | 
			
		||||
                File.WriteAllText(envSpecificFilename, JsonConvert.SerializeObject(_envSpecific));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenTheEnvironmentIs(string env)
 | 
			
		||||
        {
 | 
			
		||||
            _hostingEnvironment.SetupGet(x => x.EnvironmentName).Returns(env);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WhenIAddOcelotConfiguration()
 | 
			
		||||
        {
 | 
			
		||||
            IConfigurationBuilder builder = new ConfigurationBuilder();
 | 
			
		||||
 | 
			
		||||
            builder.AddOcelot(_hostingEnvironment.Object);
 | 
			
		||||
 | 
			
		||||
            _configRoot = builder.Build();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WhenIAddOcelotConfigurationWithSpecificFolder(string folder)
 | 
			
		||||
        {
 | 
			
		||||
            IConfigurationBuilder builder = new ConfigurationBuilder();
 | 
			
		||||
            builder.AddOcelot(folder, _hostingEnvironment.Object);
 | 
			
		||||
            _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.Scheme.ShouldBe(_globalConfig.GlobalConfiguration.ServiceDiscoveryProvider.Scheme);
 | 
			
		||||
            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 NotContainsEnvSpecificConfig()
 | 
			
		||||
        {
 | 
			
		||||
            var fc = (FileConfiguration)_configRoot.Get(typeof(FileConfiguration));
 | 
			
		||||
            fc.ReRoutes.ShouldNotContain(x => x.DownstreamScheme == _envSpecific.ReRoutes[0].DownstreamScheme);
 | 
			
		||||
            fc.ReRoutes.ShouldNotContain(x => x.DownstreamPathTemplate == _envSpecific.ReRoutes[0].DownstreamPathTemplate);
 | 
			
		||||
            fc.ReRoutes.ShouldNotContain(x => x.Key == _envSpecific.ReRoutes[0].Key);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenTheBaseUrl(string baseUrl)
 | 
			
		||||
        {
 | 
			
		||||
#pragma warning disable CS0618
 | 
			
		||||
            var builder = new ConfigurationBuilder()
 | 
			
		||||
                .AddOcelotBaseUrl(baseUrl);
 | 
			
		||||
#pragma warning restore CS0618
 | 
			
		||||
            _configuration = builder.Build();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WhenIGet(string key)
 | 
			
		||||
        {
 | 
			
		||||
            _result = _configuration.GetValue(key, "");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheResultIs(string expected)
 | 
			
		||||
        {
 | 
			
		||||
            _result.ShouldBe(expected);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
namespace Ocelot.UnitTests.DependencyInjection
 | 
			
		||||
{
 | 
			
		||||
    using Microsoft.AspNetCore.Hosting;
 | 
			
		||||
    using Microsoft.Extensions.Configuration;
 | 
			
		||||
    using Moq;
 | 
			
		||||
    using Newtonsoft.Json;
 | 
			
		||||
    using Ocelot.Configuration.File;
 | 
			
		||||
    using Ocelot.DependencyInjection;
 | 
			
		||||
    using Shouldly;
 | 
			
		||||
    using System.Collections.Generic;
 | 
			
		||||
    using System.IO;
 | 
			
		||||
    using TestStack.BDDfy;
 | 
			
		||||
    using Xunit;
 | 
			
		||||
 | 
			
		||||
    public class ConfigurationBuilderExtensionsTests
 | 
			
		||||
    {
 | 
			
		||||
        private IConfigurationRoot _configuration;
 | 
			
		||||
        private string _result;
 | 
			
		||||
        private IConfigurationRoot _configRoot;
 | 
			
		||||
        private FileConfiguration _globalConfig;
 | 
			
		||||
        private FileConfiguration _routeA;
 | 
			
		||||
        private FileConfiguration _routeB;
 | 
			
		||||
        private FileConfiguration _aggregate;
 | 
			
		||||
        private FileConfiguration _envSpecific;
 | 
			
		||||
        private Mock<IWebHostEnvironment> _hostingEnvironment;
 | 
			
		||||
 | 
			
		||||
        public ConfigurationBuilderExtensionsTests()
 | 
			
		||||
        {
 | 
			
		||||
            _hostingEnvironment = new Mock<IWebHostEnvironment>();
 | 
			
		||||
            // Clean up config files before each test
 | 
			
		||||
            var subConfigFiles = new DirectoryInfo(".").GetFiles("ocelot.*.json");
 | 
			
		||||
 | 
			
		||||
            foreach (var config in subConfigFiles)
 | 
			
		||||
            {
 | 
			
		||||
                config.Delete();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_add_base_url_to_config()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(_ => GivenTheBaseUrl("test"))
 | 
			
		||||
                .When(_ => WhenIGet("BaseUrl"))
 | 
			
		||||
                .Then(_ => ThenTheResultIs("test"))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_merge_files()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(_ => GivenMultipleConfigurationFiles("", false))
 | 
			
		||||
                .And(_ => GivenTheEnvironmentIs(null))
 | 
			
		||||
                .When(_ => WhenIAddOcelotConfiguration())
 | 
			
		||||
                .Then(_ => ThenTheConfigsAreMerged())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_merge_files_except_env()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(_ => GivenMultipleConfigurationFiles("", true))
 | 
			
		||||
                .And(_ => GivenTheEnvironmentIs("Env"))
 | 
			
		||||
                .When(_ => WhenIAddOcelotConfiguration())
 | 
			
		||||
                .Then(_ => ThenTheConfigsAreMerged())
 | 
			
		||||
                .And(_ => NotContainsEnvSpecificConfig())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_merge_files_in_specific_folder()
 | 
			
		||||
        {
 | 
			
		||||
            string configFolder = "ConfigFiles";
 | 
			
		||||
            this.Given(_ => GivenMultipleConfigurationFiles(configFolder, false))
 | 
			
		||||
                .When(_ => WhenIAddOcelotConfigurationWithSpecificFolder(configFolder))
 | 
			
		||||
                .Then(_ => ThenTheConfigsAreMerged())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenMultipleConfigurationFiles(string folder, bool addEnvSpecificConfig)
 | 
			
		||||
        {
 | 
			
		||||
            if (!string.IsNullOrEmpty(folder))
 | 
			
		||||
            {
 | 
			
		||||
                Directory.CreateDirectory(folder);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            _globalConfig = new FileConfiguration
 | 
			
		||||
            {
 | 
			
		||||
                GlobalConfiguration = new FileGlobalConfiguration
 | 
			
		||||
                {
 | 
			
		||||
                    BaseUrl = "BaseUrl",
 | 
			
		||||
                    RateLimitOptions = new FileRateLimitOptions
 | 
			
		||||
                    {
 | 
			
		||||
                        HttpStatusCode = 500,
 | 
			
		||||
                        ClientIdHeader = "ClientIdHeader",
 | 
			
		||||
                        DisableRateLimitHeaders = true,
 | 
			
		||||
                        QuotaExceededMessage = "QuotaExceededMessage",
 | 
			
		||||
                        RateLimitCounterPrefix = "RateLimitCounterPrefix"
 | 
			
		||||
                    },
 | 
			
		||||
                    ServiceDiscoveryProvider = new FileServiceDiscoveryProvider
 | 
			
		||||
                    {
 | 
			
		||||
                        Scheme = "https",
 | 
			
		||||
                        Host = "Host",
 | 
			
		||||
                        Port = 80,
 | 
			
		||||
                        Type = "Type"
 | 
			
		||||
                    },
 | 
			
		||||
                    RequestIdKey = "RequestIdKey"
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            _routeA = new FileConfiguration
 | 
			
		||||
            {
 | 
			
		||||
                Routes = new List<FileRoute>
 | 
			
		||||
                {
 | 
			
		||||
                    new FileRoute
 | 
			
		||||
                    {
 | 
			
		||||
                        DownstreamScheme = "DownstreamScheme",
 | 
			
		||||
                        DownstreamPathTemplate = "DownstreamPathTemplate",
 | 
			
		||||
                        Key = "Key",
 | 
			
		||||
                        UpstreamHost = "UpstreamHost",
 | 
			
		||||
                        UpstreamHttpMethod = new List<string>
 | 
			
		||||
                        {
 | 
			
		||||
                            "UpstreamHttpMethod"
 | 
			
		||||
                        },
 | 
			
		||||
                        DownstreamHostAndPorts = new List<FileHostAndPort>
 | 
			
		||||
                        {
 | 
			
		||||
                            new FileHostAndPort
 | 
			
		||||
                            {
 | 
			
		||||
                                Host = "Host",
 | 
			
		||||
                                Port = 80
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            _routeB = new FileConfiguration
 | 
			
		||||
            {
 | 
			
		||||
                Routes = new List<FileRoute>
 | 
			
		||||
                {
 | 
			
		||||
                    new FileRoute
 | 
			
		||||
                    {
 | 
			
		||||
                        DownstreamScheme = "DownstreamSchemeB",
 | 
			
		||||
                        DownstreamPathTemplate = "DownstreamPathTemplateB",
 | 
			
		||||
                        Key = "KeyB",
 | 
			
		||||
                        UpstreamHost = "UpstreamHostB",
 | 
			
		||||
                        UpstreamHttpMethod = new List<string>
 | 
			
		||||
                        {
 | 
			
		||||
                            "UpstreamHttpMethodB"
 | 
			
		||||
                        },
 | 
			
		||||
                        DownstreamHostAndPorts = new List<FileHostAndPort>
 | 
			
		||||
                        {
 | 
			
		||||
                            new FileHostAndPort
 | 
			
		||||
                            {
 | 
			
		||||
                                Host = "HostB",
 | 
			
		||||
                                Port = 80
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    },
 | 
			
		||||
                    new FileRoute
 | 
			
		||||
                    {
 | 
			
		||||
                        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<FileAggregateRoute>
 | 
			
		||||
                {
 | 
			
		||||
                    new FileAggregateRoute
 | 
			
		||||
                    {
 | 
			
		||||
                        RouteKeys = new List<string>
 | 
			
		||||
                        {
 | 
			
		||||
                            "KeyB",
 | 
			
		||||
                            "KeyBB"
 | 
			
		||||
                        },
 | 
			
		||||
                        UpstreamPathTemplate = "UpstreamPathTemplate",
 | 
			
		||||
                    },
 | 
			
		||||
                    new FileAggregateRoute
 | 
			
		||||
                    {
 | 
			
		||||
                        RouteKeys = new List<string>
 | 
			
		||||
                        {
 | 
			
		||||
                            "KeyB",
 | 
			
		||||
                            "KeyBB"
 | 
			
		||||
                        },
 | 
			
		||||
                        UpstreamPathTemplate = "UpstreamPathTemplate",
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            _envSpecific = new FileConfiguration
 | 
			
		||||
            {
 | 
			
		||||
                Routes = new List<FileRoute>
 | 
			
		||||
                    {
 | 
			
		||||
                        new FileRoute
 | 
			
		||||
                        {
 | 
			
		||||
                            DownstreamScheme = "DownstreamSchemeSpec",
 | 
			
		||||
                            DownstreamPathTemplate = "DownstreamPathTemplateSpec",
 | 
			
		||||
                            Key = "KeySpec",
 | 
			
		||||
                            UpstreamHost = "UpstreamHostSpec",
 | 
			
		||||
                            UpstreamHttpMethod = new List<string>
 | 
			
		||||
                            {
 | 
			
		||||
                                "UpstreamHttpMethodSpec"
 | 
			
		||||
                            },
 | 
			
		||||
                            DownstreamHostAndPorts = new List<FileHostAndPort>
 | 
			
		||||
                            {
 | 
			
		||||
                                new FileHostAndPort
 | 
			
		||||
                                {
 | 
			
		||||
                                    Host = "HostSpec",
 | 
			
		||||
                                    Port = 80
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            string globalFilename = Path.Combine(folder, "ocelot.global.json");
 | 
			
		||||
            string routesAFilename = Path.Combine(folder, "ocelot.routesA.json");
 | 
			
		||||
            string routesBFilename = Path.Combine(folder, "ocelot.routesB.json");
 | 
			
		||||
            string aggregatesFilename = Path.Combine(folder, "ocelot.aggregates.json");
 | 
			
		||||
 | 
			
		||||
            File.WriteAllText(globalFilename, JsonConvert.SerializeObject(_globalConfig));
 | 
			
		||||
            File.WriteAllText(routesAFilename, JsonConvert.SerializeObject(_routeA));
 | 
			
		||||
            File.WriteAllText(routesBFilename, JsonConvert.SerializeObject(_routeB));
 | 
			
		||||
            File.WriteAllText(aggregatesFilename, JsonConvert.SerializeObject(_aggregate));
 | 
			
		||||
 | 
			
		||||
            if (addEnvSpecificConfig)
 | 
			
		||||
            {
 | 
			
		||||
                string envSpecificFilename = Path.Combine(folder, "ocelot.Env.json");
 | 
			
		||||
                File.WriteAllText(envSpecificFilename, JsonConvert.SerializeObject(_envSpecific));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenTheEnvironmentIs(string env)
 | 
			
		||||
        {
 | 
			
		||||
            _hostingEnvironment.SetupGet(x => x.EnvironmentName).Returns(env);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WhenIAddOcelotConfiguration()
 | 
			
		||||
        {
 | 
			
		||||
            IConfigurationBuilder builder = new ConfigurationBuilder();
 | 
			
		||||
 | 
			
		||||
            builder.AddOcelot(_hostingEnvironment.Object);
 | 
			
		||||
 | 
			
		||||
            _configRoot = builder.Build();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WhenIAddOcelotConfigurationWithSpecificFolder(string folder)
 | 
			
		||||
        {
 | 
			
		||||
            IConfigurationBuilder builder = new ConfigurationBuilder();
 | 
			
		||||
            builder.AddOcelot(folder, _hostingEnvironment.Object);
 | 
			
		||||
            _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.Scheme.ShouldBe(_globalConfig.GlobalConfiguration.ServiceDiscoveryProvider.Scheme);
 | 
			
		||||
            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.Routes.Count.ShouldBe(_routeA.Routes.Count + _routeB.Routes.Count);
 | 
			
		||||
 | 
			
		||||
            fc.Routes.ShouldContain(x => x.DownstreamPathTemplate == _routeA.Routes[0].DownstreamPathTemplate);
 | 
			
		||||
            fc.Routes.ShouldContain(x => x.DownstreamPathTemplate == _routeB.Routes[0].DownstreamPathTemplate);
 | 
			
		||||
            fc.Routes.ShouldContain(x => x.DownstreamPathTemplate == _routeB.Routes[1].DownstreamPathTemplate);
 | 
			
		||||
 | 
			
		||||
            fc.Routes.ShouldContain(x => x.DownstreamScheme == _routeA.Routes[0].DownstreamScheme);
 | 
			
		||||
            fc.Routes.ShouldContain(x => x.DownstreamScheme == _routeB.Routes[0].DownstreamScheme);
 | 
			
		||||
            fc.Routes.ShouldContain(x => x.DownstreamScheme == _routeB.Routes[1].DownstreamScheme);
 | 
			
		||||
 | 
			
		||||
            fc.Routes.ShouldContain(x => x.Key == _routeA.Routes[0].Key);
 | 
			
		||||
            fc.Routes.ShouldContain(x => x.Key == _routeB.Routes[0].Key);
 | 
			
		||||
            fc.Routes.ShouldContain(x => x.Key == _routeB.Routes[1].Key);
 | 
			
		||||
 | 
			
		||||
            fc.Routes.ShouldContain(x => x.UpstreamHost == _routeA.Routes[0].UpstreamHost);
 | 
			
		||||
            fc.Routes.ShouldContain(x => x.UpstreamHost == _routeB.Routes[0].UpstreamHost);
 | 
			
		||||
            fc.Routes.ShouldContain(x => x.UpstreamHost == _routeB.Routes[1].UpstreamHost);
 | 
			
		||||
 | 
			
		||||
            fc.Aggregates.Count.ShouldBe(_aggregate.Aggregates.Count);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void NotContainsEnvSpecificConfig()
 | 
			
		||||
        {
 | 
			
		||||
            var fc = (FileConfiguration)_configRoot.Get(typeof(FileConfiguration));
 | 
			
		||||
            fc.Routes.ShouldNotContain(x => x.DownstreamScheme == _envSpecific.Routes[0].DownstreamScheme);
 | 
			
		||||
            fc.Routes.ShouldNotContain(x => x.DownstreamPathTemplate == _envSpecific.Routes[0].DownstreamPathTemplate);
 | 
			
		||||
            fc.Routes.ShouldNotContain(x => x.Key == _envSpecific.Routes[0].Key);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenTheBaseUrl(string baseUrl)
 | 
			
		||||
        {
 | 
			
		||||
#pragma warning disable CS0618
 | 
			
		||||
            var builder = new ConfigurationBuilder()
 | 
			
		||||
                .AddOcelotBaseUrl(baseUrl);
 | 
			
		||||
#pragma warning restore CS0618
 | 
			
		||||
            _configuration = builder.Build();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WhenIGet(string key)
 | 
			
		||||
        {
 | 
			
		||||
            _result = _configuration.GetValue(key, "");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheResultIs(string expected)
 | 
			
		||||
        {
 | 
			
		||||
            _result.ShouldBe(expected);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,403 +1,403 @@
 | 
			
		||||
namespace Ocelot.UnitTests.DependencyInjection
 | 
			
		||||
{
 | 
			
		||||
    using Microsoft.AspNetCore.Hosting;
 | 
			
		||||
    using Microsoft.Extensions.Configuration;
 | 
			
		||||
    using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
    using Moq;
 | 
			
		||||
    using Ocelot.Configuration.Setter;
 | 
			
		||||
    using Ocelot.DependencyInjection;
 | 
			
		||||
    using Ocelot.Infrastructure;
 | 
			
		||||
    using Ocelot.Multiplexer;
 | 
			
		||||
    using Ocelot.Requester;
 | 
			
		||||
    using Ocelot.UnitTests.Requester;
 | 
			
		||||
    using Shouldly;
 | 
			
		||||
    using System;
 | 
			
		||||
    using System.Collections.Generic;
 | 
			
		||||
    using System.Linq;
 | 
			
		||||
    using System.Net.Http;
 | 
			
		||||
    using System.Reflection;
 | 
			
		||||
    using Microsoft.AspNetCore.Http;
 | 
			
		||||
    using TestStack.BDDfy;
 | 
			
		||||
    using Xunit;
 | 
			
		||||
namespace Ocelot.UnitTests.DependencyInjection
 | 
			
		||||
{
 | 
			
		||||
    using Microsoft.AspNetCore.Hosting;
 | 
			
		||||
    using Microsoft.Extensions.Configuration;
 | 
			
		||||
    using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
    using Moq;
 | 
			
		||||
    using Ocelot.Configuration.Setter;
 | 
			
		||||
    using Ocelot.DependencyInjection;
 | 
			
		||||
    using Ocelot.Infrastructure;
 | 
			
		||||
    using Ocelot.Multiplexer;
 | 
			
		||||
    using Ocelot.Requester;
 | 
			
		||||
    using Ocelot.UnitTests.Requester;
 | 
			
		||||
    using Shouldly;
 | 
			
		||||
    using System;
 | 
			
		||||
    using System.Collections.Generic;
 | 
			
		||||
    using System.Linq;
 | 
			
		||||
    using System.Net.Http;
 | 
			
		||||
    using System.Reflection;
 | 
			
		||||
    using Microsoft.AspNetCore.Http;
 | 
			
		||||
    using TestStack.BDDfy;
 | 
			
		||||
    using Xunit;
 | 
			
		||||
    using System.Threading.Tasks;
 | 
			
		||||
    using Ocelot.LoadBalancer.LoadBalancers;
 | 
			
		||||
    using Ocelot.Responses;
 | 
			
		||||
    using Ocelot.Values;
 | 
			
		||||
    using static Ocelot.UnitTests.Multiplexing.UserDefinedResponseAggregatorTests;
 | 
			
		||||
 | 
			
		||||
    public class OcelotBuilderTests
 | 
			
		||||
    {
 | 
			
		||||
        private readonly IServiceCollection _services;
 | 
			
		||||
        private IServiceProvider _serviceProvider;
 | 
			
		||||
        private readonly IConfiguration _configRoot;
 | 
			
		||||
        private IOcelotBuilder _ocelotBuilder;
 | 
			
		||||
        private readonly int _maxRetries;
 | 
			
		||||
        private Exception _ex;
 | 
			
		||||
 | 
			
		||||
        public OcelotBuilderTests()
 | 
			
		||||
        {
 | 
			
		||||
            _configRoot = new ConfigurationRoot(new List<IConfigurationProvider>());
 | 
			
		||||
            _services = new ServiceCollection();
 | 
			
		||||
            _services.AddSingleton<IWebHostEnvironment>(GetHostingEnvironment());
 | 
			
		||||
            _services.AddSingleton(_configRoot);
 | 
			
		||||
            _maxRetries = 100;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private IWebHostEnvironment GetHostingEnvironment()
 | 
			
		||||
        {
 | 
			
		||||
            var environment = new Mock<IWebHostEnvironment>();
 | 
			
		||||
            environment
 | 
			
		||||
                .Setup(e => e.ApplicationName)
 | 
			
		||||
                .Returns(typeof(OcelotBuilderTests).GetTypeInfo().Assembly.GetName().Name);
 | 
			
		||||
 | 
			
		||||
            return environment.Object;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_add_specific_delegating_handlers_transient()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => WhenISetUpOcelotServices())
 | 
			
		||||
                .When(x => AddSpecificTransientDelegatingHandler<FakeDelegatingHandler>())
 | 
			
		||||
                .And(x => AddSpecificTransientDelegatingHandler<FakeDelegatingHandlerTwo>())
 | 
			
		||||
                .Then(x => ThenTheProviderIsRegisteredAndReturnsSpecificHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
 | 
			
		||||
                .And(x => ThenTheSpecificHandlersAreTransient())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_add_type_specific_delegating_handlers_transient()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => WhenISetUpOcelotServices())
 | 
			
		||||
                .When(x => AddTypeSpecificTransientDelegatingHandler(typeof(FakeDelegatingHandler)))
 | 
			
		||||
                .And(x => AddTypeSpecificTransientDelegatingHandler(typeof(FakeDelegatingHandlerTwo)))
 | 
			
		||||
                .Then(x => ThenTheProviderIsRegisteredAndReturnsSpecificHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
 | 
			
		||||
                .And(x => ThenTheSpecificHandlersAreTransient())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_add_global_delegating_handlers_transient()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => WhenISetUpOcelotServices())
 | 
			
		||||
                .When(x => AddTransientGlobalDelegatingHandler<FakeDelegatingHandler>())
 | 
			
		||||
                .And(x => AddTransientGlobalDelegatingHandler<FakeDelegatingHandlerTwo>())
 | 
			
		||||
                .Then(x => ThenTheProviderIsRegisteredAndReturnsHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
 | 
			
		||||
                .And(x => ThenTheGlobalHandlersAreTransient())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_add_global_type_delegating_handlers_transient()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => WhenISetUpOcelotServices())
 | 
			
		||||
                .When(x => AddTransientGlobalDelegatingHandler<FakeDelegatingHandler>())
 | 
			
		||||
                .And(x => AddTransientGlobalDelegatingHandler<FakeDelegatingHandlerTwo>())
 | 
			
		||||
                .Then(x => ThenTheProviderIsRegisteredAndReturnsHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
 | 
			
		||||
                .And(x => ThenTheGlobalHandlersAreTransient())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_set_up_services()
 | 
			
		||||
        {
 | 
			
		||||
            this.When(x => WhenISetUpOcelotServices())
 | 
			
		||||
                .Then(x => ThenAnExceptionIsntThrown())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_return_ocelot_builder()
 | 
			
		||||
        {
 | 
			
		||||
            this.When(x => WhenISetUpOcelotServices())
 | 
			
		||||
                .Then(x => ThenAnOcelotBuilderIsReturned())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_use_logger_factory()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => WhenISetUpOcelotServices())
 | 
			
		||||
                .When(x => WhenIValidateScopes())
 | 
			
		||||
                .When(x => WhenIAccessLoggerFactory())
 | 
			
		||||
                .Then(x => ThenAnExceptionIsntThrown())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_set_up_without_passing_in_config()
 | 
			
		||||
        {
 | 
			
		||||
            this.When(x => WhenISetUpOcelotServicesWithoutConfig())
 | 
			
		||||
                .Then(x => ThenAnExceptionIsntThrown())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_add_singleton_defined_aggregators()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => WhenISetUpOcelotServices())
 | 
			
		||||
                .When(x => AddSingletonDefinedAggregator<TestDefinedAggregator>())
 | 
			
		||||
                .When(x => AddSingletonDefinedAggregator<TestDefinedAggregator>())
 | 
			
		||||
                .Then(x => ThenTheProviderIsRegisteredAndReturnsSpecificAggregators<TestDefinedAggregator, TestDefinedAggregator>())
 | 
			
		||||
                .And(x => ThenTheAggregatorsAreSingleton<TestDefinedAggregator, TestDefinedAggregator>())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_add_transient_defined_aggregators()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => WhenISetUpOcelotServices())
 | 
			
		||||
                .When(x => AddTransientDefinedAggregator<TestDefinedAggregator>())
 | 
			
		||||
                .When(x => AddTransientDefinedAggregator<TestDefinedAggregator>())
 | 
			
		||||
                .Then(x => ThenTheProviderIsRegisteredAndReturnsSpecificAggregators<TestDefinedAggregator, TestDefinedAggregator>())
 | 
			
		||||
                .And(x => ThenTheAggregatorsAreTransient<TestDefinedAggregator, TestDefinedAggregator>())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_add_custom_load_balancer_creators_by_default_ctor()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => WhenISetUpOcelotServices())
 | 
			
		||||
                .When(x => _ocelotBuilder.AddCustomLoadBalancer<FakeCustomLoadBalancer>())
 | 
			
		||||
                .Then(x => ThenTheProviderIsRegisteredAndReturnsBothBuiltInAndCustomLoadBalancerCreators())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_add_custom_load_balancer_creators_by_factory_method()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => WhenISetUpOcelotServices())
 | 
			
		||||
                .When(x => _ocelotBuilder.AddCustomLoadBalancer(() => new FakeCustomLoadBalancer()))
 | 
			
		||||
                .Then(x => ThenTheProviderIsRegisteredAndReturnsBothBuiltInAndCustomLoadBalancerCreators())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_add_custom_load_balancer_creators_by_di_factory_method()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => WhenISetUpOcelotServices())
 | 
			
		||||
                .When(x => _ocelotBuilder.AddCustomLoadBalancer(provider => new FakeCustomLoadBalancer()))
 | 
			
		||||
                .Then(x => ThenTheProviderIsRegisteredAndReturnsBothBuiltInAndCustomLoadBalancerCreators())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_add_custom_load_balancer_creators_by_factory_method_with_arguments()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => WhenISetUpOcelotServices())
 | 
			
		||||
                .When(x => _ocelotBuilder.AddCustomLoadBalancer((reroute, discoveryProvider) => new FakeCustomLoadBalancer()))
 | 
			
		||||
                .Then(x => ThenTheProviderIsRegisteredAndReturnsBothBuiltInAndCustomLoadBalancerCreators())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_replace_iplaceholder()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.WhenISetUpOcelotServices())
 | 
			
		||||
                .When(x => AddConfigPlaceholders())
 | 
			
		||||
                .Then(x => ThenAnExceptionIsntThrown())
 | 
			
		||||
                .And(x => ThenTheIPlaceholderInstanceIsReplaced())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_add_custom_load_balancer_creators()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => WhenISetUpOcelotServices())
 | 
			
		||||
                .When(x => _ocelotBuilder.AddCustomLoadBalancer((provider, reroute, discoveryProvider) => new FakeCustomLoadBalancer()))
 | 
			
		||||
                .Then(x => ThenTheProviderIsRegisteredAndReturnsBothBuiltInAndCustomLoadBalancerCreators())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void AddSingletonDefinedAggregator<T>()
 | 
			
		||||
            where T : class, IDefinedAggregator
 | 
			
		||||
        {
 | 
			
		||||
            _ocelotBuilder.AddSingletonDefinedAggregator<T>();
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        private void AddTransientDefinedAggregator<T>()
 | 
			
		||||
            where T : class, IDefinedAggregator
 | 
			
		||||
        {
 | 
			
		||||
            _ocelotBuilder.AddTransientDefinedAggregator<T>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void AddConfigPlaceholders()
 | 
			
		||||
        {
 | 
			
		||||
            _ocelotBuilder.AddConfigPlaceholders();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheSpecificHandlersAreTransient()
 | 
			
		||||
        {
 | 
			
		||||
            var handlers = _serviceProvider.GetServices<DelegatingHandler>().ToList();
 | 
			
		||||
            var first = handlers[0];
 | 
			
		||||
            handlers = _serviceProvider.GetServices<DelegatingHandler>().ToList();
 | 
			
		||||
            var second = handlers[0];
 | 
			
		||||
            first.ShouldNotBe(second);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheGlobalHandlersAreTransient()
 | 
			
		||||
        {
 | 
			
		||||
            var handlers = _serviceProvider.GetServices<GlobalDelegatingHandler>().ToList();
 | 
			
		||||
            var first = handlers[0].DelegatingHandler;
 | 
			
		||||
            handlers = _serviceProvider.GetServices<GlobalDelegatingHandler>().ToList();
 | 
			
		||||
            var second = handlers[0].DelegatingHandler;
 | 
			
		||||
            first.ShouldNotBe(second);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void AddTransientGlobalDelegatingHandler<T>()
 | 
			
		||||
            where T : DelegatingHandler
 | 
			
		||||
        {
 | 
			
		||||
            _ocelotBuilder.AddDelegatingHandler<T>(true);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void AddSpecificTransientDelegatingHandler<T>()
 | 
			
		||||
            where T : DelegatingHandler
 | 
			
		||||
        {
 | 
			
		||||
            _ocelotBuilder.AddDelegatingHandler<T>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void AddTypeTransientGlobalDelegatingHandler(Type type)
 | 
			
		||||
        {
 | 
			
		||||
            _ocelotBuilder.AddDelegatingHandler(type, true);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void AddTypeSpecificTransientDelegatingHandler(Type type)
 | 
			
		||||
        {
 | 
			
		||||
            _ocelotBuilder.AddDelegatingHandler(type);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheProviderIsRegisteredAndReturnsHandlers<TOne, TWo>()
 | 
			
		||||
        {
 | 
			
		||||
            _serviceProvider = _services.BuildServiceProvider();
 | 
			
		||||
            var handlers = _serviceProvider.GetServices<GlobalDelegatingHandler>().ToList();
 | 
			
		||||
            handlers[0].DelegatingHandler.ShouldBeOfType<TOne>();
 | 
			
		||||
            handlers[1].DelegatingHandler.ShouldBeOfType<TWo>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheProviderIsRegisteredAndReturnsSpecificHandlers<TOne, TWo>()
 | 
			
		||||
        {
 | 
			
		||||
            _serviceProvider = _services.BuildServiceProvider();
 | 
			
		||||
            var handlers = _serviceProvider.GetServices<DelegatingHandler>().ToList();
 | 
			
		||||
            handlers[0].ShouldBeOfType<TOne>();
 | 
			
		||||
            handlers[1].ShouldBeOfType<TWo>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheProviderIsRegisteredAndReturnsSpecificAggregators<TOne, TWo>()
 | 
			
		||||
        {
 | 
			
		||||
            _serviceProvider = _services.BuildServiceProvider();
 | 
			
		||||
            var handlers = _serviceProvider.GetServices<IDefinedAggregator>().ToList();
 | 
			
		||||
            handlers[0].ShouldBeOfType<TOne>();
 | 
			
		||||
            handlers[1].ShouldBeOfType<TWo>();
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        private void ThenTheProviderIsRegisteredAndReturnsBothBuiltInAndCustomLoadBalancerCreators()
 | 
			
		||||
        {
 | 
			
		||||
            _serviceProvider = _services.BuildServiceProvider();
 | 
			
		||||
            var creators = _serviceProvider.GetServices<ILoadBalancerCreator>().ToList();
 | 
			
		||||
            creators.Count(c => c.GetType() == typeof(NoLoadBalancerCreator)).ShouldBe(1);
 | 
			
		||||
            creators.Count(c => c.GetType() == typeof(RoundRobinCreator)).ShouldBe(1);
 | 
			
		||||
            creators.Count(c => c.GetType() == typeof(CookieStickySessionsCreator)).ShouldBe(1);
 | 
			
		||||
            creators.Count(c => c.GetType() == typeof(LeastConnectionCreator)).ShouldBe(1);
 | 
			
		||||
            creators.Count(c => c.GetType() == typeof(DelegateInvokingLoadBalancerCreator<FakeCustomLoadBalancer>)).ShouldBe(1);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheAggregatorsAreTransient<TOne, TWo>()
 | 
			
		||||
        {
 | 
			
		||||
            var aggregators = _serviceProvider.GetServices<IDefinedAggregator>().ToList();
 | 
			
		||||
            var first = aggregators[0];
 | 
			
		||||
            aggregators = _serviceProvider.GetServices<IDefinedAggregator>().ToList();
 | 
			
		||||
            var second = aggregators[0];
 | 
			
		||||
            first.ShouldNotBe(second);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheAggregatorsAreSingleton<TOne, TWo>()
 | 
			
		||||
        {
 | 
			
		||||
            var aggregators = _serviceProvider.GetServices<IDefinedAggregator>().ToList();
 | 
			
		||||
            var first = aggregators[0];
 | 
			
		||||
            aggregators = _serviceProvider.GetServices<IDefinedAggregator>().ToList();
 | 
			
		||||
            var second = aggregators[0];
 | 
			
		||||
            first.ShouldBe(second);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenAnOcelotBuilderIsReturned()
 | 
			
		||||
        {
 | 
			
		||||
            _ocelotBuilder.ShouldBeOfType<OcelotBuilder>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheIPlaceholderInstanceIsReplaced()
 | 
			
		||||
        {
 | 
			
		||||
            _serviceProvider = _services.BuildServiceProvider();
 | 
			
		||||
            var placeholders = _serviceProvider.GetService<IPlaceholders>();
 | 
			
		||||
            placeholders.ShouldBeOfType<ConfigAwarePlaceholders>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WhenISetUpOcelotServices()
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                _ocelotBuilder = _services.AddOcelot(_configRoot);
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception e)
 | 
			
		||||
            {
 | 
			
		||||
                _ex = e;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WhenISetUpOcelotServicesWithoutConfig()
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                _ocelotBuilder = _services.AddOcelot();
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception e)
 | 
			
		||||
            {
 | 
			
		||||
                _ex = e;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WhenIAccessLoggerFactory()
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                _serviceProvider = _services.BuildServiceProvider();
 | 
			
		||||
                var logger = _serviceProvider.GetService<IFileConfigurationSetter>();
 | 
			
		||||
                logger.ShouldNotBeNull();
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception e)
 | 
			
		||||
            {
 | 
			
		||||
                _ex = e;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WhenIValidateScopes()
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                _serviceProvider = _services.BuildServiceProvider(new ServiceProviderOptions { ValidateScopes = true });
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception e)
 | 
			
		||||
            {
 | 
			
		||||
                _ex = e;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenAnExceptionIsntThrown()
 | 
			
		||||
        {
 | 
			
		||||
            _ex.ShouldBeNull();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private class FakeCustomLoadBalancer : ILoadBalancer
 | 
			
		||||
        {
 | 
			
		||||
            public Task<Response<ServiceHostAndPort>> Lease(HttpContext httpContext)
 | 
			
		||||
            {
 | 
			
		||||
                // Not relevant for these tests
 | 
			
		||||
                throw new NotImplementedException();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            public void Release(ServiceHostAndPort hostAndPort)
 | 
			
		||||
            {
 | 
			
		||||
                // Not relevant for these tests
 | 
			
		||||
                throw new NotImplementedException();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
    public class OcelotBuilderTests
 | 
			
		||||
    {
 | 
			
		||||
        private readonly IServiceCollection _services;
 | 
			
		||||
        private IServiceProvider _serviceProvider;
 | 
			
		||||
        private readonly IConfiguration _configRoot;
 | 
			
		||||
        private IOcelotBuilder _ocelotBuilder;
 | 
			
		||||
        private readonly int _maxRetries;
 | 
			
		||||
        private Exception _ex;
 | 
			
		||||
 | 
			
		||||
        public OcelotBuilderTests()
 | 
			
		||||
        {
 | 
			
		||||
            _configRoot = new ConfigurationRoot(new List<IConfigurationProvider>());
 | 
			
		||||
            _services = new ServiceCollection();
 | 
			
		||||
            _services.AddSingleton<IWebHostEnvironment>(GetHostingEnvironment());
 | 
			
		||||
            _services.AddSingleton(_configRoot);
 | 
			
		||||
            _maxRetries = 100;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private IWebHostEnvironment GetHostingEnvironment()
 | 
			
		||||
        {
 | 
			
		||||
            var environment = new Mock<IWebHostEnvironment>();
 | 
			
		||||
            environment
 | 
			
		||||
                .Setup(e => e.ApplicationName)
 | 
			
		||||
                .Returns(typeof(OcelotBuilderTests).GetTypeInfo().Assembly.GetName().Name);
 | 
			
		||||
 | 
			
		||||
            return environment.Object;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_add_specific_delegating_handlers_transient()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => WhenISetUpOcelotServices())
 | 
			
		||||
                .When(x => AddSpecificTransientDelegatingHandler<FakeDelegatingHandler>())
 | 
			
		||||
                .And(x => AddSpecificTransientDelegatingHandler<FakeDelegatingHandlerTwo>())
 | 
			
		||||
                .Then(x => ThenTheProviderIsRegisteredAndReturnsSpecificHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
 | 
			
		||||
                .And(x => ThenTheSpecificHandlersAreTransient())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_add_type_specific_delegating_handlers_transient()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => WhenISetUpOcelotServices())
 | 
			
		||||
                .When(x => AddTypeSpecificTransientDelegatingHandler(typeof(FakeDelegatingHandler)))
 | 
			
		||||
                .And(x => AddTypeSpecificTransientDelegatingHandler(typeof(FakeDelegatingHandlerTwo)))
 | 
			
		||||
                .Then(x => ThenTheProviderIsRegisteredAndReturnsSpecificHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
 | 
			
		||||
                .And(x => ThenTheSpecificHandlersAreTransient())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_add_global_delegating_handlers_transient()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => WhenISetUpOcelotServices())
 | 
			
		||||
                .When(x => AddTransientGlobalDelegatingHandler<FakeDelegatingHandler>())
 | 
			
		||||
                .And(x => AddTransientGlobalDelegatingHandler<FakeDelegatingHandlerTwo>())
 | 
			
		||||
                .Then(x => ThenTheProviderIsRegisteredAndReturnsHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
 | 
			
		||||
                .And(x => ThenTheGlobalHandlersAreTransient())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_add_global_type_delegating_handlers_transient()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => WhenISetUpOcelotServices())
 | 
			
		||||
                .When(x => AddTransientGlobalDelegatingHandler<FakeDelegatingHandler>())
 | 
			
		||||
                .And(x => AddTransientGlobalDelegatingHandler<FakeDelegatingHandlerTwo>())
 | 
			
		||||
                .Then(x => ThenTheProviderIsRegisteredAndReturnsHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
 | 
			
		||||
                .And(x => ThenTheGlobalHandlersAreTransient())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_set_up_services()
 | 
			
		||||
        {
 | 
			
		||||
            this.When(x => WhenISetUpOcelotServices())
 | 
			
		||||
                .Then(x => ThenAnExceptionIsntThrown())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_return_ocelot_builder()
 | 
			
		||||
        {
 | 
			
		||||
            this.When(x => WhenISetUpOcelotServices())
 | 
			
		||||
                .Then(x => ThenAnOcelotBuilderIsReturned())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_use_logger_factory()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => WhenISetUpOcelotServices())
 | 
			
		||||
                .When(x => WhenIValidateScopes())
 | 
			
		||||
                .When(x => WhenIAccessLoggerFactory())
 | 
			
		||||
                .Then(x => ThenAnExceptionIsntThrown())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_set_up_without_passing_in_config()
 | 
			
		||||
        {
 | 
			
		||||
            this.When(x => WhenISetUpOcelotServicesWithoutConfig())
 | 
			
		||||
                .Then(x => ThenAnExceptionIsntThrown())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_add_singleton_defined_aggregators()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => WhenISetUpOcelotServices())
 | 
			
		||||
                .When(x => AddSingletonDefinedAggregator<TestDefinedAggregator>())
 | 
			
		||||
                .When(x => AddSingletonDefinedAggregator<TestDefinedAggregator>())
 | 
			
		||||
                .Then(x => ThenTheProviderIsRegisteredAndReturnsSpecificAggregators<TestDefinedAggregator, TestDefinedAggregator>())
 | 
			
		||||
                .And(x => ThenTheAggregatorsAreSingleton<TestDefinedAggregator, TestDefinedAggregator>())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_add_transient_defined_aggregators()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => WhenISetUpOcelotServices())
 | 
			
		||||
                .When(x => AddTransientDefinedAggregator<TestDefinedAggregator>())
 | 
			
		||||
                .When(x => AddTransientDefinedAggregator<TestDefinedAggregator>())
 | 
			
		||||
                .Then(x => ThenTheProviderIsRegisteredAndReturnsSpecificAggregators<TestDefinedAggregator, TestDefinedAggregator>())
 | 
			
		||||
                .And(x => ThenTheAggregatorsAreTransient<TestDefinedAggregator, TestDefinedAggregator>())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_add_custom_load_balancer_creators_by_default_ctor()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => WhenISetUpOcelotServices())
 | 
			
		||||
                .When(x => _ocelotBuilder.AddCustomLoadBalancer<FakeCustomLoadBalancer>())
 | 
			
		||||
                .Then(x => ThenTheProviderIsRegisteredAndReturnsBothBuiltInAndCustomLoadBalancerCreators())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_add_custom_load_balancer_creators_by_factory_method()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => WhenISetUpOcelotServices())
 | 
			
		||||
                .When(x => _ocelotBuilder.AddCustomLoadBalancer(() => new FakeCustomLoadBalancer()))
 | 
			
		||||
                .Then(x => ThenTheProviderIsRegisteredAndReturnsBothBuiltInAndCustomLoadBalancerCreators())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_add_custom_load_balancer_creators_by_di_factory_method()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => WhenISetUpOcelotServices())
 | 
			
		||||
                .When(x => _ocelotBuilder.AddCustomLoadBalancer(provider => new FakeCustomLoadBalancer()))
 | 
			
		||||
                .Then(x => ThenTheProviderIsRegisteredAndReturnsBothBuiltInAndCustomLoadBalancerCreators())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_add_custom_load_balancer_creators_by_factory_method_with_arguments()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => WhenISetUpOcelotServices())
 | 
			
		||||
                .When(x => _ocelotBuilder.AddCustomLoadBalancer((route, discoveryProvider) => new FakeCustomLoadBalancer()))
 | 
			
		||||
                .Then(x => ThenTheProviderIsRegisteredAndReturnsBothBuiltInAndCustomLoadBalancerCreators())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_replace_iplaceholder()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.WhenISetUpOcelotServices())
 | 
			
		||||
                .When(x => AddConfigPlaceholders())
 | 
			
		||||
                .Then(x => ThenAnExceptionIsntThrown())
 | 
			
		||||
                .And(x => ThenTheIPlaceholderInstanceIsReplaced())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_add_custom_load_balancer_creators()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => WhenISetUpOcelotServices())
 | 
			
		||||
                .When(x => _ocelotBuilder.AddCustomLoadBalancer((provider, route, discoveryProvider) => new FakeCustomLoadBalancer()))
 | 
			
		||||
                .Then(x => ThenTheProviderIsRegisteredAndReturnsBothBuiltInAndCustomLoadBalancerCreators())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void AddSingletonDefinedAggregator<T>()
 | 
			
		||||
            where T : class, IDefinedAggregator
 | 
			
		||||
        {
 | 
			
		||||
            _ocelotBuilder.AddSingletonDefinedAggregator<T>();
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        private void AddTransientDefinedAggregator<T>()
 | 
			
		||||
            where T : class, IDefinedAggregator
 | 
			
		||||
        {
 | 
			
		||||
            _ocelotBuilder.AddTransientDefinedAggregator<T>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void AddConfigPlaceholders()
 | 
			
		||||
        {
 | 
			
		||||
            _ocelotBuilder.AddConfigPlaceholders();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheSpecificHandlersAreTransient()
 | 
			
		||||
        {
 | 
			
		||||
            var handlers = _serviceProvider.GetServices<DelegatingHandler>().ToList();
 | 
			
		||||
            var first = handlers[0];
 | 
			
		||||
            handlers = _serviceProvider.GetServices<DelegatingHandler>().ToList();
 | 
			
		||||
            var second = handlers[0];
 | 
			
		||||
            first.ShouldNotBe(second);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheGlobalHandlersAreTransient()
 | 
			
		||||
        {
 | 
			
		||||
            var handlers = _serviceProvider.GetServices<GlobalDelegatingHandler>().ToList();
 | 
			
		||||
            var first = handlers[0].DelegatingHandler;
 | 
			
		||||
            handlers = _serviceProvider.GetServices<GlobalDelegatingHandler>().ToList();
 | 
			
		||||
            var second = handlers[0].DelegatingHandler;
 | 
			
		||||
            first.ShouldNotBe(second);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void AddTransientGlobalDelegatingHandler<T>()
 | 
			
		||||
            where T : DelegatingHandler
 | 
			
		||||
        {
 | 
			
		||||
            _ocelotBuilder.AddDelegatingHandler<T>(true);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void AddSpecificTransientDelegatingHandler<T>()
 | 
			
		||||
            where T : DelegatingHandler
 | 
			
		||||
        {
 | 
			
		||||
            _ocelotBuilder.AddDelegatingHandler<T>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void AddTypeTransientGlobalDelegatingHandler(Type type)
 | 
			
		||||
        {
 | 
			
		||||
            _ocelotBuilder.AddDelegatingHandler(type, true);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void AddTypeSpecificTransientDelegatingHandler(Type type)
 | 
			
		||||
        {
 | 
			
		||||
            _ocelotBuilder.AddDelegatingHandler(type);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheProviderIsRegisteredAndReturnsHandlers<TOne, TWo>()
 | 
			
		||||
        {
 | 
			
		||||
            _serviceProvider = _services.BuildServiceProvider();
 | 
			
		||||
            var handlers = _serviceProvider.GetServices<GlobalDelegatingHandler>().ToList();
 | 
			
		||||
            handlers[0].DelegatingHandler.ShouldBeOfType<TOne>();
 | 
			
		||||
            handlers[1].DelegatingHandler.ShouldBeOfType<TWo>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheProviderIsRegisteredAndReturnsSpecificHandlers<TOne, TWo>()
 | 
			
		||||
        {
 | 
			
		||||
            _serviceProvider = _services.BuildServiceProvider();
 | 
			
		||||
            var handlers = _serviceProvider.GetServices<DelegatingHandler>().ToList();
 | 
			
		||||
            handlers[0].ShouldBeOfType<TOne>();
 | 
			
		||||
            handlers[1].ShouldBeOfType<TWo>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheProviderIsRegisteredAndReturnsSpecificAggregators<TOne, TWo>()
 | 
			
		||||
        {
 | 
			
		||||
            _serviceProvider = _services.BuildServiceProvider();
 | 
			
		||||
            var handlers = _serviceProvider.GetServices<IDefinedAggregator>().ToList();
 | 
			
		||||
            handlers[0].ShouldBeOfType<TOne>();
 | 
			
		||||
            handlers[1].ShouldBeOfType<TWo>();
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        private void ThenTheProviderIsRegisteredAndReturnsBothBuiltInAndCustomLoadBalancerCreators()
 | 
			
		||||
        {
 | 
			
		||||
            _serviceProvider = _services.BuildServiceProvider();
 | 
			
		||||
            var creators = _serviceProvider.GetServices<ILoadBalancerCreator>().ToList();
 | 
			
		||||
            creators.Count(c => c.GetType() == typeof(NoLoadBalancerCreator)).ShouldBe(1);
 | 
			
		||||
            creators.Count(c => c.GetType() == typeof(RoundRobinCreator)).ShouldBe(1);
 | 
			
		||||
            creators.Count(c => c.GetType() == typeof(CookieStickySessionsCreator)).ShouldBe(1);
 | 
			
		||||
            creators.Count(c => c.GetType() == typeof(LeastConnectionCreator)).ShouldBe(1);
 | 
			
		||||
            creators.Count(c => c.GetType() == typeof(DelegateInvokingLoadBalancerCreator<FakeCustomLoadBalancer>)).ShouldBe(1);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheAggregatorsAreTransient<TOne, TWo>()
 | 
			
		||||
        {
 | 
			
		||||
            var aggregators = _serviceProvider.GetServices<IDefinedAggregator>().ToList();
 | 
			
		||||
            var first = aggregators[0];
 | 
			
		||||
            aggregators = _serviceProvider.GetServices<IDefinedAggregator>().ToList();
 | 
			
		||||
            var second = aggregators[0];
 | 
			
		||||
            first.ShouldNotBe(second);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheAggregatorsAreSingleton<TOne, TWo>()
 | 
			
		||||
        {
 | 
			
		||||
            var aggregators = _serviceProvider.GetServices<IDefinedAggregator>().ToList();
 | 
			
		||||
            var first = aggregators[0];
 | 
			
		||||
            aggregators = _serviceProvider.GetServices<IDefinedAggregator>().ToList();
 | 
			
		||||
            var second = aggregators[0];
 | 
			
		||||
            first.ShouldBe(second);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenAnOcelotBuilderIsReturned()
 | 
			
		||||
        {
 | 
			
		||||
            _ocelotBuilder.ShouldBeOfType<OcelotBuilder>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheIPlaceholderInstanceIsReplaced()
 | 
			
		||||
        {
 | 
			
		||||
            _serviceProvider = _services.BuildServiceProvider();
 | 
			
		||||
            var placeholders = _serviceProvider.GetService<IPlaceholders>();
 | 
			
		||||
            placeholders.ShouldBeOfType<ConfigAwarePlaceholders>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WhenISetUpOcelotServices()
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                _ocelotBuilder = _services.AddOcelot(_configRoot);
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception e)
 | 
			
		||||
            {
 | 
			
		||||
                _ex = e;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WhenISetUpOcelotServicesWithoutConfig()
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                _ocelotBuilder = _services.AddOcelot();
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception e)
 | 
			
		||||
            {
 | 
			
		||||
                _ex = e;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WhenIAccessLoggerFactory()
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                _serviceProvider = _services.BuildServiceProvider();
 | 
			
		||||
                var logger = _serviceProvider.GetService<IFileConfigurationSetter>();
 | 
			
		||||
                logger.ShouldNotBeNull();
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception e)
 | 
			
		||||
            {
 | 
			
		||||
                _ex = e;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WhenIValidateScopes()
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                _serviceProvider = _services.BuildServiceProvider(new ServiceProviderOptions { ValidateScopes = true });
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception e)
 | 
			
		||||
            {
 | 
			
		||||
                _ex = e;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenAnExceptionIsntThrown()
 | 
			
		||||
        {
 | 
			
		||||
            _ex.ShouldBeNull();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private class FakeCustomLoadBalancer : ILoadBalancer
 | 
			
		||||
        {
 | 
			
		||||
            public Task<Response<ServiceHostAndPort>> Lease(HttpContext httpContext)
 | 
			
		||||
            {
 | 
			
		||||
                // Not relevant for these tests
 | 
			
		||||
                throw new NotImplementedException();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            public void Release(ServiceHostAndPort hostAndPort)
 | 
			
		||||
            {
 | 
			
		||||
                // Not relevant for these tests
 | 
			
		||||
                throw new NotImplementedException();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user