Exemplo n.º 1
0
        public void EmptyTransforms_AddsDefaults()
        {
            var transformBuilder = CreateTransformBuilder();
            var errorReporter    = new TestConfigErrorReporter();
            var transforms       = new List <IDictionary <string, string> >();

            var valid = transformBuilder.Validate(transforms, "routeId", errorReporter);

            Assert.True(valid);
            Assert.Empty(errorReporter.Errors);

            var results = transformBuilder.Build(transforms);

            Assert.NotNull(results);
            Assert.Null(results.CopyRequestHeaders);
            Assert.Empty(results.ResponseHeaderTransforms);
            Assert.Empty(results.ResponseTrailerTransforms);
            Assert.Empty(results.RequestTransforms);

            Assert.Equal(5, results.RequestHeaderTransforms.Count);
            Assert.IsType <RequestHeaderValueTransform>(results.RequestHeaderTransforms[HeaderNames.Host]);
            Assert.IsType <RequestHeaderXForwardedForTransform>(results.RequestHeaderTransforms[ForwardedHeadersDefaults.XForwardedForHeaderName]);
            Assert.IsType <RequestHeaderXForwardedHostTransform>(results.RequestHeaderTransforms[ForwardedHeadersDefaults.XForwardedHostHeaderName]);
            Assert.IsType <RequestHeaderXForwardedPathBaseTransform>(results.RequestHeaderTransforms["X-Forwarded-PathBase"]);
            Assert.IsType <RequestHeaderXForwardedProtoTransform>(results.RequestHeaderTransforms[ForwardedHeadersDefaults.XForwardedProtoHeaderName]);
        }
Exemplo n.º 2
0
        public void DefaultsCanBeDisabled()
        {
            var transformBuilder = CreateTransformBuilder();
            var errorReporter    = new TestConfigErrorReporter();
            var transforms       = new List <IDictionary <string, string> >()
            {
                new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase)
                {
                    { "RequestHeaderOriginalHost", "true" }
                },
                new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase)
                {
                    { "X-Forwarded", "" }
                },
            };

            var valid = transformBuilder.Validate(transforms, "routeId", errorReporter);

            Assert.True(valid);
            Assert.Empty(errorReporter.Errors);

            var results = transformBuilder.Build(transforms);

            Assert.NotNull(results);
            Assert.Null(results.CopyRequestHeaders);
            Assert.Empty(results.ResponseHeaderTransforms);
            Assert.Empty(results.ResponseTrailerTransforms);
            Assert.Empty(results.RequestTransforms);
            Assert.Empty(results.RequestHeaderTransforms);
        }
Exemplo n.º 3
0
        public async Task BuildConfigAsync_ConfigFilterRouteActionThrows_SkipsRoute()
        {
            var errorReporter = new TestConfigErrorReporter();
            var route1        = new ProxyRoute {
                RouteId = "route1", Match = { Host = "example.com" }, Priority = 1, BackendId = "backend1"
            };
            var route2 = new ProxyRoute {
                RouteId = "route2", Match = { Host = "example2.com" }, Priority = 1, BackendId = "backend2"
            };
            var configBuilder = CreateConfigBuilder(new TestBackendsRepo(), new TestRoutesRepo(new[] { route1, route2 }),
                                                    proxyBuilder =>
            {
                proxyBuilder.AddProxyConfigFilter <BackendAndRouteThrows>();
                proxyBuilder.AddProxyConfigFilter <BackendAndRouteThrows>();
            });

            var result = await configBuilder.BuildConfigAsync(errorReporter, CancellationToken.None);

            // Assert
            Assert.True(result.IsSuccess);
            Assert.NotNull(result.Value);
            Assert.Empty(result.Value.Backends);
            Assert.Empty(result.Value.Routes);
            Assert.Equal(2, errorReporter.Errors.Count);
            Assert.IsType <NotFiniteNumberException>(errorReporter.Errors.First().Exception);
            Assert.IsType <NotFiniteNumberException>(errorReporter.Errors.Skip(1).First().Exception);
        }
        public async Task BuildConfigAsync_ConfigFilterConfiguresCluster_Works()
        {
            var errorReporter = new TestConfigErrorReporter();
            var configBuilder = CreateConfigBuilder(CreateOneCluster(), new TestRoutesRepo(),
                                                    proxyBuilder =>
            {
                proxyBuilder.AddProxyConfigFilter <ClusterAndRouteFilter>();
            });

            var result = await configBuilder.BuildConfigAsync(errorReporter, CancellationToken.None);

            Assert.Empty(errorReporter.Errors);
            Assert.NotNull(result);
            Assert.Single(result.Clusters);
            var cluster = result.Clusters["cluster1"];

            Assert.NotNull(cluster);
            Assert.True(cluster.HealthCheckOptions.Enabled);
            Assert.Equal(TimeSpan.FromSeconds(12), cluster.HealthCheckOptions.Interval);
            Assert.Single(cluster.Destinations);
            var destination = cluster.Destinations["d1"];

            Assert.NotNull(destination);
            Assert.Equal(TestAddress, destination.Address);
        }
