This commit is contained in:
2026-08-04 06:17:32 +03:00
parent 53f9819d40
commit 2028db671f
19 changed files with 159 additions and 45 deletions
+1 -1
View File
@@ -20,7 +20,7 @@ public sealed class CommandTests
{
["production"] = new ConnectionProfile
{
Name = "production", Endpoint = "ep://host",
Name = "production", Endpoint = "ep://host:65535",
},
},
}, default);
+7 -6
View File
@@ -8,13 +8,14 @@ namespace Esiur.CLI.Tests;
public sealed class ConfigurationTests
{
[Theory]
[InlineData("ep://localhost", "ep://localhost")]
[InlineData("ep://localhost:65535", "ep://localhost:65535")]
[InlineData("ep://example.test:9000/sys/service", "ep://example.test:9000")]
public void EndpointParserExtractsConnectionEndpoint(string value, string expected) =>
Assert.Equal(expected, EndpointParser.ConnectionEndpoint(value));
[Theory]
[InlineData("http://localhost")]
[InlineData("ep://localhost")]
[InlineData("ep:///missing-host")]
[InlineData("not-an-endpoint")]
public void EndpointParserRejectsInvalidEndpoints(string value) =>
@@ -43,7 +44,7 @@ public sealed class ConfigurationTests
["production"] = new ConnectionProfile
{
Name = "production",
Endpoint = "ep://host",
Endpoint = "ep://host:65535",
Provider = "password",
Identity = "ahmed",
},
@@ -55,7 +56,7 @@ public sealed class ConfigurationTests
Assert.DoesNotContain("secret", text, StringComparison.OrdinalIgnoreCase);
var loaded = await store.LoadAsync(default);
Assert.Equal("production", loaded.DefaultProfile);
Assert.Equal("ep://host", loaded.Profiles["PRODUCTION"].Endpoint);
Assert.Equal("ep://host:65535", loaded.Profiles["PRODUCTION"].Endpoint);
}
finally { directory.Delete(true); }
}
@@ -71,14 +72,14 @@ public sealed class ConfigurationTests
{
["saved"] = new ConnectionProfile
{
Name = "saved", Endpoint = "ep://saved", OutputFormat = "raw",
Name = "saved", Endpoint = "ep://saved:65535", OutputFormat = "raw",
Identity = "stored",
},
},
};
var result = ConfigurationResolver.Resolve(configuration,
new GlobalOptions("saved", "ep://explicit", null, "explicit", "json", TimeSpan.FromSeconds(4), false, false));
Assert.Equal("ep://explicit", result.Endpoint);
new GlobalOptions("saved", "ep://explicit:65535", null, "explicit", "json", TimeSpan.FromSeconds(4), false, false));
Assert.Equal("ep://explicit:65535", result.Endpoint);
Assert.Equal("explicit", result.Identity);
Assert.Equal("json", result.OutputFormat);
Assert.Equal(TimeSpan.FromSeconds(4), result.Timeout);
+32 -3
View File
@@ -361,6 +361,31 @@ public sealed class AspNetCoreIntegrationTests
cleanupCancellation.Token);
}
[Fact]
public async Task FrameworkWebSocket_AcceptsProxyEndpointWithUnspecifiedRemotePort()
{
await using var host = await StartApplicationAsync(
configureApplication: application => application.Use(
async (context, next) =>
{
context.Connection.RemotePort = IPEndPoint.MinPort;
await next(context);
}));
using var cancellation = new CancellationTokenSource(TestTimeout);
using var socket = new ClientWebSocket();
socket.Options.AddSubProtocol(FrameworkWebSocket.SubProtocol);
await socket.ConnectAsync(host.WebSocketAddress, cancellation.Token);
Assert.Equal(WebSocketState.Open, socket.State);
Assert.Equal(FrameworkWebSocket.SubProtocol, socket.SubProtocol);
await WaitUntilAsync(
() => host.Server.Connections.Count == 1,
cancellation.Token);
socket.Abort();
}
[Fact]
public async Task HostShutdown_CancelsWebSocketAndCleansUpAdmission()
{
@@ -640,7 +665,8 @@ public sealed class AspNetCoreIntegrationTests
private static WebApplication BuildApplication(
Action<EsiurBuilder>? configureEsiur = null,
Action<EpServer>? configureServer = null,
Action<WarehouseConfiguration>? configureWarehouse = null)
Action<WarehouseConfiguration>? configureWarehouse = null,
Action<WebApplication>? configureApplication = null)
{
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
@@ -665,6 +691,7 @@ public sealed class AspNetCoreIntegrationTests
var application = builder.Build();
application.UseWebSockets();
configureApplication?.Invoke(application);
application.MapGet("/health", () => Results.Text("healthy"));
application.MapEsiur("/esiur");
return application;
@@ -673,7 +700,8 @@ public sealed class AspNetCoreIntegrationTests
private static async Task<TestApplication> StartApplicationAsync(
Action<EpServer>? configureServer = null,
Action<WarehouseConfiguration>? configureWarehouse = null,
Action<EsiurBuilder>? configureEsiur = null)
Action<EsiurBuilder>? configureEsiur = null,
Action<WebApplication>? configureApplication = null)
{
var application = BuildApplication(
esiur =>
@@ -682,7 +710,8 @@ public sealed class AspNetCoreIntegrationTests
configureEsiur?.Invoke(esiur);
},
configureServer,
configureWarehouse);
configureWarehouse,
configureApplication);
using var cancellation = new CancellationTokenSource(TestTimeout);
await application.StartAsync(cancellation.Token);
+5 -5
View File
@@ -27,7 +27,7 @@ public sealed class EpConnectionReconnectTests
var open = connection.Connect(
hostname: "localhost",
port: 10518,
port: IPEndPoint.MaxPort,
domain: "test");
var completed = await Task.WhenAny(
@@ -62,7 +62,7 @@ public sealed class EpConnectionReconnectTests
var open = connection.Connect(
hostname: "localhost",
port: 10518,
port: IPEndPoint.MaxPort,
domain: "test");
await delayedSocket.ConnectInvoked.WaitAsync(TimeSpan.FromSeconds(2));
@@ -95,7 +95,7 @@ public sealed class EpConnectionReconnectTests
var open = connection.Connect(
hostname: "localhost",
port: 10518,
port: IPEndPoint.MaxPort,
domain: "test");
connection.AutoReconnect = false;
@@ -133,7 +133,7 @@ public sealed class EpConnectionReconnectTests
_ = connection.Connect(
initialSocket,
hostname: "localhost",
port: 10518,
port: IPEndPoint.MaxPort,
domain: "test");
initialSocket.Disconnect();
connection.AutoReconnect = false;
@@ -160,7 +160,7 @@ public sealed class EpConnectionReconnectTests
public SocketState State => state;
public INetworkReceiver<ISocket> Receiver { get; set; } = null!;
public IPEndPoint RemoteEndPoint { get; } =
new(IPAddress.Loopback, 10518);
new(IPAddress.Loopback, IPEndPoint.MaxPort);
public IPEndPoint LocalEndPoint { get; } =
new(IPAddress.Loopback, 50000);
public int ConnectCount { get; private set; }
+22
View File
@@ -0,0 +1,22 @@
using Esiur.Protocol;
using Esiur.Resource;
namespace Esiur.Tests.Unit;
public sealed class EpPortTests
{
[Fact]
public void ServerDoesNotAssignAProtocolPort()
=> Assert.Equal(0, new EpServer().Port);
[Fact]
public async Task ClientEndpointWithoutPortIsRejected()
{
var warehouse = new Warehouse();
var exception = await Assert.ThrowsAsync<FormatException>(async () =>
await warehouse.Get<EpConnection>("ep://localhost/sys/resource"));
Assert.Contains("explicit port", exception.Message, StringComparison.OrdinalIgnoreCase);
}
}
+2 -2
View File
@@ -251,7 +251,7 @@ public class PeerConnectionLimitTests
connection,
null);
_ = connection.Connect(socket, "example.test", 10518, "example.test");
_ = connection.Connect(socket, "example.test", IPEndPoint.MaxPort, "example.test");
var deadline = DateTime.UtcNow + TimeSpan.FromSeconds(3);
while (socket.State != SocketState.Closed && DateTime.UtcNow < deadline)
@@ -269,7 +269,7 @@ public class PeerConnectionLimitTests
public SocketState State { get; private set; } = SocketState.Established;
public INetworkReceiver<ISocket> Receiver { get; set; } = null!;
public IPEndPoint RemoteEndPoint { get; }
public IPEndPoint LocalEndPoint { get; } = new(IPAddress.Loopback, 10518);
public IPEndPoint LocalEndPoint { get; } = new(IPAddress.Loopback, IPEndPoint.MaxPort);
public TestSocket(IPAddress address, int port)
=> RemoteEndPoint = new IPEndPoint(address, port);
+1 -1
View File
@@ -382,7 +382,7 @@ public class SocketProtocolSecurityTests
public SocketState State { get; private set; } = SocketState.Listening;
public INetworkReceiver<ISocket> Receiver { get; set; } = null!;
public IPEndPoint RemoteEndPoint => null!;
public IPEndPoint LocalEndPoint { get; } = new(IPAddress.Loopback, 10518);
public IPEndPoint LocalEndPoint { get; } = new(IPAddress.Loopback, IPEndPoint.MaxPort);
public ISocket Accept()
{