File: Resilience\HttpClientBuilderExtensionsTests.BySelector.cs
Web Access
Project: src\test\Libraries\Microsoft.Extensions.Http.Resilience.Tests\Microsoft.Extensions.Http.Resilience.Tests.csproj (Microsoft.Extensions.Http.Resilience.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;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Http.Resilience.Internal;
using Microsoft.Extensions.Http.Resilience.Test.Helpers;
using Moq;
using Polly;
using Polly.Registry;
using Xunit;
 
namespace Microsoft.Extensions.Http.Resilience.Test;
 
public sealed partial class HttpClientBuilderExtensionsTests
{
    [InlineData(true, "https://dummy:21/path", "https://dummy:21")]
    [InlineData(true, "https://dummy", "https://dummy")]
    [InlineData(false, "https://dummy:21/path", "https://dummy:21")]
    [InlineData(false, "https://dummy", "https://dummy")]
    [Theory]
    public void SelectPipelineByAuthority_Ok(bool standardResilience, string url, string expectedPipelineKey)
    {
        _builder.Services.AddFakeRedaction();
 
        var pipelineName = standardResilience ?
            _builder.AddStandardResilienceHandler().SelectPipelineByAuthority().PipelineName :
            _builder
                .AddResilienceHandler("dummy", builder => builder.AddTimeout(TimeSpan.FromSeconds(1)))
                .SelectPipelineByAuthority().PipelineName;
 
        var provider = _builder.Services.BuildServiceProvider().GetPipelineKeyProvider(pipelineName)!;
 
        using var request = new HttpRequestMessage(HttpMethod.Head, url);
 
        var key = provider(request);
 
        Assert.Equal(expectedPipelineKey, key);
        Assert.Same(provider(request), provider(request));
    }
 
    [Fact]
    public void SelectPipelineByAuthority_Ok_NullURL_Throws()
    {
        _builder.Services.AddFakeRedaction();
        var builder = _builder.AddResilienceHandler("dummy", builder => builder.AddTimeout(TimeSpan.FromSeconds(1))).SelectPipelineByAuthority();
        var provider = PipelineKeyProviderHelper.GetPipelineKeyProvider(builder.Services.BuildServiceProvider(), builder.PipelineName)!;
 
        using var request = new HttpRequestMessage();
 
        Assert.Throws<InvalidOperationException>(() => provider(request));
    }
 
    [InlineData(true, "https://dummy:21/path", "https://")]
    [InlineData(true, "https://dummy", "https://")]
    [InlineData(false, "https://dummy:21/path", "https://")]
    [InlineData(false, "https://dummy", "https://")]
    [Theory]
    public void SelectPipelineBy_Ok(bool standardResilience, string url, string expectedPipelineKey)
    {
        _builder.Services.AddFakeRedaction();
 
        string? pipelineName = null;
 
        if (standardResilience)
        {
            pipelineName = _builder
                .AddResilienceHandler("dummy", builder => builder.AddTimeout(TimeSpan.FromSeconds(1)))
                .SelectPipelineBy(_ => r => r.RequestUri!.GetLeftPart(UriPartial.Scheme)).PipelineName;
        }
        else
        {
            pipelineName = _builder
                .AddStandardResilienceHandler()
                .SelectPipelineBy(_ => r => r.RequestUri!.GetLeftPart(UriPartial.Scheme)).PipelineName;
        }
 
        var provider = _builder.Services.BuildServiceProvider().GetPipelineKeyProvider(pipelineName)!;
 
        using var request = new HttpRequestMessage(HttpMethod.Head, url);
 
        var key = provider(request);
 
        Assert.Equal(expectedPipelineKey, key);
        Assert.NotSame(provider(request), provider(request));
    }
 
    [Theory]
#if NET6_0_OR_GREATER
    [InlineData(true, "https://dummy:21/path", "https://dummy:21", true)]
    [InlineData(true, "https://dummy123", "https://dummy123", true)]
    [InlineData(false, "https://dummy:21/path", "https://dummy:21", true)]
    [InlineData(false, "https://dummy123", "https://dummy123", true)]
    [InlineData(true, "https://dummy:21/path", "https://dummy:21", false)]
    [InlineData(true, "https://dummy123", "https://dummy123", false)]
    [InlineData(false, "https://dummy:21/path", "https://dummy:21", false)]
    [InlineData(false, "https://dummy123", "https://dummy123", false)]
#else
    [InlineData(true, "https://dummy:21/path", "https://dummy:21")]
    [InlineData(true, "https://dummy123", "https://dummy123")]
    [InlineData(false, "https://dummy:21/path", "https://dummy:21")]
    [InlineData(false, "https://dummy123", "https://dummy123")]
#endif
    public async Task SelectPipelineByAuthority_EnsureResiliencePipelineProviderCall(
        bool standardResilience, string url, string expectedPipelineKey, bool asynchronous = true)
    {
        var provider = new Mock<ResiliencePipelineProvider<HttpKey>>(MockBehavior.Strict);
 
        _builder.Services.AddFakeRedaction();
        _builder.Services.TryAddSingleton(provider.Object);
        string? pipelineName = null;
        if (standardResilience)
        {
            pipelineName = _builder
                .AddResilienceHandler("dummy", builder => builder.AddTimeout(TimeSpan.FromSeconds(1)))
                .SelectPipelineByAuthority().PipelineName;
        }
        else
        {
            pipelineName = _builder
                .AddStandardResilienceHandler()
                .SelectPipelineByAuthority().PipelineName;
        }
 
        _builder.AddHttpMessageHandler(() => new TestHandlerStub(HttpStatusCode.OK));
 
        provider
            .Setup(p => p.GetPipeline<HttpResponseMessage>(new HttpKey(pipelineName, expectedPipelineKey)))
            .Returns(ResiliencePipeline<HttpResponseMessage>.Empty);
 
        var client = CreateClient();
        await SendRequest(client, url, asynchronous);
 
        provider.VerifyAll();
    }
}