Exemplo n.º 5
0
        public async Task BuildConfigAsync_ConfigFilterConfiguresBackend_Works()
        {
            var errorReporter = new TestConfigErrorReporter();
            var configBuilder = CreateConfigBuilder(CreateOneBackend(), new TestRoutesRepo(),
                                                    proxyBuilder =>
            {
                proxyBuilder.AddProxyConfigFilter <BackendAndRouteFilter>();
            });

            var result = await configBuilder.BuildConfigAsync(errorReporter, CancellationToken.None);

            Assert.True(result.IsSuccess);
            Assert.Empty(errorReporter.Errors);
            Assert.NotNull(result.Value);
            Assert.Single(result.Value.Backends);
            var backend = result.Value.Backends["backend1"];

            Assert.NotNull(backend);
            Assert.True(backend.HealthCheckOptions.Enabled);
            Assert.Equal(TimeSpan.FromSeconds(12), backend.HealthCheckOptions.Interval);
            Assert.Single(backend.Endpoints);
            var endpoint = backend.Endpoints["ep1"];

            Assert.NotNull(endpoint);
            Assert.Equal(TestAddress, endpoint.Address);
        }
        public async Task BuildConfigAsync_RouteValidationError_SkipsRoute()
        {
            // Arrange
            var errorReporter = new TestConfigErrorReporter();

            Mock <IBackendsRepo>()
            .Setup(r => r.GetBackendsAsync(It.IsAny <CancellationToken>()))
            .ReturnsAsync(new Dictionary <string, Backend>());

            var route1 = new ProxyRoute {
                RouteId = "route1", Match = { Host = "example.com" }, Priority = 1, BackendId = "backend1"
            };

            Mock <IRoutesRepo>()
            .Setup(r => r.GetRoutesAsync(It.IsAny <CancellationToken>()))
            .ReturnsAsync(new[] { route1 });

            var parsedRoute1 = new ParsedRoute();

            Mock <IRouteValidator>()
            .Setup(r => r.ValidateRoute(parsedRoute1, errorReporter))
            .Returns(false);

            // Act
            var configManager = Create <DynamicConfigBuilder>();
            var result        = await configManager.BuildConfigAsync(errorReporter, CancellationToken.None);

            // Assert
            result.IsSuccess.Should().BeTrue();
            result.Value.Should().NotBeNull();
            result.Value.Backends.Should().BeEmpty();
            result.Value.Routes.Should().BeEmpty();
        }
