From b21f84543aa76608ec6104a851a3cd18af6aa7bb Mon Sep 17 00:00:00 2001 From: David Fowler Date: Wed, 3 May 2017 19:35:09 -0700 Subject: [PATCH] Use WebHostBuilder as an implementation detail of TestServer (#1804) - This will make tests run more similarly so we can swap out the transport more easily. --- .../TestServer.cs | 95 ++++++++++--------- test/shared/TestServiceContext.cs | 7 +- 2 files changed, 55 insertions(+), 47 deletions(-) diff --git a/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/TestServer.cs b/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/TestServer.cs index 630e87657b..73f2adfbf9 100644 --- a/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/TestServer.cs +++ b/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/TestServer.cs @@ -4,13 +4,16 @@ using System; using System.Net; using System.Net.Sockets; -using System.Threading; +using System.Reflection; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Hosting.Server; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Server.Kestrel.Core; using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions; -using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv; -using Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets; using Microsoft.AspNetCore.Testing; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests @@ -18,12 +21,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests /// /// Summary description for TestServer /// - public class TestServer : IDisposable + public class TestServer : IDisposable, IStartup { - private static TimeSpan _shutdownTimeout = TimeSpan.FromSeconds(5); - - private KestrelServer _server; + private IWebHost _host; private ListenOptions _listenOptions; + private readonly RequestDelegate _app; public TestServer(RequestDelegate app) : this(app, new TestServiceContext()) @@ -47,54 +49,60 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests public TestServer(RequestDelegate app, TestServiceContext context, ListenOptions listenOptions, IHttpContextFactory httpContextFactory) { + _app = app; _listenOptions = listenOptions; - Context = context; - context.ServerOptions.ListenOptions.Add(_listenOptions); - // Switch this to test on socket transport - var transportFactory = CreateLibuvTransportFactory(context); - // var transportFactory = CreateSocketTransportFactory(context); + _host = new WebHostBuilder() + .UseKestrel(o => + { + o.ListenOptions.Add(_listenOptions); + }) + .ConfigureServices(services => + { + if (httpContextFactory != null) + { + services.AddSingleton(httpContextFactory); + } - _server = new KestrelServer(transportFactory, context); - var httpApplication = new DummyApplication(app, httpContextFactory); + services.AddSingleton(this); + services.AddSingleton(new KestrelTestLoggerFactory(context.ErrorLogger)); + services.AddSingleton(sp => + { + // Manually configure options on the TestServiceContext. + // We're doing this so we can use the same instance that was passed in + var configureOptions = sp.GetServices>(); + foreach (var c in configureOptions) + { + c.Configure(context.ServerOptions); + } + return new KestrelServer(sp.GetRequiredService(), context); + }); + }) + .UseSetting(WebHostDefaults.ApplicationKey, typeof(TestServer).GetTypeInfo().Assembly.FullName) + .Build(); - try - { - _server.StartAsync(httpApplication, CancellationToken.None).Wait(); - } - catch - { - _server.StopAsync(new CancellationTokenSource(_shutdownTimeout).Token).Wait(); - _server.Dispose(); - throw; - } + _host.Start(); } - private static ITransportFactory CreateLibuvTransportFactory(TestServiceContext context) - { - var transportOptions = new LibuvTransportOptions { ThreadCount = 1 }; - - var transportFactory = new LibuvTransportFactory( - Options.Create(transportOptions), - new LifetimeNotImplemented(), - new KestrelTestLoggerFactory(new TestApplicationErrorLogger())); - - return transportFactory; - } - - private static ITransportFactory CreateSocketTransportFactory(TestServiceContext context) - { - var options = new SocketTransportOptions(); - return new SocketTransportFactory(Options.Create(options)); - } - public IPEndPoint EndPoint => _listenOptions.IPEndPoint; public int Port => _listenOptions.IPEndPoint.Port; public AddressFamily AddressFamily => _listenOptions.IPEndPoint.AddressFamily; public TestServiceContext Context { get; } + void IStartup.Configure(IApplicationBuilder app) + { + app.Run(_app); + } + + IServiceProvider IStartup.ConfigureServices(IServiceCollection services) + { + // Unfortunately, this needs to be replaced in IStartup.ConfigureServices + services.AddSingleton(); + return services.BuildServiceProvider(); + } + public TestConnection CreateConnection() { return new TestConnection(Port, AddressFamily); @@ -102,8 +110,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests public void Dispose() { - _server.StopAsync(new CancellationTokenSource(_shutdownTimeout).Token).Wait(); - _server.Dispose(); + _host.Dispose(); } } } diff --git a/test/shared/TestServiceContext.cs b/test/shared/TestServiceContext.cs index 349ef91a43..b1b28f7014 100644 --- a/test/shared/TestServiceContext.cs +++ b/test/shared/TestServiceContext.cs @@ -13,9 +13,8 @@ namespace Microsoft.AspNetCore.Testing { public TestServiceContext() { - var logger = new TestApplicationErrorLogger(); - - Log = new TestKestrelTrace(logger); + ErrorLogger = new TestApplicationErrorLogger(); + Log = new TestKestrelTrace(ErrorLogger); ThreadPool = new LoggingThreadPool(Log); SystemClock = new MockSystemClock(); DateHeaderValueManager = new DateHeaderValueManager(SystemClock); @@ -28,6 +27,8 @@ namespace Microsoft.AspNetCore.Testing }; } + public TestApplicationErrorLogger ErrorLogger { get; } + public string DateHeaderValue { get; } } }