Refactor code structure and optimize performance across multiple modules
This commit is contained in:
@@ -8,11 +8,13 @@ using StellaOps.Router.Gateway.State;
|
||||
using StellaOps.Router.Transport.InMemory;
|
||||
using Xunit;
|
||||
|
||||
using StellaOps.TestKit;
|
||||
namespace StellaOps.Router.Gateway.Tests;
|
||||
|
||||
public sealed class ConnectionManagerTests
|
||||
{
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task StartAsync_WhenHelloInvalid_RejectsAndClosesChannel()
|
||||
{
|
||||
var (manager, server, registry, routingState) = Create();
|
||||
@@ -59,7 +61,8 @@ public sealed class ConnectionManagerTests
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task WhenClientDisconnects_RemovesFromRoutingState()
|
||||
{
|
||||
var (manager, server, registry, routingState) = Create();
|
||||
@@ -102,7 +105,8 @@ public sealed class ConnectionManagerTests
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task WhenMultipleClientsConnect_TracksAndCleansIndependently()
|
||||
{
|
||||
var (manager, server, registry, routingState) = Create();
|
||||
|
||||
@@ -6,11 +6,13 @@ using StellaOps.Router.Gateway.Configuration;
|
||||
using StellaOps.Router.Gateway.Routing;
|
||||
using Xunit;
|
||||
|
||||
using StellaOps.TestKit;
|
||||
namespace StellaOps.Router.Gateway.Tests;
|
||||
|
||||
public sealed class DefaultRoutingPluginTests
|
||||
{
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task ChooseInstanceAsync_WhenNoCandidates_ReturnsNull()
|
||||
{
|
||||
var plugin = CreatePlugin(gatewayRegion: "eu1");
|
||||
@@ -38,7 +40,8 @@ public sealed class DefaultRoutingPluginTests
|
||||
decision.Should().BeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task ChooseInstanceAsync_WhenRequestedVersionDoesNotMatch_ReturnsNull()
|
||||
{
|
||||
var plugin = CreatePlugin(
|
||||
@@ -63,7 +66,8 @@ public sealed class DefaultRoutingPluginTests
|
||||
decision.Should().BeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task ChooseInstanceAsync_PrefersHealthyOverDegraded()
|
||||
{
|
||||
var plugin = CreatePlugin(
|
||||
@@ -93,7 +97,8 @@ public sealed class DefaultRoutingPluginTests
|
||||
decision!.Connection.ConnectionId.Should().Be("inv-healthy");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task ChooseInstanceAsync_PrefersLocalRegionOverRemote()
|
||||
{
|
||||
var plugin = CreatePlugin(
|
||||
@@ -120,7 +125,8 @@ public sealed class DefaultRoutingPluginTests
|
||||
decision!.Connection.ConnectionId.Should().Be("inv-eu1");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task ChooseInstanceAsync_WhenNoLocal_UsesNeighborRegion()
|
||||
{
|
||||
var plugin = CreatePlugin(
|
||||
@@ -148,7 +154,8 @@ public sealed class DefaultRoutingPluginTests
|
||||
decision!.Connection.ConnectionId.Should().Be("inv-eu2");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task ChooseInstanceAsync_WhenTied_UsesRoundRobin()
|
||||
{
|
||||
var plugin = CreatePlugin(
|
||||
|
||||
@@ -4,11 +4,13 @@ using StellaOps.Router.Common.Models;
|
||||
using StellaOps.Router.Gateway.State;
|
||||
using Xunit;
|
||||
|
||||
using StellaOps.TestKit;
|
||||
namespace StellaOps.Router.Gateway.Tests;
|
||||
|
||||
public sealed class InMemoryRoutingStateTests
|
||||
{
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void ResolveEndpoint_WhenExactMatch_ReturnsEndpointDescriptor()
|
||||
{
|
||||
var routingState = new InMemoryRoutingState();
|
||||
@@ -33,7 +35,8 @@ public sealed class InMemoryRoutingStateTests
|
||||
resolved.Path.Should().Be("/items");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void ResolveEndpoint_WhenTemplateMatch_ReturnsEndpointDescriptor()
|
||||
{
|
||||
var routingState = new InMemoryRoutingState();
|
||||
@@ -55,7 +58,8 @@ public sealed class InMemoryRoutingStateTests
|
||||
resolved!.Path.Should().Be("/items/{sku}");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void RemoveConnection_RemovesEndpointsFromIndex()
|
||||
{
|
||||
var routingState = new InMemoryRoutingState();
|
||||
@@ -78,7 +82,8 @@ public sealed class InMemoryRoutingStateTests
|
||||
routingState.GetAllConnections().Should().BeEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void GetConnectionsFor_FiltersByServiceAndVersion()
|
||||
{
|
||||
var routingState = new InMemoryRoutingState();
|
||||
|
||||
@@ -2,11 +2,13 @@ using FluentAssertions;
|
||||
using StellaOps.Router.Gateway.RateLimit;
|
||||
using Xunit;
|
||||
|
||||
using StellaOps.TestKit;
|
||||
namespace StellaOps.Router.Gateway.Tests;
|
||||
|
||||
public sealed class InMemoryValkeyRateLimitStoreTests
|
||||
{
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task IncrementAndCheckAsync_UsesSmallestWindowAsRepresentativeWhenAllowed()
|
||||
{
|
||||
var store = new InMemoryValkeyRateLimitStore();
|
||||
@@ -25,7 +27,8 @@ public sealed class InMemoryValkeyRateLimitStoreTests
|
||||
result.RetryAfterSeconds.Should().Be(0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task IncrementAndCheckAsync_DeniesWhenLimitExceeded()
|
||||
{
|
||||
var store = new InMemoryValkeyRateLimitStore();
|
||||
|
||||
@@ -2,11 +2,13 @@ using FluentAssertions;
|
||||
using StellaOps.Router.Gateway.RateLimit;
|
||||
using Xunit;
|
||||
|
||||
using StellaOps.TestKit;
|
||||
namespace StellaOps.Router.Gateway.Tests;
|
||||
|
||||
public sealed class InstanceRateLimiterTests
|
||||
{
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void TryAcquire_ReportsMostConstrainedRuleWhenAllowed()
|
||||
{
|
||||
var limiter = new InstanceRateLimiter(
|
||||
@@ -24,7 +26,8 @@ public sealed class InstanceRateLimiterTests
|
||||
decision.CurrentCount.Should().Be(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void TryAcquire_DeniesWhenAnyRuleIsExceeded()
|
||||
{
|
||||
var limiter = new InstanceRateLimiter(
|
||||
|
||||
@@ -2,11 +2,13 @@ using FluentAssertions;
|
||||
using StellaOps.Router.Gateway.RateLimit;
|
||||
using Xunit;
|
||||
|
||||
using StellaOps.TestKit;
|
||||
namespace StellaOps.Router.Gateway.Tests;
|
||||
|
||||
public sealed class LimitInheritanceResolverTests
|
||||
{
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void ResolveEnvironmentTarget_UsesEnvironmentDefaultsWhenNoMicroserviceOverride()
|
||||
{
|
||||
var config = new RateLimitConfig
|
||||
@@ -32,7 +34,8 @@ public sealed class LimitInheritanceResolverTests
|
||||
target.Rules[0].MaxRequests.Should().Be(600);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void ResolveEnvironmentTarget_UsesMicroserviceOverrideWhenPresent()
|
||||
{
|
||||
var config = new RateLimitConfig
|
||||
@@ -65,7 +68,8 @@ public sealed class LimitInheritanceResolverTests
|
||||
target.Rules[0].MaxRequests.Should().Be(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void ResolveEnvironmentTarget_DisablesWhenNoRulesAtAnyLevel()
|
||||
{
|
||||
var config = new RateLimitConfig
|
||||
@@ -84,7 +88,8 @@ public sealed class LimitInheritanceResolverTests
|
||||
target.Enabled.Should().BeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void ResolveEnvironmentTarget_UsesRouteOverrideWhenPresent()
|
||||
{
|
||||
var config = new RateLimitConfig
|
||||
@@ -126,7 +131,8 @@ public sealed class LimitInheritanceResolverTests
|
||||
target.Rules[0].MaxRequests.Should().Be(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void ResolveEnvironmentTarget_DoesNotTreatRouteAsOverrideWhenItHasNoRules()
|
||||
{
|
||||
var config = new RateLimitConfig
|
||||
|
||||
@@ -15,11 +15,14 @@ using StellaOps.Router.Gateway.Middleware;
|
||||
using StellaOps.Router.Gateway.State;
|
||||
using Xunit;
|
||||
|
||||
|
||||
using StellaOps.TestKit;
|
||||
namespace StellaOps.Router.Gateway.Tests;
|
||||
|
||||
public sealed class MiddlewareErrorScenarioTests
|
||||
{
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task EndpointResolutionMiddleware_WhenNoEndpoint_Returns404StructuredError()
|
||||
{
|
||||
var context = CreateContext(method: "GET", path: "/missing");
|
||||
@@ -45,7 +48,8 @@ public sealed class MiddlewareErrorScenarioTests
|
||||
body.GetProperty("traceId").GetString().Should().Be("trace-1");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task RoutingDecisionMiddleware_WhenNoInstances_Returns503StructuredError()
|
||||
{
|
||||
var context = CreateContext(method: "GET", path: "/items");
|
||||
@@ -84,7 +88,8 @@ public sealed class MiddlewareErrorScenarioTests
|
||||
body.GetProperty("version").GetString().Should().Be("1.0.0");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task AuthorizationMiddleware_WhenMissingClaim_Returns403StructuredError()
|
||||
{
|
||||
var context = CreateContext(method: "GET", path: "/items");
|
||||
@@ -128,7 +133,8 @@ public sealed class MiddlewareErrorScenarioTests
|
||||
body.GetProperty("details").GetProperty("requiredClaimValue").GetString().Should().Be("admin");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task GlobalErrorHandlerMiddleware_WhenUnhandledException_Returns500StructuredError()
|
||||
{
|
||||
var context = CreateContext(method: "GET", path: "/boom");
|
||||
|
||||
@@ -3,11 +3,13 @@ using Microsoft.Extensions.Configuration;
|
||||
using StellaOps.Router.Gateway.RateLimit;
|
||||
using Xunit;
|
||||
|
||||
using StellaOps.TestKit;
|
||||
namespace StellaOps.Router.Gateway.Tests;
|
||||
|
||||
public sealed class RateLimitConfigTests
|
||||
{
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Load_BindsRoutesAndRules()
|
||||
{
|
||||
var configuration = new ConfigurationBuilder()
|
||||
@@ -41,7 +43,8 @@ public sealed class RateLimitConfigTests
|
||||
route.Rules[0].MaxRequests.Should().Be(50);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Load_ThrowsForInvalidRegexRoute()
|
||||
{
|
||||
var configuration = new ConfigurationBuilder()
|
||||
|
||||
@@ -7,11 +7,14 @@ using StellaOps.Router.Gateway;
|
||||
using StellaOps.Router.Gateway.RateLimit;
|
||||
using Xunit;
|
||||
|
||||
|
||||
using StellaOps.TestKit;
|
||||
namespace StellaOps.Router.Gateway.Tests;
|
||||
|
||||
public sealed class RateLimitMiddlewareTests
|
||||
{
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task InvokeAsync_EnforcesEnvironmentLimit_WithRetryAfterAndJsonBody()
|
||||
{
|
||||
var config = new RateLimitConfig
|
||||
|
||||
@@ -2,11 +2,13 @@ using FluentAssertions;
|
||||
using StellaOps.Router.Gateway.RateLimit;
|
||||
using Xunit;
|
||||
|
||||
using StellaOps.TestKit;
|
||||
namespace StellaOps.Router.Gateway.Tests;
|
||||
|
||||
public sealed class RateLimitRouteMatcherTests
|
||||
{
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void TryMatch_ExactBeatsPrefixAndRegex()
|
||||
{
|
||||
var microservice = new MicroserviceLimitsConfig
|
||||
@@ -43,7 +45,8 @@ public sealed class RateLimitRouteMatcherTests
|
||||
match!.Value.Name.Should().Be("exact");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void TryMatch_LongestPrefixWins()
|
||||
{
|
||||
var microservice = new MicroserviceLimitsConfig
|
||||
|
||||
@@ -3,6 +3,7 @@ using Microsoft.Extensions.Logging.Abstractions;
|
||||
using StellaOps.Router.Gateway.RateLimit;
|
||||
using Xunit;
|
||||
|
||||
using StellaOps.TestKit;
|
||||
namespace StellaOps.Router.Gateway.Tests;
|
||||
|
||||
public sealed class RateLimitServiceTests
|
||||
@@ -26,7 +27,8 @@ public sealed class RateLimitServiceTests
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task CheckLimitAsync_DoesNotInvokeEnvironmentLimiterUntilActivationGateTriggers()
|
||||
{
|
||||
var config = new RateLimitConfig
|
||||
@@ -58,7 +60,8 @@ public sealed class RateLimitServiceTests
|
||||
store.Calls.Should().Be(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task CheckLimitAsync_EnforcesPerRouteEnvironmentRules()
|
||||
{
|
||||
var config = new RateLimitConfig
|
||||
|
||||
@@ -5,11 +5,14 @@ using StellaOps.Router.Gateway.Configuration;
|
||||
using StellaOps.Router.Gateway.DependencyInjection;
|
||||
using Xunit;
|
||||
|
||||
|
||||
using StellaOps.TestKit;
|
||||
namespace StellaOps.Router.Gateway.Tests;
|
||||
|
||||
public sealed class RouterNodeConfigValidationTests
|
||||
{
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void RouterNodeConfig_WhenRegionMissing_ThrowsOptionsValidationException()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
@@ -22,7 +25,8 @@ public sealed class RouterNodeConfigValidationTests
|
||||
act.Should().Throw<OptionsValidationException>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void RouterNodeConfig_WhenRegionProvided_GeneratesNodeIdIfMissing()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\__Libraries\StellaOps.Router.Gateway\StellaOps.Router.Gateway.csproj" />
|
||||
<ProjectReference Include="../../__Libraries/StellaOps.TestKit/StellaOps.TestKit.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
Reference in New Issue
Block a user