Exemplo n.º 7
0
        public void UnknownTransforms_Error()
        {
            var transformBuilder = CreateTransformBuilder();
            var errorReporter    = new TestConfigErrorReporter();
            var transforms       = new List <IDictionary <string, string> >()
            {
                new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase) // Unrecognized transform
                {
                    { "string1", "value1" },
                    { "string2", "value2" }
                },
                new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase) // Unrecognized transform
                {
                    { "string3", "value3" },
                    { "string4", "value4" }
                },
            };

            var valid = transformBuilder.Validate(transforms, "routeId", errorReporter);

            Assert.False(valid);
            // All errors reported
            Assert.Equal(2, errorReporter.Errors.Count);
            Assert.Equal("Unknown transform: string1;string2", errorReporter.Errors.First().Message);
            Assert.Equal("Unknown transform: string3;string4", errorReporter.Errors.Skip(1).First().Message);

            var nie = Assert.Throws <NotSupportedException>(() => transformBuilder.Build(transforms));

            // First error reported
            Assert.Equal("string1;string2", nie.Message);
        }
        public async Task BuildConfigAsync_ValidRoute_Works()
        {
            // Arrange
            var errorReporter = new TestConfigErrorReporter();

            Mock <IBackendsRepo>()
            .Setup(r => r.GetBackendsAsync(It.IsAny <CancellationToken>()))
            .ReturnsAsync(new Dictionary <string, Backend>());

            var route1 = new ProxyRoute {
                RouteId = "route1", Match = { Host = "example.com" }, Priority = 1, BackendId = "backend1"
            };

            Mock <IRoutesRepo>()
            .Setup(r => r.GetRoutesAsync(It.IsAny <CancellationToken>()))
            .ReturnsAsync(new[] { route1 });

            Mock <IRouteValidator>()
            .Setup(r => r.ValidateRoute(It.IsAny <ParsedRoute>(), errorReporter))
            .Returns(true);

            // Act
            var configManager = Create <DynamicConfigBuilder>();
            var result        = await configManager.BuildConfigAsync(errorReporter, CancellationToken.None);

            // Assert
            Assert.True(result.IsSuccess);
            Assert.Empty(errorReporter.Errors);
            Assert.NotNull(result.Value);
            Assert.Empty(result.Value.Backends);
            Assert.Single(result.Value.Routes);
            Assert.Same(route1.RouteId, result.Value.Routes[0].RouteId);
        }
Exemplo n.º 9
0
        private (bool IsSuccess, TestConfigErrorReporter ErrorReporter) RunScenario(ParsedRoute parsedRoute)
        {
            var errorReporter = new TestConfigErrorReporter();

            var validator = Create <RouteValidator>();
            var isSuccess = validator.ValidateRoute(parsedRoute, errorReporter);

            return(isSuccess, errorReporter);
        }
Exemplo n.º 10
0
        private (bool IsSuccess, TestConfigErrorReporter ErrorReporter) RunScenario(ParsedRoute parsedRoute)
        {
            var errorReporter = new TestConfigErrorReporter();

            Mock <ITransformBuilder>().Setup(builder
                                             => builder.Validate(It.IsAny <IList <IDictionary <string, string> > >(), It.IsAny <string>(), It.IsAny <IConfigErrorReporter>())).Returns(true);
            var validator = Create <RouteValidator>();
            var isSuccess = validator.ValidateRoute(parsedRoute, errorReporter);

            return(isSuccess, errorReporter);
        }
        public async Task BuildConfigAsync_EmptyInput_Works()
        {
            var errorReporter = new TestConfigErrorReporter();

            var configBuilder = CreateConfigBuilder(new TestClustersRepo(new Dictionary <string, Cluster>()), new TestRoutesRepo(new List <ProxyRoute>()));
            var result        = await configBuilder.BuildConfigAsync(errorReporter, CancellationToken.None);

            Assert.Empty(errorReporter.Errors);
            Assert.NotNull(result);
            Assert.Empty(result.Clusters);
            Assert.Empty(result.Routes);
        }
