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.
This commit is contained in:
parent
6c0c31640f
commit
b21f84543a
|
|
@ -4,13 +4,16 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
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.Http;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions;
|
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.AspNetCore.Testing;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
||||||
|
|
@ -18,12 +21,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Summary description for TestServer
|
/// Summary description for TestServer
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class TestServer : IDisposable
|
public class TestServer : IDisposable, IStartup
|
||||||
{
|
{
|
||||||
private static TimeSpan _shutdownTimeout = TimeSpan.FromSeconds(5);
|
private IWebHost _host;
|
||||||
|
|
||||||
private KestrelServer _server;
|
|
||||||
private ListenOptions _listenOptions;
|
private ListenOptions _listenOptions;
|
||||||
|
private readonly RequestDelegate _app;
|
||||||
|
|
||||||
public TestServer(RequestDelegate app)
|
public TestServer(RequestDelegate app)
|
||||||
: this(app, new TestServiceContext())
|
: this(app, new TestServiceContext())
|
||||||
|
|
@ -47,46 +49,40 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
||||||
|
|
||||||
public TestServer(RequestDelegate app, TestServiceContext context, ListenOptions listenOptions, IHttpContextFactory httpContextFactory)
|
public TestServer(RequestDelegate app, TestServiceContext context, ListenOptions listenOptions, IHttpContextFactory httpContextFactory)
|
||||||
{
|
{
|
||||||
|
_app = app;
|
||||||
_listenOptions = listenOptions;
|
_listenOptions = listenOptions;
|
||||||
|
|
||||||
Context = context;
|
Context = context;
|
||||||
context.ServerOptions.ListenOptions.Add(_listenOptions);
|
|
||||||
|
|
||||||
// Switch this to test on socket transport
|
_host = new WebHostBuilder()
|
||||||
var transportFactory = CreateLibuvTransportFactory(context);
|
.UseKestrel(o =>
|
||||||
// var transportFactory = CreateSocketTransportFactory(context);
|
{
|
||||||
|
o.ListenOptions.Add(_listenOptions);
|
||||||
|
})
|
||||||
|
.ConfigureServices(services =>
|
||||||
|
{
|
||||||
|
if (httpContextFactory != null)
|
||||||
|
{
|
||||||
|
services.AddSingleton(httpContextFactory);
|
||||||
|
}
|
||||||
|
|
||||||
_server = new KestrelServer(transportFactory, context);
|
services.AddSingleton<IStartup>(this);
|
||||||
var httpApplication = new DummyApplication(app, httpContextFactory);
|
services.AddSingleton<ILoggerFactory>(new KestrelTestLoggerFactory(context.ErrorLogger));
|
||||||
|
services.AddSingleton<IServer>(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<IConfigureOptions<KestrelServerOptions>>();
|
||||||
|
foreach (var c in configureOptions)
|
||||||
|
{
|
||||||
|
c.Configure(context.ServerOptions);
|
||||||
|
}
|
||||||
|
return new KestrelServer(sp.GetRequiredService<ITransportFactory>(), context);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.UseSetting(WebHostDefaults.ApplicationKey, typeof(TestServer).GetTypeInfo().Assembly.FullName)
|
||||||
|
.Build();
|
||||||
|
|
||||||
try
|
_host.Start();
|
||||||
{
|
|
||||||
_server.StartAsync(httpApplication, CancellationToken.None).Wait();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
_server.StopAsync(new CancellationTokenSource(_shutdownTimeout).Token).Wait();
|
|
||||||
_server.Dispose();
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 IPEndPoint EndPoint => _listenOptions.IPEndPoint;
|
||||||
|
|
@ -95,6 +91,18 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
||||||
|
|
||||||
public TestServiceContext Context { get; }
|
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<IApplicationLifetime, LifetimeNotImplemented>();
|
||||||
|
return services.BuildServiceProvider();
|
||||||
|
}
|
||||||
|
|
||||||
public TestConnection CreateConnection()
|
public TestConnection CreateConnection()
|
||||||
{
|
{
|
||||||
return new TestConnection(Port, AddressFamily);
|
return new TestConnection(Port, AddressFamily);
|
||||||
|
|
@ -102,8 +110,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_server.StopAsync(new CancellationTokenSource(_shutdownTimeout).Token).Wait();
|
_host.Dispose();
|
||||||
_server.Dispose();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,9 +13,8 @@ namespace Microsoft.AspNetCore.Testing
|
||||||
{
|
{
|
||||||
public TestServiceContext()
|
public TestServiceContext()
|
||||||
{
|
{
|
||||||
var logger = new TestApplicationErrorLogger();
|
ErrorLogger = new TestApplicationErrorLogger();
|
||||||
|
Log = new TestKestrelTrace(ErrorLogger);
|
||||||
Log = new TestKestrelTrace(logger);
|
|
||||||
ThreadPool = new LoggingThreadPool(Log);
|
ThreadPool = new LoggingThreadPool(Log);
|
||||||
SystemClock = new MockSystemClock();
|
SystemClock = new MockSystemClock();
|
||||||
DateHeaderValueManager = new DateHeaderValueManager(SystemClock);
|
DateHeaderValueManager = new DateHeaderValueManager(SystemClock);
|
||||||
|
|
@ -28,6 +27,8 @@ namespace Microsoft.AspNetCore.Testing
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TestApplicationErrorLogger ErrorLogger { get; }
|
||||||
|
|
||||||
public string DateHeaderValue { get; }
|
public string DateHeaderValue { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue