File: ConditionalReferenceExpressionTests.cs
Web Access
Project: src\tests\Aspire.Hosting.Tests\Aspire.Hosting.Tests.csproj (Aspire.Hosting.Tests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Net.Sockets;
 
namespace Aspire.Hosting.Tests;
 
public class ConditionalReferenceExpressionTests
{
    [Fact]
    public async Task GetValueAsync_ReturnsTrueValue_WhenConditionIsTrue()
    {
        var condition = new TestValueProvider(bool.TrueString);
        var whenTrue = ReferenceExpression.Create($",ssl=true");
        var whenFalse = ReferenceExpression.Empty;
 
        var expr = ReferenceExpression.CreateConditional(condition, bool.TrueString, whenTrue, whenFalse);
 
        var value = await expr.GetValueAsync(default);
        Assert.Equal(",ssl=true", value);
    }
 
    [Fact]
    public async Task GetValueAsync_ReturnsFalseValue_WhenConditionIsFalse()
    {
        var condition = new TestValueProvider(bool.FalseString);
        var whenTrue = ReferenceExpression.Create($",ssl=true");
        var whenFalse = ReferenceExpression.Empty;
 
        var expr = ReferenceExpression.CreateConditional(condition, bool.TrueString, whenTrue, whenFalse);
 
        var value = await expr.GetValueAsync(default);
        Assert.Null(value);
    }
 
    [Fact]
    public void ValueExpression_ReturnsManifestParameterReference()
    {
        var condition = new TestValueProvider(bool.TrueString);
        var whenTrue = ReferenceExpression.Create($",ssl=true");
        var whenFalse = ReferenceExpression.Empty;
 
        var expr = ReferenceExpression.CreateConditional(condition, bool.TrueString, whenTrue, whenFalse);
 
        Assert.StartsWith("{cond-", expr.ValueExpression);
        Assert.EndsWith(".connectionString}", expr.ValueExpression);
    }
 
    [Fact]
    public async Task ConditionalReferenceExpression_WorksInReferenceExpressionBuilder()
    {
        var condition = new TestValueProvider(bool.FalseString);
        var whenTrue = ReferenceExpression.Create($",ssl=true");
        var whenFalse = ReferenceExpression.Empty;
 
        var conditional = ReferenceExpression.CreateConditional(condition, bool.TrueString, whenTrue, whenFalse);
 
        var builder = new ReferenceExpressionBuilder();
        builder.AppendLiteral("localhost:6379");
        builder.Append($"{conditional}");
        var expression = builder.Build();
 
        // Before enabling: runtime value does not include TLS
        var valueBefore = await expression.GetValueAsync(new(), default);
        Assert.Equal("localhost:6379", valueBefore);
 
        // After enabling: runtime value includes TLS dynamically
        condition.Value = bool.TrueString;
        var valueAfter = await expression.GetValueAsync(new(), default);
        Assert.Equal("localhost:6379,ssl=true", valueAfter);
    }
 
    [Fact]
    public void References_IncludesConditionAndBranchReferences()
    {
        var resource = new TestResourceWithEndpoints("test");
        var annotation = new EndpointAnnotation(ProtocolType.Tcp, uriScheme: "http", name: "http");
        resource.Annotations.Add(annotation);
        var endpointRef = new EndpointReference(resource, annotation);
 
        var condition = endpointRef.Property(EndpointProperty.TlsEnabled);
        var whenTrue = ReferenceExpression.Create($",ssl=true");
        var whenFalse = ReferenceExpression.Empty;
 
        var expr = ReferenceExpression.CreateConditional(condition, bool.TrueString, whenTrue, whenFalse);
 
        var references = ((IValueWithReferences)expr).References.ToList();
        Assert.Contains(endpointRef, references);
    }
 
    [Fact]
    public void Name_IsAutoGeneratedFromCondition()
    {
        var expr = ReferenceExpression.CreateConditional(new TestValueProvider(bool.TrueString), bool.TrueString, ReferenceExpression.Empty, ReferenceExpression.Empty);
        Assert.StartsWith("cond-", expr.Name);
    }
 
    private sealed class TestResourceWithEndpoints(string name) : Resource(name), IResourceWithEndpoints
    {
    }
 
    private sealed class TestValueProvider(string value) : IValueProvider, IManifestExpressionProvider
    {
        public string Value { get; set; } = value;
 
        public string ValueExpression => "test-condition";
 
        public ValueTask<string?> GetValueAsync(CancellationToken cancellationToken = default)
        {
            return new ValueTask<string?>(Value);
        }
 
        public ValueTask<string?> GetValueAsync(ValueProviderContext context, CancellationToken cancellationToken = default)
        {
            return new ValueTask<string?>(Value);
        }
    }
}
 
public class EndpointPropertyTlsEnabledTests
{
    [Fact]
    public async Task TlsEnabled_ReturnsFalseString_WhenTlsNotEnabled()
    {
        var resource = new TestResourceWithEndpoints("test");
        var annotation = new EndpointAnnotation(ProtocolType.Tcp, uriScheme: "http", name: "tcp");
        resource.Annotations.Add(annotation);
        var endpointRef = new EndpointReference(resource, annotation);
 
        var tlsExpr = endpointRef.Property(EndpointProperty.TlsEnabled);
 
        var value = await tlsExpr.GetValueAsync();
        Assert.Equal(bool.FalseString, value);
    }
 
    [Fact]
    public async Task TlsEnabled_ReturnsTrueString_WhenTlsEnabled()
    {
        var resource = new TestResourceWithEndpoints("test");
        var annotation = new EndpointAnnotation(ProtocolType.Tcp, uriScheme: "https", name: "tcp")
        {
            TlsEnabled = true
        };
        resource.Annotations.Add(annotation);
        var endpointRef = new EndpointReference(resource, annotation);
 
        var tlsExpr = endpointRef.Property(EndpointProperty.TlsEnabled);
 
        var value = await tlsExpr.GetValueAsync();
        Assert.Equal(bool.TrueString, value);
    }
 
    [Fact]
    public void ValueExpression_ReturnsEndpointTlsExpression()
    {
        var resource = new TestResourceWithEndpoints("myresource");
        var annotation = new EndpointAnnotation(ProtocolType.Tcp, uriScheme: "http", name: "tcp");
        resource.Annotations.Add(annotation);
        var endpointRef = new EndpointReference(resource, annotation);
 
        var tlsExpr = endpointRef.Property(EndpointProperty.TlsEnabled);
 
        Assert.Equal("{myresource.bindings.tcp.tlsEnabled}", tlsExpr.ValueExpression);
    }
 
    [Fact]
    public async Task TlsEnabled_ResolvesLazilyFromCurrentState()
    {
        var resource = new TestResourceWithEndpoints("test");
        var annotation = new EndpointAnnotation(ProtocolType.Tcp, uriScheme: "http", name: "tcp");
        resource.Annotations.Add(annotation);
        var endpointRef = new EndpointReference(resource, annotation);
 
        var tlsExpr = endpointRef.Property(EndpointProperty.TlsEnabled);
 
        Assert.Equal(bool.FalseString, await tlsExpr.GetValueAsync());
 
        annotation.TlsEnabled = true;
        Assert.Equal(bool.TrueString, await tlsExpr.GetValueAsync());
    }
 
    private sealed class TestResourceWithEndpoints(string name) : Resource(name), IResourceWithEndpoints
    {
    }
}