Exemplo n.º 12
0
        public async Task BuildConfigAsync_NullInput_Works()
        {
            var errorReporter = new TestConfigErrorReporter();
            var configBuilder = CreateConfigBuilder(new TestBackendsRepo(), new TestRoutesRepo());

            var result = await configBuilder.BuildConfigAsync(errorReporter, CancellationToken.None);

            Assert.True(result.IsSuccess);
            Assert.Empty(errorReporter.Errors);
            Assert.NotNull(result.Value);
            Assert.Empty(result.Value.Backends);
            Assert.Empty(result.Value.Routes);
        }
        public async Task BuildConfigAsync_RouteValidationError_SkipsRoute()
        {
            var errorReporter = new TestConfigErrorReporter();
            var route1        = new ProxyRoute {
                RouteId = "route1", Match = { Host = "invalid host name" }, Priority = 1, ClusterId = "cluster1"
            };
            var configBuilder = CreateConfigBuilder(new TestClustersRepo(), new TestRoutesRepo(new[] { route1 }));

            var result = await configBuilder.BuildConfigAsync(errorReporter, CancellationToken.None);

            Assert.NotNull(result);
            Assert.Empty(result.Clusters);
            Assert.Empty(result.Routes);
        }
        public async Task BuildConfigAsync_NullInput_Works()
        {
            // Arrange
            var errorReporter = new TestConfigErrorReporter();

            // Act
            var configManager = Create <DynamicConfigBuilder>();
            var result        = await configManager.BuildConfigAsync(errorReporter, CancellationToken.None);

            // Assert
            Assert.True(result.IsSuccess);
            Assert.Empty(errorReporter.Errors);
            Assert.NotNull(result.Value);
            Assert.Empty(result.Value.Backends);
            Assert.Empty(result.Value.Routes);
        }
        public async Task BuildConfigAsync_ValidRoute_Works()
        {
            var errorReporter = new TestConfigErrorReporter();
            var route1        = new ProxyRoute {
                RouteId = "route1", Match = { Host = "example.com" }, Priority = 1, ClusterId = "cluster1"
            };
            var configBuilder = CreateConfigBuilder(new TestClustersRepo(), new TestRoutesRepo(new[] { route1 }));

            var result = await configBuilder.BuildConfigAsync(errorReporter, CancellationToken.None);

            Assert.Empty(errorReporter.Errors);
            Assert.NotNull(result);
            Assert.Empty(result.Clusters);
            Assert.Single(result.Routes);
            Assert.Same(route1.RouteId, result.Routes[0].RouteId);
        }
        public async Task BuildConfigAsync_NullInput_Works()
        {
            // Arrange
            var errorReporter = new TestConfigErrorReporter();

            // Act
            var configManager = Create <DynamicConfigBuilder>();
            var result        = await configManager.BuildConfigAsync(errorReporter, CancellationToken.None);

            // Assert
            result.IsSuccess.Should().BeTrue();
            errorReporter.Errors.Should().BeEmpty();
            result.Value.Should().NotBeNull();
            result.Value.Backends.Should().BeEmpty();
            result.Value.Routes.Should().BeEmpty();
        }
Exemplo n.º 17
0
        public void Rejects_MissingRouteId(string routeId)
        {
            // Arrange
            var errorReporter = new TestConfigErrorReporter();
            var parsedRoute   = new ParsedRoute {
                RouteId = routeId
            };
            var validator = Create <RouteValidator>();

            // Act
            var isSuccess = validator.ValidateRoute(parsedRoute, errorReporter);

            // Assert
            Assert.False(isSuccess);
            Assert.Contains(errorReporter.Errors, err => err.ErrorCode == ConfigErrors.ParsedRouteMissingId);
        }
        public async Task BuildConfigAsync_OneBackend_Works()
        {
            // Arrange
            const string TestAddress = "https://localhost:123/";

            var errorReporter = new TestConfigErrorReporter();

            Mock <IBackendsRepo>()
            .Setup(r => r.GetBackendsAsync(It.IsAny <CancellationToken>()))
            .ReturnsAsync(new Dictionary <string, Backend>
            {
                {
                    "backend1", new Backend
                    {
                        Endpoints =
                        {
                            { "ep1", new BackendEndpoint {
                                  Address = TestAddress
                              } }
                        }
                    }
                }
            });

            Mock <IRoutesRepo>()
            .Setup(r => r.GetRoutesAsync(It.IsAny <CancellationToken>()))
            .ReturnsAsync(new List <ProxyRoute>());

            // Act
            var configManager = Create <DynamicConfigBuilder>();
            var result        = await configManager.BuildConfigAsync(errorReporter, CancellationToken.None);

            // Assert
            result.IsSuccess.Should().BeTrue();
            errorReporter.Errors.Should().BeEmpty();
            result.Value.Should().NotBeNull();
            result.Value.Backends.Should().HaveCount(1);
            var backend = result.Value.Backends["backend1"];

            backend.Should().NotBeNull();
            backend.Endpoints.Should().HaveCount(1);
            var endpoint = backend.Endpoints["ep1"];

            endpoint.Should().NotBeNull();
            endpoint.Address.Should().Be(TestAddress);
        }
        public async Task BuildConfigAsync_ConfigFilterClusterActionThrows_ClusterSkipped()
        {
            var errorReporter = new TestConfigErrorReporter();
            var configBuilder = CreateConfigBuilder(CreateOneCluster(), new TestRoutesRepo(),
                                                    proxyBuilder =>
            {
                proxyBuilder.AddProxyConfigFilter <ClusterAndRouteThrows>();
                proxyBuilder.AddProxyConfigFilter <ClusterAndRouteThrows>();
            });

            var result = await configBuilder.BuildConfigAsync(errorReporter, CancellationToken.None);

            // Assert
            Assert.NotNull(result);
            Assert.Empty(result.Clusters);
            Assert.NotEmpty(errorReporter.Errors);
            Assert.IsType <NotFiniteNumberException>(errorReporter.Errors.Single().Exception);
        }
