/
githubmirror
/
aspnetcore
Обзор
Документация
Войти
/
githubmirror
/
aspnetcore
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Hosting/TestHost/test/HttpContextBuilderTests.cs
500 строк
18 KB
Copilot
Add [Obsolete] attribute to WebHost, IWebHost, and WebHostService
15 авг 2025, 20:33
Не верифицирован
15 авг 2025, 20:33
fe0ccd9
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Text; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.InternalTesting; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; namespace Microsoft.AspNetCore.TestHost; public class HttpContextBuilderTests { [Fact] public async Task ExpectedValuesAreAvailable() { using var host = new HostBuilder() .ConfigureWebHost(webBuilder => { webBuilder .UseTestServer() .Configure(app => { }); }) .Build(); var server = host.GetTestServer(); await host.StartAsync(); server.BaseAddress = new Uri("https://example.com/A/Path/"); var context = await server.SendAsync(c => { c.Request.Method = HttpMethods.Post; c.Request.Path = "/and/file.txt"; c.Request.QueryString = new QueryString("?and=query"); }); Assert.True(context.RequestAborted.CanBeCanceled); Assert.Equal(HttpProtocol.Http11, context.Request.Protocol); Assert.Equal("POST", context.Request.Method); Assert.Equal("https", context.Request.Scheme); Assert.Equal("example.com", context.Request.Host.Value); Assert.Equal("/A/Path", context.Request.PathBase.Value); Assert.Equal("/and/file.txt", context.Request.Path.Value); Assert.Equal("?and=query", context.Request.QueryString.Value); Assert.Null(context.Request.CanHaveBody()); Assert.NotNull(context.Request.Body); Assert.NotNull(context.Request.Headers); Assert.NotNull(context.Response.Headers); Assert.NotNull(context.Response.Body); Assert.Equal(404, context.Response.StatusCode); Assert.Null(context.Features.Get<IHttpResponseFeature>().ReasonPhrase); } [Fact] public async Task UserAgentHeaderWorks() { var userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:71.0) Gecko/20100101 Firefox/71.0"; using var host = new HostBuilder() .ConfigureWebHost(webBuilder => { webBuilder .UseTestServer() .Configure(app => { }); }) .Build(); var server = host.GetTestServer(); await host.StartAsync(); server.BaseAddress = new Uri("https://example.com/"); var context = await server.SendAsync(c => { c.Request.Headers.UserAgent = userAgent; }); var actualResult = context.Request.Headers.UserAgent; Assert.Equal(userAgent, actualResult); } [Fact] public async Task SingleSlashNotMovedToPathBase() { using var host = new HostBuilder() .ConfigureWebHost(webBuilder => { webBuilder .UseTestServer() .Configure(app => { }); }) .Build(); var server = host.GetTestServer(); await host.StartAsync(); var context = await server.SendAsync(c => { c.Request.Path = "/"; }); Assert.Equal("", context.Request.PathBase.Value); Assert.Equal("/", context.Request.Path.Value); } [Fact] public async Task MiddlewareOnlySetsHeaders() { using var host = new HostBuilder() .ConfigureWebHost(webBuilder => { webBuilder .UseTestServer() .Configure(app => { app.Run(c => { c.Response.Headers["TestHeader"] = "TestValue"; return Task.FromResult(0); }); }); }) .Build(); var server = host.GetTestServer(); await host.StartAsync(); var context = await server.SendAsync(c => { }); Assert.Equal("TestValue", context.Response.Headers["TestHeader"]); } [Fact] public async Task BlockingMiddlewareShouldNotBlockClient() { var block = new ManualResetEvent(false); var builder = new HostBuilder().ConfigureWebHost(webHostBuilder => webHostBuilder.Configure(app => { app.Run(c => { block.WaitOne(); return Task.FromResult(0); }); }) .UseTestServer()); using var host = builder.Build(); await host.StartAsync(); var server = host.GetTestServer(); var task = server.SendAsync(c => { }); Assert.False(task.IsCompleted); #pragma warning disable xUnit1031 // Do not use blocking task operations in test method Assert.False(task.Wait(50)); #pragma warning restore xUnit1031 // Do not use blocking task operations in test method block.Set(); var context = await task; } [Fact] public async Task HeadersAvailableBeforeSyncBodyFinished() { var block = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); using var host = new HostBuilder() .ConfigureWebHost(webBuilder => { webBuilder .UseTestServer() .Configure(app => { app.Run(async c => { c.Response.Headers["TestHeader"] = "TestValue"; var bytes = Encoding.UTF8.GetBytes("BodyStarted" + Environment.NewLine); c.Features.Get<IHttpBodyControlFeature>().AllowSynchronousIO = true; c.Response.Body.Write(bytes, 0, bytes.Length); await block.Task; bytes = Encoding.UTF8.GetBytes("BodyFinished"); c.Response.Body.Write(bytes, 0, bytes.Length); }); }); }) .Build(); var server = host.GetTestServer(); await host.StartAsync(); var context = await server.SendAsync(c => { }); Assert.Equal("TestValue", context.Response.Headers["TestHeader"]); var reader = new StreamReader(context.Response.Body); Assert.Equal("BodyStarted", reader.ReadLine()); block.SetResult(); Assert.Equal("BodyFinished", reader.ReadToEnd()); } [Fact] public async Task HeadersAvailableBeforeAsyncBodyFinished() { var block = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); using var host = new HostBuilder() .ConfigureWebHost(webBuilder => { webBuilder .UseTestServer() .Configure(app => { app.Run(async c => { c.Response.Headers["TestHeader"] = "TestValue"; await c.Response.WriteAsync("BodyStarted" + Environment.NewLine); await block.Task; await c.Response.WriteAsync("BodyFinished"); }); }); }) .Build(); var server = host.GetTestServer(); await host.StartAsync(); var context = await server.SendAsync(c => { }); Assert.Equal("TestValue", context.Response.Headers["TestHeader"]); var reader = new StreamReader(context.Response.Body); Assert.Equal("BodyStarted", await reader.ReadLineAsync()); block.SetResult(); Assert.Equal("BodyFinished", await reader.ReadToEndAsync()); } [Fact] public async Task FlushSendsHeaders() { var block = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); using var host = new HostBuilder() .ConfigureWebHost(webBuilder => { webBuilder .UseTestServer() .Configure(app => { app.Run(async c => { c.Response.Headers["TestHeader"] = "TestValue"; await c.Response.Body.FlushAsync(); await block.Task; await c.Response.WriteAsync("BodyFinished"); }); }); }) .Build(); var server = host.GetTestServer(); await host.StartAsync(); var context = await server.SendAsync(c => { }); Assert.Equal("TestValue", context.Response.Headers["TestHeader"]); block.SetResult(); Assert.Equal("BodyFinished", new StreamReader(context.Response.Body).ReadToEnd()); } [Fact] public async Task ClientDisposalCloses() { var block = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); using var host = new HostBuilder() .ConfigureWebHost(webBuilder => { webBuilder .UseTestServer() .Configure(app => { app.Run(async c => { c.Response.Headers["TestHeader"] = "TestValue"; await c.Response.Body.FlushAsync(); await block.Task; await c.Response.WriteAsync("BodyFinished"); }); }); }) .Build(); var server = host.GetTestServer(); await host.StartAsync(); var context = await server.SendAsync(c => { }); Assert.Equal("TestValue", context.Response.Headers["TestHeader"]); var responseStream = context.Response.Body; Task<int> readTask = responseStream.ReadAsync(new byte[100], 0, 100); Assert.False(readTask.IsCompleted); responseStream.Dispose(); await Assert.ThrowsAsync<OperationCanceledException>(() => readTask.DefaultTimeout()); block.SetResult(); } [Fact] public async Task ClientCancellationAborts() { var block = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); using var host = new HostBuilder() .ConfigureWebHost(webBuilder => { webBuilder .UseTestServer() .Configure(app => { app.Run(c => { block.SetResult(); Assert.True(c.RequestAborted.WaitHandle.WaitOne(TimeSpan.FromSeconds(10))); c.RequestAborted.ThrowIfCancellationRequested(); return Task.CompletedTask; }); }); }) .Build(); var server = host.GetTestServer(); await host.StartAsync(); var cts = new CancellationTokenSource(); var contextTask = server.SendAsync(c => { }, cts.Token); await block.Task; cts.Cancel(); await Assert.ThrowsAsync<OperationCanceledException>(() => contextTask.DefaultTimeout()); } [Fact] public async Task ClientCancellationAbortsReadAsync() { var block = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); using var host = new HostBuilder() .ConfigureWebHost(webBuilder => { webBuilder .UseTestServer() .Configure(app => { app.Run(async c => { c.Response.Headers["TestHeader"] = "TestValue"; await c.Response.Body.FlushAsync(); await block.Task; await c.Response.WriteAsync("BodyFinished"); }); }); }) .Build(); var server = host.GetTestServer(); await host.StartAsync(); var context = await server.SendAsync(c => { }); Assert.Equal("TestValue", context.Response.Headers["TestHeader"]); var responseStream = context.Response.Body; var cts = new CancellationTokenSource(); var readTask = responseStream.ReadAsync(new byte[100], 0, 100, cts.Token); Assert.False(readTask.IsCompleted); cts.Cancel(); await Assert.ThrowsAsync<OperationCanceledException>(() => readTask.DefaultTimeout()); block.SetResult(); } [Fact] public Task ExceptionBeforeFirstWriteIsReported() { using var host = new HostBuilder() .ConfigureWebHost(webBuilder => { webBuilder .UseTestServer() .Configure(app => { app.Run(c => { throw new InvalidOperationException("Test Exception"); }); }); }) .Build(); var server = host.GetTestServer(); return Assert.ThrowsAsync<InvalidOperationException>(() => server.SendAsync(c => { })); } [Fact] public async Task ExceptionAfterFirstWriteIsReported() { var block = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); using var host = new HostBuilder() .ConfigureWebHost(webBuilder => { webBuilder .UseTestServer() .Configure(app => { app.Run(async c => { c.Response.Headers["TestHeader"] = "TestValue"; await c.Response.WriteAsync("BodyStarted"); await block.Task; throw new InvalidOperationException("Test Exception"); }); }); }) .Build(); var server = host.GetTestServer(); await host.StartAsync(); var context = await server.SendAsync(c => { }); Assert.Equal("TestValue", context.Response.Headers["TestHeader"]); Assert.Equal(11, context.Response.Body.Read(new byte[100], 0, 100)); block.SetResult(); var ex = Assert.Throws<IOException>(() => context.Response.Body.Read(new byte[100], 0, 100)); Assert.IsAssignableFrom<InvalidOperationException>(ex.InnerException); } [Fact] public async Task ClientHandlerCreateContextWithDefaultRequestParameters() { // This logger will attempt to access information from HttpRequest once the HttpContext is created var logger = new VerifierLogger(); using var host = new HostBuilder() .ConfigureWebHost(webBuilder => { webBuilder .UseTestServer() .ConfigureServices(services => { #pragma warning disable ASPDEPR008 // IWebHost is obsolete services.AddSingleton<ILogger<IWebHost>>(logger); #pragma warning restore ASPDEPR008 // IWebHost is obsolete }) .Configure(app => { app.Run(context => { return Task.FromResult(0); }); }); }) .Build(); var server = host.GetTestServer(); await host.StartAsync(); // The HttpContext will be created and the logger will make sure that the HttpRequest exists and contains reasonable values var ctx = await server.SendAsync(c => { }); } [Fact] public async Task CallingAbortInsideHandlerShouldSetRequestAborted() { var requestAborted = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); using var host = new HostBuilder() .ConfigureWebHost(webBuilder => { webBuilder .UseTestServer() .Configure(app => { app.Run(context => { context.RequestAborted.Register(() => requestAborted.SetResult()); context.Abort(); return Task.CompletedTask; }); }); }) .Build(); var server = host.GetTestServer(); await host.StartAsync(); var ex = await Assert.ThrowsAsync<OperationCanceledException>(() => server.SendAsync(c => { })); Assert.Equal("The application aborted the request.", ex.Message); await requestAborted.Task.DefaultTimeout(); } #pragma warning disable ASPDEPR008 // IWebHost is obsolete private class VerifierLogger : ILogger<IWebHost> #pragma warning restore ASPDEPR008 // IWebHost is obsolete { public IDisposable BeginScope<TState>(TState state) => new NoopDispoasble(); public bool IsEnabled(LogLevel logLevel) => true; // This call verifies that fields of HttpRequest are accessed and valid public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter) => formatter(state, exception); class NoopDispoasble : IDisposable { public void Dispose() { } } } }