167 lines
6.4 KiB
C#
167 lines
6.4 KiB
C#
using FluentAssertions;
|
|
using StellaOps.Router.Gateway.RateLimit;
|
|
using Xunit;
|
|
|
|
namespace StellaOps.Router.Gateway.Tests;
|
|
|
|
public sealed class LimitInheritanceResolverTests
|
|
{
|
|
[Fact]
|
|
public void ResolveEnvironmentTarget_UsesEnvironmentDefaultsWhenNoMicroserviceOverride()
|
|
{
|
|
var config = new RateLimitConfig
|
|
{
|
|
ActivationThresholdPer5Min = 0,
|
|
ForEnvironment = new EnvironmentLimitsConfig
|
|
{
|
|
ValkeyConnection = "localhost:6379",
|
|
ValkeyBucket = "bucket",
|
|
Rules = [new RateLimitRule { PerSeconds = 60, MaxRequests = 600 }],
|
|
}
|
|
}.Validate();
|
|
|
|
var resolver = new LimitInheritanceResolver(config);
|
|
var target = resolver.ResolveEnvironmentTarget("scanner", "/api/scans");
|
|
|
|
target.Enabled.Should().BeTrue();
|
|
target.Kind.Should().Be(RateLimitTargetKind.EnvironmentDefault);
|
|
target.RouteName.Should().BeNull();
|
|
target.TargetKey.Should().Be("scanner");
|
|
target.Rules.Should().ContainSingle();
|
|
target.Rules[0].PerSeconds.Should().Be(60);
|
|
target.Rules[0].MaxRequests.Should().Be(600);
|
|
}
|
|
|
|
[Fact]
|
|
public void ResolveEnvironmentTarget_UsesMicroserviceOverrideWhenPresent()
|
|
{
|
|
var config = new RateLimitConfig
|
|
{
|
|
ActivationThresholdPer5Min = 0,
|
|
ForEnvironment = new EnvironmentLimitsConfig
|
|
{
|
|
ValkeyConnection = "localhost:6379",
|
|
ValkeyBucket = "bucket",
|
|
Rules = [new RateLimitRule { PerSeconds = 60, MaxRequests = 600 }],
|
|
Microservices = new Dictionary<string, MicroserviceLimitsConfig>(StringComparer.OrdinalIgnoreCase)
|
|
{
|
|
["scanner"] = new MicroserviceLimitsConfig
|
|
{
|
|
Rules = [new RateLimitRule { PerSeconds = 10, MaxRequests = 1 }],
|
|
}
|
|
}
|
|
}
|
|
}.Validate();
|
|
|
|
var resolver = new LimitInheritanceResolver(config);
|
|
var target = resolver.ResolveEnvironmentTarget("scanner", "/api/scans");
|
|
|
|
target.Enabled.Should().BeTrue();
|
|
target.Kind.Should().Be(RateLimitTargetKind.Microservice);
|
|
target.RouteName.Should().BeNull();
|
|
target.TargetKey.Should().Be("scanner");
|
|
target.Rules.Should().ContainSingle();
|
|
target.Rules[0].PerSeconds.Should().Be(10);
|
|
target.Rules[0].MaxRequests.Should().Be(1);
|
|
}
|
|
|
|
[Fact]
|
|
public void ResolveEnvironmentTarget_DisablesWhenNoRulesAtAnyLevel()
|
|
{
|
|
var config = new RateLimitConfig
|
|
{
|
|
ActivationThresholdPer5Min = 0,
|
|
ForEnvironment = new EnvironmentLimitsConfig
|
|
{
|
|
ValkeyConnection = "localhost:6379",
|
|
ValkeyBucket = "bucket",
|
|
}
|
|
}.Validate();
|
|
|
|
var resolver = new LimitInheritanceResolver(config);
|
|
var target = resolver.ResolveEnvironmentTarget("scanner", "/api/scans");
|
|
|
|
target.Enabled.Should().BeFalse();
|
|
}
|
|
|
|
[Fact]
|
|
public void ResolveEnvironmentTarget_UsesRouteOverrideWhenPresent()
|
|
{
|
|
var config = new RateLimitConfig
|
|
{
|
|
ActivationThresholdPer5Min = 0,
|
|
ForEnvironment = new EnvironmentLimitsConfig
|
|
{
|
|
ValkeyConnection = "localhost:6379",
|
|
ValkeyBucket = "bucket",
|
|
Rules = [new RateLimitRule { PerSeconds = 60, MaxRequests = 600 }],
|
|
Microservices = new Dictionary<string, MicroserviceLimitsConfig>(StringComparer.OrdinalIgnoreCase)
|
|
{
|
|
["scanner"] = new MicroserviceLimitsConfig
|
|
{
|
|
Rules = [new RateLimitRule { PerSeconds = 60, MaxRequests = 600 }],
|
|
Routes = new Dictionary<string, RouteLimitsConfig>(StringComparer.OrdinalIgnoreCase)
|
|
{
|
|
["scan_submit"] = new RouteLimitsConfig
|
|
{
|
|
Pattern = "/api/scans",
|
|
MatchType = RouteMatchType.Exact,
|
|
Rules = [new RateLimitRule { PerSeconds = 300, MaxRequests = 1 }]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}.Validate();
|
|
|
|
var resolver = new LimitInheritanceResolver(config);
|
|
var target = resolver.ResolveEnvironmentTarget("scanner", "/api/scans");
|
|
|
|
target.Enabled.Should().BeTrue();
|
|
target.Kind.Should().Be(RateLimitTargetKind.Route);
|
|
target.RouteName.Should().Be("scan_submit");
|
|
target.TargetKey.Should().Be("scanner:scan_submit");
|
|
target.Rules.Should().ContainSingle();
|
|
target.Rules[0].PerSeconds.Should().Be(300);
|
|
target.Rules[0].MaxRequests.Should().Be(1);
|
|
}
|
|
|
|
[Fact]
|
|
public void ResolveEnvironmentTarget_DoesNotTreatRouteAsOverrideWhenItHasNoRules()
|
|
{
|
|
var config = new RateLimitConfig
|
|
{
|
|
ActivationThresholdPer5Min = 0,
|
|
ForEnvironment = new EnvironmentLimitsConfig
|
|
{
|
|
ValkeyConnection = "localhost:6379",
|
|
ValkeyBucket = "bucket",
|
|
Rules = [new RateLimitRule { PerSeconds = 60, MaxRequests = 600 }],
|
|
Microservices = new Dictionary<string, MicroserviceLimitsConfig>(StringComparer.OrdinalIgnoreCase)
|
|
{
|
|
["scanner"] = new MicroserviceLimitsConfig
|
|
{
|
|
Rules = [new RateLimitRule { PerSeconds = 60, MaxRequests = 600 }],
|
|
Routes = new Dictionary<string, RouteLimitsConfig>(StringComparer.OrdinalIgnoreCase)
|
|
{
|
|
["named_only"] = new RouteLimitsConfig
|
|
{
|
|
Pattern = "/api/scans",
|
|
MatchType = RouteMatchType.Exact
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}.Validate();
|
|
|
|
var resolver = new LimitInheritanceResolver(config);
|
|
var target = resolver.ResolveEnvironmentTarget("scanner", "/api/scans");
|
|
|
|
target.Enabled.Should().BeTrue();
|
|
target.Kind.Should().Be(RateLimitTargetKind.Microservice);
|
|
target.RouteName.Should().BeNull();
|
|
target.TargetKey.Should().Be("scanner");
|
|
}
|
|
}
|