Exemplo n.º 20
0
        public async Task BuildConfigAsync_OneBackend_Works()
        {
            var errorReporter = new TestConfigErrorReporter();
            var configBuilder = CreateConfigBuilder(CreateOneBackend(), new TestRoutesRepo());

            var result = await configBuilder.BuildConfigAsync(errorReporter, CancellationToken.None);

            // Assert
            Assert.True(result.IsSuccess);
            Assert.Empty(errorReporter.Errors);
            Assert.NotNull(result.Value);
            Assert.Single(result.Value.Backends);
            var backend = result.Value.Backends["backend1"];

            Assert.NotNull(backend);
            Assert.Single(backend.Endpoints);
            var endpoint = backend.Endpoints["ep1"];

            Assert.NotNull(endpoint);
            Assert.Equal(TestAddress, endpoint.Address);
        }
        public async Task BuildConfigAsync_OneCluster_Works()
        {
            var errorReporter = new TestConfigErrorReporter();
            var configBuilder = CreateConfigBuilder(CreateOneCluster(), new TestRoutesRepo());

            var result = await configBuilder.BuildConfigAsync(errorReporter, CancellationToken.None);

            // Assert
            Assert.Empty(errorReporter.Errors);
            Assert.NotNull(result);
            Assert.Single(result.Clusters);
            var cluster = result.Clusters["cluster1"];

            Assert.NotNull(cluster);
            Assert.Equal("cluster1", cluster.Id);
            Assert.Single(cluster.Destinations);
            var destination = cluster.Destinations["d1"];

            Assert.NotNull(destination);
            Assert.Equal(TestAddress, destination.Address);
        }
Exemplo n.º 22
0
        public void CopyRequestHeader(bool copyRequestHeaders)
        {
            var transformBuilder = CreateTransformBuilder();
            var errorReporter    = new TestConfigErrorReporter();
            var transforms       = new List <IDictionary <string, string> >()
            {
                new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase)
                {
                    { "RequestHeadersCopy", copyRequestHeaders.ToString() }
                }
            };

            var valid = transformBuilder.Validate(transforms, "routeId", errorReporter);

            Assert.True(valid);
            Assert.Empty(errorReporter.Errors);

            var results = transformBuilder.Build(transforms);

            Assert.NotNull(results);
            Assert.Equal(copyRequestHeaders, results.CopyRequestHeaders);
        }
Exemplo n.º 23
0
        public async Task BuildConfigAsync_ConfigFilterRouteActions_Works()
        {
            var errorReporter = new TestConfigErrorReporter();
            var route1        = new ProxyRoute {
                RouteId = "route1", Match = { Host = "example.com" }, Priority = 1, BackendId = "backend1"
            };
            var configBuilder = CreateConfigBuilder(new TestBackendsRepo(), new TestRoutesRepo(new[] { route1 }),
                                                    proxyBuilder =>
            {
                proxyBuilder.AddProxyConfigFilter <BackendAndRouteFilter>();
            });

            var result = await configBuilder.BuildConfigAsync(errorReporter, CancellationToken.None);

            Assert.True(result.IsSuccess);
            Assert.Empty(errorReporter.Errors);
            Assert.NotNull(result.Value);
            Assert.Empty(result.Value.Backends);
            Assert.Single(result.Value.Routes);
            Assert.Same(route1.RouteId, result.Value.Routes[0].RouteId);
            Assert.Equal(12, route1.Priority);
        }
