diff --git a/test/SuperSocket.Tests/ClientTest.cs b/test/SuperSocket.Tests/ClientTest.cs index c190f8174..7b2d05b74 100644 --- a/test/SuperSocket.Tests/ClientTest.cs +++ b/test/SuperSocket.Tests/ClientTest.cs @@ -14,7 +14,10 @@ using SuperSocket.Server.Abstractions; using SuperSocket.Server.Abstractions.Session; using System.Threading; +using Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging.Abstractions; +using SuperSocket.Kestrel; using SuperSocket.WebSocket; namespace SuperSocket.Tests @@ -256,78 +259,92 @@ public async Task TestCommandLine(Type hostConfiguratorType) } } - [Fact] +[Fact] [Trait("Category", "TestDetachableConnection")] public async Task TestDetachableConnection() { IHostConfigurator hostConfigurator = new RegularHostConfigurator(); - await TestDetachableConnectionInternal(hostConfigurator, (_, socket) => - new StreamPipeConnection( - hostConfigurator.GetClientStream(socket).Result, - socket.RemoteEndPoint, - socket.LocalEndPoint, - new ConnectionOptions - { - Logger = DefaultLoggerFactory.CreateLogger(nameof(TestDetachableConnection)), - ReadAsDemand = true - }) - ); - - /* KestrelPipeConnection doesn't support Detach right now. - await TestDetachableConnectionInternal(new KestralConnectionHostConfigurator(), (server, socket) => - new KestrelPipeConnection( - server.ServiceProvider.GetService().Create(socket), + using (var server = CreateSocketServerBuilder(hostConfigurator) + .UsePackageHandler(async (s, p) => + { + await s.SendAsync(Utf8Encoding.GetBytes("PRE-" + p.Text + "\r\n")); + }).BuildAsServer()) + { + Assert.Equal("TestServer", server.Name); + + Assert.True(await server.StartAsync()); + OutputHelper.WriteLine("Server started."); + + using (var socket = hostConfigurator.CreateClient()) + { + await TestDetachableConnectionInternal(hostConfigurator, server, ser => new StreamPipeConnection( + hostConfigurator.GetClientStream(socket).Result, + socket.RemoteEndPoint, + socket.LocalEndPoint, new ConnectionOptions { Logger = DefaultLoggerFactory.CreateLogger(nameof(TestDetachableConnection)), - ReadAsDemand = false - } - ) - ); - */ - } + ReadAsDemand = true + }), () => socket.Connected); + } + + await server.StopAsync(); + } - async Task TestDetachableConnectionInternal(IHostConfigurator hostConfigurator, Func connectionFactory) - { using (var server = CreateSocketServerBuilder(hostConfigurator) - .UsePackageHandler(async (s, p) => - { - await s.SendAsync(Utf8Encoding.GetBytes("PRE-" + p.Text + "\r\n")); - }).BuildAsServer()) + .ConfigureServices((ctx, services) => services.AddSocketConnectionFactory()) + .UsePackageHandler(async (s, p) => + { + await s.SendAsync(Utf8Encoding.GetBytes("PRE-" + p.Text + "\r\n")); + }).BuildAsServer()) { - Assert.Equal("TestServer", server.Name); Assert.True(await server.StartAsync()); OutputHelper.WriteLine("Server started."); - - using (var socket = hostConfigurator.CreateClient()) + var connectionFactory = server.ServiceProvider + .GetRequiredService(); + await using (var context = await connectionFactory.ConnectAsync(hostConfigurator.GetServerEndPoint())) { - var connection = connectionFactory(server, socket); + await TestDetachableConnectionInternal(hostConfigurator, server, ser => new KestrelPipeConnection( + context, + new ConnectionOptions + { + Logger = DefaultLoggerFactory.CreateLogger(nameof(TestDetachableConnection)), + ReadAsDemand = true + } + ), () => !context.ConnectionClosed.IsCancellationRequested); + } - await TestConnection(connection); + await server.StopAsync(); + } + } - OutputHelper.WriteLine("Before DetachAsync"); + async Task TestDetachableConnectionInternal(IHostConfigurator hostConfigurator, + IServer server, + Func connectionFactory, + Func checkConnectionFactory) + { + var connection = connectionFactory(server); - await connection.DetachAsync(); + await TestConnection(connection); - // the connection is still alive in the server - Assert.Equal(1, server.SessionCount); + OutputHelper.WriteLine("Before DetachAsync"); - // socket.Connected is is still connected - Assert.True(socket.Connected); + await connection.DetachAsync(); - // Attach the socket with another connection - connection = connectionFactory(server, socket); + // the connection is still alive in the server + Assert.Equal(1, server.SessionCount); - await TestConnection(connection); - } + // socket.Connected is is still connected + Assert.True(checkConnectionFactory()); - await server.StopAsync(); - } - } + // Attach the socket with another connection + connection = connectionFactory(server); + await TestConnection(connection); + } async Task TestConnection(IConnection connection) { var packagePipe = connection.RunAsync(new LinePipelineFilter()); diff --git a/test/SuperSocket.Tests/ServiceCollectionExtensions.cs b/test/SuperSocket.Tests/ServiceCollectionExtensions.cs new file mode 100644 index 000000000..bdc2932a7 --- /dev/null +++ b/test/SuperSocket.Tests/ServiceCollectionExtensions.cs @@ -0,0 +1,25 @@ +using System; +using Microsoft.AspNetCore.Connections; +using Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets; +using Microsoft.Extensions.DependencyInjection; + +namespace SuperSocket.Tests; + +public static class ServiceCollectionExtensions +{ + private const string SocketConnectionFactoryTypeName = + "Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketConnectionFactory"; + + private static Type FindSocketConnectionFactory() + { + var assembly = typeof(SocketTransportOptions).Assembly; + var connectionFactoryType = assembly.GetType(SocketConnectionFactoryTypeName); + return connectionFactoryType ?? throw new NotSupportedException(SocketConnectionFactoryTypeName); + } + + public static IServiceCollection AddSocketConnectionFactory(this IServiceCollection services) + { + var factoryType = FindSocketConnectionFactory(); + return services.AddSingleton(typeof(IConnectionFactory), factoryType); + } +} \ No newline at end of file