From f7be1fb80e485c96102cd134fd64d4f063814c16 Mon Sep 17 00:00:00 2001 From: John Luo Date: Mon, 11 Jan 2016 16:57:59 -0800 Subject: [PATCH] Fixing logger nullref when context created with no feature #532 --- .../ClientHandler.cs | 9 ++-- .../WebSocketClient.cs | 7 +-- .../ClientHandlerTests.cs | 48 +++++++++++++++++++ .../TestClientTests.cs | 44 ++++++++++++----- .../TestServerTests.cs | 1 - 5 files changed, 90 insertions(+), 19 deletions(-) diff --git a/src/Microsoft.AspNet.TestHost/ClientHandler.cs b/src/Microsoft.AspNet.TestHost/ClientHandler.cs index 0dac9f0546..9f3a9f0fbb 100644 --- a/src/Microsoft.AspNet.TestHost/ClientHandler.cs +++ b/src/Microsoft.AspNet.TestHost/ClientHandler.cs @@ -124,12 +124,13 @@ namespace Microsoft.AspNet.TestHost request.Headers.Host = request.RequestUri.GetComponents(UriComponents.HostAndPort, UriFormat.UriEscaped); } - Context = application.CreateContext(new FeatureCollection()); + var contextFeatures = new FeatureCollection(); + contextFeatures.Set(new RequestFeature()); + _responseFeature = new ResponseFeature(); + contextFeatures.Set(_responseFeature); + Context = application.CreateContext(contextFeatures); var httpContext = Context.HttpContext; - httpContext.Features.Set(new RequestFeature()); - _responseFeature = new ResponseFeature(); - httpContext.Features.Set(_responseFeature); var serverRequest = httpContext.Request; serverRequest.Protocol = "HTTP/" + request.Version.ToString(2); serverRequest.Scheme = request.RequestUri.Scheme; diff --git a/src/Microsoft.AspNet.TestHost/WebSocketClient.cs b/src/Microsoft.AspNet.TestHost/WebSocketClient.cs index 8c9da7e11b..b26a1a4223 100644 --- a/src/Microsoft.AspNet.TestHost/WebSocketClient.cs +++ b/src/Microsoft.AspNet.TestHost/WebSocketClient.cs @@ -98,11 +98,13 @@ namespace Microsoft.AspNet.TestHost _application = application; // HttpContext - Context = _application.CreateContext(new FeatureCollection()); + var contextFeatures = new FeatureCollection(); + contextFeatures.Set(new RequestFeature()); + contextFeatures.Set(new ResponseFeature()); + Context = _application.CreateContext(contextFeatures); var httpContext = Context.HttpContext; // Request - httpContext.Features.Set(new RequestFeature()); var request = httpContext.Request; request.Protocol = "HTTP/1.1"; var scheme = uri.Scheme; @@ -130,7 +132,6 @@ namespace Microsoft.AspNet.TestHost request.Body = Stream.Null; // Response - httpContext.Features.Set(new ResponseFeature()); var response = httpContext.Response; response.Body = Stream.Null; response.StatusCode = 200; diff --git a/test/Microsoft.AspNet.TestHost.Tests/ClientHandlerTests.cs b/test/Microsoft.AspNet.TestHost.Tests/ClientHandlerTests.cs index 820f98d1fb..b439df01bd 100644 --- a/test/Microsoft.AspNet.TestHost.Tests/ClientHandlerTests.cs +++ b/test/Microsoft.AspNet.TestHost.Tests/ClientHandlerTests.cs @@ -5,13 +5,19 @@ using System; using System.IO; using System.Linq; using System.Net.Http; +using System.Text; using System.Threading; using System.Threading.Tasks; +using Microsoft.AspNet.Builder; +using Microsoft.AspNet.Hosting; +using Microsoft.AspNet.Hosting.Internal; using Microsoft.AspNet.Hosting.Server; using Microsoft.AspNet.Http; using Microsoft.AspNet.Http.Internal; using Microsoft.AspNet.Http.Features; using Microsoft.AspNet.Testing.xunit; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Xunit; using Context = Microsoft.AspNet.Hosting.Internal.HostingApplication.Context; @@ -269,5 +275,47 @@ namespace Microsoft.AspNet.TestHost return _application(context.HttpContext); } } + + + [ConditionalFact] + [FrameworkSkipCondition(RuntimeFrameworks.Mono, SkipReason = "Hangs randomly (issue #507)")] + public async Task ClientHandlerCreateContextWithDefaultRequestParameters() + { + // This logger will attempt to access information from HttpRequest once the HttpContext is created + var logger = new VerifierLogger(); + var builder = new WebApplicationBuilder() + .ConfigureServices(services => + { + services.AddSingleton>(logger); + }) + .Configure(app => + { + app.Run(context => + { + return Task.FromResult(0); + }); + }); + var server = new TestServer(builder); + + // The HttpContext will be created and the logger will make sure that the HttpRequest exists and contains reasonable values + var result = await server.CreateClient().GetStringAsync("/"); + } + + private class VerifierLogger : ILogger + { + public IDisposable BeginScopeImpl(object state) => new NoopDispoasble(); + + public bool IsEnabled(LogLevel logLevel) => true; + + // This call verifies that fields of HttpRequest are accessed and valid + public void Log(LogLevel logLevel, int eventId, object state, Exception exception, Func formatter) => formatter(state, exception); + + class NoopDispoasble : IDisposable + { + public void Dispose() + { + } + } + } } } diff --git a/test/Microsoft.AspNet.TestHost.Tests/TestClientTests.cs b/test/Microsoft.AspNet.TestHost.Tests/TestClientTests.cs index a453aaa564..42a1a7752f 100644 --- a/test/Microsoft.AspNet.TestHost.Tests/TestClientTests.cs +++ b/test/Microsoft.AspNet.TestHost.Tests/TestClientTests.cs @@ -11,21 +11,17 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.AspNet.Builder; using Microsoft.AspNet.Hosting; +using Microsoft.AspNet.Hosting.Internal; using Microsoft.AspNet.Http; using Microsoft.AspNet.Testing.xunit; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Xunit; namespace Microsoft.AspNet.TestHost { public class TestClientTests { - private readonly TestServer _server; - - public TestClientTests() - { - _server = new TestServer(new WebApplicationBuilder().Configure(app => app.Run(ctx => Task.FromResult(0)))); - } - [ConditionalFact] [FrameworkSkipCondition(RuntimeFrameworks.Mono, SkipReason = "Hangs randomly (issue #507)")] public async Task GetAsyncWorks() @@ -134,6 +130,8 @@ namespace Microsoft.AspNet.TestHost public async Task WebSocketWorks() { // Arrange + // This logger will attempt to access information from HttpRequest once the HttpContext is createds + var logger = new VerifierLogger(); RequestDelegate appDelegate = async ctx => { if (ctx.WebSockets.IsWebSocketRequest) @@ -156,14 +154,20 @@ namespace Microsoft.AspNet.TestHost } } }; - var builder = new WebApplicationBuilder().Configure(app => - { - app.Run(appDelegate); - }); + var builder = new WebApplicationBuilder() + .ConfigureServices(services => + { + services.AddSingleton>(logger); + }) + .Configure(app => + { + app.Run(appDelegate); + }); var server = new TestServer(builder); // Act var client = server.CreateWebSocketClient(); + // The HttpContext will be created and the logger will make sure that the HttpRequest exists and contains reasonable values var clientSocket = await client.ConnectAsync(new System.Uri("http://localhost"), CancellationToken.None); var hello = Encoding.UTF8.GetBytes("hello"); await clientSocket.SendAsync(new System.ArraySegment(hello), WebSocketMessageType.Text, true, CancellationToken.None); @@ -192,6 +196,24 @@ namespace Microsoft.AspNet.TestHost clientSocket.Dispose(); } + + private class VerifierLogger : ILogger + { + public IDisposable BeginScopeImpl(object state) => new NoopDispoasble(); + + public bool IsEnabled(LogLevel logLevel) => true; + + // This call verifies that fields of HttpRequest are accessed and valid + public void Log(LogLevel logLevel, int eventId, object state, Exception exception, Func formatter) => formatter(state, exception); + + class NoopDispoasble : IDisposable + { + public void Dispose() + { + } + } + } + [ConditionalFact] [FrameworkSkipCondition(RuntimeFrameworks.Mono, SkipReason = "Hangs randomly (issue #507)")] public async Task WebSocketDisposalThrowsOnPeer() diff --git a/test/Microsoft.AspNet.TestHost.Tests/TestServerTests.cs b/test/Microsoft.AspNet.TestHost.Tests/TestServerTests.cs index 02a56de542..8d55816777 100644 --- a/test/Microsoft.AspNet.TestHost.Tests/TestServerTests.cs +++ b/test/Microsoft.AspNet.TestHost.Tests/TestServerTests.cs @@ -10,7 +10,6 @@ using System.Threading.Tasks; using Microsoft.AspNet.Builder; using Microsoft.AspNet.Hosting; using Microsoft.AspNet.Http; -using Microsoft.AspNet.Http.Features; using Microsoft.AspNet.Http.Features.Internal; using Microsoft.AspNet.Http.Internal; using Microsoft.AspNet.Testing.xunit;