Exemplo n.º 24
0
        public void EmptyTransform_Error()
        {
            var transformBuilder = CreateTransformBuilder();
            var errorReporter    = new TestConfigErrorReporter();
            var transforms       = new List <IDictionary <string, string> >()
            {
                new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase), // Empty
            };

            var valid = transformBuilder.Validate(transforms, "routeId", errorReporter);

            Assert.False(valid);
            Assert.Single(errorReporter.Errors);
            var error = errorReporter.Errors.First();

            Assert.Equal("routeId", error.ElementId);
            Assert.Equal("Unknown transform: ", error.Message);

            var nie = Assert.Throws <NotSupportedException>(() => transformBuilder.Build(transforms));

            Assert.Equal("", nie.Message);
        }
        public async Task BuildConfigAsync_ConfigFilterRouteActions_CanFixBrokenRoute()
        {
            var errorReporter = new TestConfigErrorReporter();
            var route1        = new ProxyRoute {
                RouteId = "route1", Match = { Host = "invalid host name" }, Priority = 1, ClusterId = "cluster1"
            };
            var configBuilder = CreateConfigBuilder(new TestClustersRepo(), new TestRoutesRepo(new[] { route1 }),
                                                    proxyBuilder =>
            {
                proxyBuilder.AddProxyConfigFilter <FixRouteHostFilter>();
            });

            var result = await configBuilder.BuildConfigAsync(errorReporter, CancellationToken.None);

            Assert.Empty(errorReporter.Errors);
            Assert.NotNull(result);
            Assert.Empty(result.Clusters);
            Assert.Single(result.Routes);
            var builtRoute = result.Routes[0];

            Assert.Same(route1.RouteId, builtRoute.RouteId);
            Assert.Equal("example.com", builtRoute.Host);
        }
Exemplo n.º 26
0
        public void RequestHeader(bool append, string value)
        {
            var transformBuilder = CreateTransformBuilder();
            var errorReporter    = new TestConfigErrorReporter();
            var transforms       = new List <IDictionary <string, string> >()
            {
                new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase)
                {
                    { "RequestHeader", "HeaderName" },
                    { append ? "Append" : "Set", value }
                }
            };

            var valid = transformBuilder.Validate(transforms, "routeId", errorReporter);

            Assert.True(valid);
            Assert.Empty(errorReporter.Errors);

            var results = transformBuilder.Build(transforms);

            Assert.IsType <RequestHeaderValueTransform>(results.RequestHeaderTransforms["heaDerName"]);
            // TODO: How to check Append/Set and the value?
        }
        public async Task BuildConfigAsync_EmptyInput_Works()
        {
            // Arrange
            var errorReporter = new TestConfigErrorReporter();

            Mock <IBackendsRepo>()
            .Setup(r => r.GetBackendsAsync(It.IsAny <CancellationToken>()))
            .ReturnsAsync(new Dictionary <string, Backend>());

            Mock <IRoutesRepo>()
            .Setup(r => r.GetRoutesAsync(It.IsAny <CancellationToken>()))
            .ReturnsAsync(new List <ProxyRoute>());

            // Act
            var configManager = Create <DynamicConfigBuilder>();
            var result        = await configManager.BuildConfigAsync(errorReporter, CancellationToken.None);

            // Assert
            result.IsSuccess.Should().BeTrue();
            errorReporter.Errors.Should().BeEmpty();
            result.Value.Should().NotBeNull();
            result.Value.Backends.Should().BeEmpty();
            result.Value.Routes.Should().BeEmpty();
        }
