|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.ConcurrencyLimiter.Tests;
public static class TestUtils
{
#pragma warning disable CS0618 // Type or member is obsolete
public static ConcurrencyLimiterMiddleware CreateTestMiddleware(IQueuePolicy queue = null, RequestDelegate onRejected = null, RequestDelegate next = null)
{
var options = Options.Create(new ConcurrencyLimiterOptions
{
OnRejected = onRejected ?? (context => Task.CompletedTask),
});
return new ConcurrencyLimiterMiddleware(
next: next ?? (context => Task.CompletedTask),
loggerFactory: NullLoggerFactory.Instance,
queue: queue ?? CreateQueuePolicy(1, 0),
options: options
);
}
public static ConcurrencyLimiterMiddleware CreateTestMiddleware_QueuePolicy(int maxConcurrentRequests, int requestQueueLimit, RequestDelegate onRejected = null, RequestDelegate next = null)
{
return CreateTestMiddleware(
queue: CreateQueuePolicy(maxConcurrentRequests, requestQueueLimit),
onRejected: onRejected,
next: next
);
}
public static ConcurrencyLimiterMiddleware CreateTestMiddleware_StackPolicy(int maxConcurrentRequests, int requestQueueLimit, RequestDelegate onRejected = null, RequestDelegate next = null)
{
return CreateTestMiddleware(
queue: CreateStackPolicy(maxConcurrentRequests, requestQueueLimit),
onRejected: onRejected,
next: next
);
}
internal static StackPolicy CreateStackPolicy(int maxConcurrentRequests, int requestsQueuelimit = 100)
{
var options = Options.Create(new QueuePolicyOptions
{
MaxConcurrentRequests = maxConcurrentRequests,
RequestQueueLimit = requestsQueuelimit
});
return new StackPolicy(options);
}
internal static QueuePolicy CreateQueuePolicy(int maxConcurrentRequests, int requestQueueLimit = 100)
{
var options = Options.Create(new QueuePolicyOptions
{
MaxConcurrentRequests = maxConcurrentRequests,
RequestQueueLimit = requestQueueLimit
});
return new QueuePolicy(options);
}
#pragma warning restore CS0618 // Type or member is obsolete
}
internal class TestQueue : IQueuePolicy
{
private Func<TestQueue, Task<bool>> _onTryEnter { get; }
private Action _onExit { get; }
private int _queuedRequests;
public int QueuedRequests { get => _queuedRequests; }
public TestQueue(Func<TestQueue, Task<bool>> onTryEnter, Action onExit = null)
{
_onTryEnter = onTryEnter;
_onExit = onExit ?? (() => { });
}
public TestQueue(Func<TestQueue, bool> onTryEnter, Action onExit = null) :
this(state => Task.FromResult(onTryEnter(state))
, onExit)
{ }
public async ValueTask<bool> TryEnterAsync()
{
Interlocked.Increment(ref _queuedRequests);
var result = await _onTryEnter(this);
Interlocked.Decrement(ref _queuedRequests);
return result;
}
public void OnExit()
{
_onExit();
}
public static TestQueue AlwaysFalse =
new TestQueue((_) => false);
public static TestQueue AlwaysTrue =
new TestQueue((_) => true);
public static TestQueue AlwaysBlock =
new TestQueue(async (_) =>
{
await new SemaphoreSlim(0).WaitAsync();
return false;
});
}
|