|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Aspire.Hosting.ApplicationModel;
using Aspire.Hosting.Utils;
namespace Aspire.Hosting.Yarp.Tests;
public class YarpClusterTests(ITestOutputHelper testOutputHelper)
{
[Fact]
public void Create_YarpCluster_From_Raw_Strings()
{
var cluster = new YarpCluster("raw_cluster", "http://localhost:5000", "https://localhost:5001");
Assert.Equal("http://localhost:5000", cluster.Targets[0]);
Assert.Equal("https://localhost:5001", cluster.Targets[1]);
}
[Fact]
public void Create_YarpCluster_From_Endpoints_With_Names()
{
using var builder = TestDistributedApplicationBuilder.Create(testOutputHelper);
var resource = builder.AddResource(new TestResource("ServiceA"))
.WithHttpEndpoint(name: "testendpoint")
.WithHttpsEndpoint(name: "anotherendpoint");
var httpEndpoint = resource.GetEndpoint("testendpoint");
var httpsEndpoint = resource.GetEndpoint("anotherendpoint");
var httpCluster = new YarpCluster(httpEndpoint);
Assert.Equal("http://_testendpoint.ServiceA", httpCluster.Targets[0]);
var httpsCluster = new YarpCluster(httpsEndpoint);
Assert.Equal("https://_anotherendpoint.ServiceA", httpsCluster.Targets[0]);
}
[Fact]
public void Create_YarpCluster_From_Endpoints_Without_Names()
{
using var builder = TestDistributedApplicationBuilder.Create(testOutputHelper);
var resource = builder.AddResource(new TestResource("ServiceC"))
.WithHttpEndpoint()
.WithHttpsEndpoint();
var httpEndpoint = resource.GetEndpoint("http");
var httpsEndpoint = resource.GetEndpoint("https");
var httpCluster = new YarpCluster(httpEndpoint);
Assert.Equal("http://_http.ServiceC", httpCluster.Targets[0]);
var httpsCluster = new YarpCluster(httpsEndpoint);
Assert.Equal("https://_https.ServiceC", httpsCluster.Targets[0]);
}
[Fact]
public void Create_YarpCluster_From_Resource_With_One_Endpoint()
{
using var builder = TestDistributedApplicationBuilder.Create(testOutputHelper);
var httpService = builder.AddResource(new TestResource("ServiceC"))
.WithHttpEndpoint()
.WithHttpEndpoint(name: "grpc");
var httpCluster = new YarpCluster(httpService.Resource);
Assert.Equal($"http://ServiceC", httpCluster.Targets[0]);
var httpsService = builder.AddResource(new TestResource("ServiceD"))
.WithHttpsEndpoint()
.WithHttpsEndpoint(name: "grpc");
var httpsCluster = new YarpCluster(httpsService.Resource);
Assert.Equal($"https://ServiceD", httpsCluster.Targets[0]);
}
[Fact]
public void Create_YarpCluster_From_Resource_With_Both_Endpoints()
{
using var builder = TestDistributedApplicationBuilder.Create(testOutputHelper);
var serviceA = builder.AddResource(new TestResource("ServiceA"))
.WithHttpEndpoint()
.WithHttpsEndpoint();
var clusterA = new YarpCluster(serviceA.Resource);
Assert.Equal($"https+http://ServiceA", clusterA.Targets[0]);
}
[Fact]
public void AddCluster_WithStringDestination_CreatesCluster()
{
using var builder = TestDistributedApplicationBuilder.Create(testOutputHelper);
var yarp = builder.AddYarp("gateway");
yarp.WithConfiguration(config =>
{
var cluster = config.AddCluster("test-cluster", (object)"http://localhost:5000");
Assert.NotNull(cluster);
Assert.Single(cluster.Targets);
Assert.Equal("http://localhost:5000", cluster.Targets[0]);
});
}
[Fact]
public void AddCluster_WithUriDestination_CreatesCluster()
{
using var builder = TestDistributedApplicationBuilder.Create(testOutputHelper);
var yarp = builder.AddYarp("gateway");
yarp.WithConfiguration(config =>
{
var uri = new Uri("https://example.com:8080");
var cluster = config.AddCluster("test-cluster", (object)uri);
Assert.NotNull(cluster);
Assert.Single(cluster.Targets);
Assert.Equal(uri, cluster.Targets[0]);
});
}
[Fact]
public void AddCluster_WithObjectArrayDestinations_CreatesCluster()
{
using var builder = TestDistributedApplicationBuilder.Create(testOutputHelper);
var yarp = builder.AddYarp("gateway");
yarp.WithConfiguration(config =>
{
var destinations = new object[] { "http://localhost:5000", new Uri("http://localhost:5001") };
var cluster = config.AddCluster("test-cluster", destinations);
Assert.NotNull(cluster);
Assert.Equal(2, cluster.Targets.Length);
Assert.Equal("http://localhost:5000", cluster.Targets[0]);
});
}
[Fact]
public void AddCluster_WithNullObjectDestination_ThrowsArgumentException()
{
using var builder = TestDistributedApplicationBuilder.Create(testOutputHelper);
var yarp = builder.AddYarp("gateway");
yarp.WithConfiguration(config =>
{
var ex = Assert.Throws<ArgumentException>(() => config.AddCluster("test-cluster", (object)null!));
Assert.Contains("IValueProvider, string, or Uri", ex.Message);
});
}
[Fact]
public void AddCluster_WithNullObjectArrayDestinations_ThrowsArgumentNullException()
{
using var builder = TestDistributedApplicationBuilder.Create(testOutputHelper);
var yarp = builder.AddYarp("gateway");
yarp.WithConfiguration(config =>
{
Assert.Throws<ArgumentNullException>(() => config.AddCluster("test-cluster", (object[])null!));
});
}
[Fact]
public void AddCluster_WithEmptyDestinationsArray_ThrowsArgumentException()
{
using var builder = TestDistributedApplicationBuilder.Create(testOutputHelper);
var yarp = builder.AddYarp("gateway");
yarp.WithConfiguration(config =>
{
Assert.Throws<ArgumentException>(() => config.AddCluster("test-cluster", Array.Empty<object>()));
});
}
[Fact]
public void AddCluster_WithInvalidDestinationType_ThrowsArgumentException()
{
using var builder = TestDistributedApplicationBuilder.Create(testOutputHelper);
var yarp = builder.AddYarp("gateway");
yarp.WithConfiguration(config =>
{
var ex = Assert.Throws<ArgumentException>(() => config.AddCluster("test-cluster", new object[] { 123 }));
Assert.Contains("IValueProvider, string, or Uri", ex.Message);
});
}
[Fact]
public void AddCluster_WithMixedValidTypes_CreatesCluster()
{
using var builder = TestDistributedApplicationBuilder.Create(testOutputHelper);
var yarp = builder.AddYarp("gateway");
yarp.WithConfiguration(config =>
{
var uri = new Uri("https://example.com");
var refExpr = ReferenceExpression.Create($"http://localhost:5000");
var cluster = config.AddCluster("test-cluster", new object[] { "http://localhost:5000", uri, refExpr });
Assert.NotNull(cluster);
Assert.Equal(3, cluster.Targets.Length);
});
}
[Fact]
public void AddCluster_WithObjectOverload_ValidatesTypes()
{
using var builder = TestDistributedApplicationBuilder.Create(testOutputHelper);
var yarp = builder.AddYarp("gateway");
yarp.WithConfiguration(config =>
{
// Valid object type (string)
var cluster = config.AddCluster("test-cluster", (object)"http://localhost:5000");
Assert.NotNull(cluster);
Assert.Single(cluster.Targets);
// Invalid object type
var ex = Assert.Throws<ArgumentException>(() => config.AddCluster("test-cluster2", (object)123));
Assert.Contains("IValueProvider, string, or Uri", ex.Message);
});
}
private sealed class TestResource(string name) : IResourceWithServiceDiscovery
{
public string Name => name;
public ResourceAnnotationCollection Annotations { get; } = new ResourceAnnotationCollection();
}
}
|