Exemplo n.º 28
0
        public async Task ApplyConfigurationsAsync_OneClusterOneDestinationOneRoute_Works()
        {
            // Arrange
            const string TestAddress = "https://localhost:123/";

            var cluster = new Cluster
            {
                Destinations =
                {
                    { "d1", new Destination {
                          Address = TestAddress
                      } }
                }
            };
            var route = new ParsedRoute
            {
                RouteId   = "route1",
                ClusterId = "cluster1",
            };

            var dynamicConfigRoot = new DynamicConfigRoot
            {
                Clusters = new Dictionary <string, Cluster> {
                    { "cluster1", cluster }
                },
                Routes = new[] { route },
            };

            Mock <IDynamicConfigBuilder>()
            .Setup(d => d.BuildConfigAsync(It.IsAny <IConfigErrorReporter>(), It.IsAny <CancellationToken>()))
            .ReturnsAsync(dynamicConfigRoot);

            var errorReporter = new TestConfigErrorReporter();
            var proxyManager  = Create <ReverseProxyConfigManager>();

            // Act
            await proxyManager.ApplyConfigurationsAsync(errorReporter, CancellationToken.None);

            // Assert

            var actualClusters = _clusterManager.GetItems();

            Assert.Single(actualClusters);
            Assert.Equal("cluster1", actualClusters[0].ClusterId);
            Assert.NotNull(actualClusters[0].DestinationManager);
            Assert.NotNull(actualClusters[0].Config.Value);

            var actualDestinations = actualClusters[0].DestinationManager.GetItems();

            Assert.Single(actualDestinations);
            Assert.Equal("d1", actualDestinations[0].DestinationId);
            Assert.NotNull(actualDestinations[0].Config.Value);
            Assert.Equal(TestAddress, actualDestinations[0].Config.Value.Address);

            var actualRoutes = _routeManager.GetItems();

            Assert.Single(actualRoutes);
            Assert.Equal("route1", actualRoutes[0].RouteId);
            Assert.NotNull(actualRoutes[0].Config.Value);
            Assert.Same(actualClusters[0], actualRoutes[0].Config.Value.Cluster);
        }
        public async Task ApplyConfigurationsAsync_OneBackendOneEndpointOneRoute_Works()
        {
            // Arrange
            const string TestAddress = "https://localhost:123/";

            var backend = new Backend
            {
                Endpoints =
                {
                    { "ep1", new BackendEndpoint {
                          Address = TestAddress
                      } }
                }
            };
            var route = new ParsedRoute
            {
                RouteId   = "route1",
                BackendId = "backend1",
            };

            var dynamicConfigRoot = new DynamicConfigRoot
            {
                Backends = new Dictionary <string, Backend> {
                    { "backend1", backend }
                },
                Routes = new[] { route },
            };

            Mock <IDynamicConfigBuilder>()
            .Setup(d => d.BuildConfigAsync(It.IsAny <IConfigErrorReporter>(), It.IsAny <CancellationToken>()))
            .ReturnsAsync(Result.Success(dynamicConfigRoot));

            var errorReporter = new TestConfigErrorReporter();
            var proxyManager  = Create <ReverseProxyConfigManager>();

            // Act
            var result = await proxyManager.ApplyConfigurationsAsync(errorReporter, CancellationToken.None);

            // Assert
            Assert.True(result);

            var actualBackends = _backendManager.GetItems();

            Assert.Single(actualBackends);
            Assert.Equal("backend1", actualBackends[0].BackendId);
            Assert.NotNull(actualBackends[0].EndpointManager);
            Assert.NotNull(actualBackends[0].Config.Value);

            var actualEndpoints = actualBackends[0].EndpointManager.GetItems();

            Assert.Single(actualEndpoints);
            Assert.Equal("ep1", actualEndpoints[0].EndpointId);
            Assert.NotNull(actualEndpoints[0].Config.Value);
            Assert.Equal(TestAddress, actualEndpoints[0].Config.Value.Address);

            var actualRoutes = _routeManager.GetItems();

            Assert.Single(actualRoutes);
            Assert.Equal("route1", actualRoutes[0].RouteId);
            Assert.NotNull(actualRoutes[0].Config.Value);
            Assert.Same(actualBackends[0], actualRoutes[0].Config.Value.BackendOrNull);
        }