Noop on the request body stream in TestServer (#10738)

* Noop on the request body stream in TestServer
- Disposable should not be observable on the client side if the server disposes the body. This is similar to how Kestrel noops on dispose to avoid common usages like StreamReader disposing the underlying stream.
This commit is contained in:
David Fowler 2019-06-02 13:53:36 -07:00 committed by GitHub
parent 173cf1786e
commit 620c673705
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 42 additions and 3 deletions

View File

@ -116,17 +116,18 @@ namespace Microsoft.AspNetCore.TestHost
public override void Close()
{
_inner.Close();
// Don't dispose the inner stream, we don't want to impact the client stream
}
protected override void Dispose(bool disposing)
{
_inner.Dispose();
// Don't dispose the inner stream, we don't want to impact the client stream
}
public override ValueTask DisposeAsync()
{
return _inner.DisposeAsync();
// Don't dispose the inner stream, we don't want to impact the client stream
return default;
}
}
}

View File

@ -3,8 +3,10 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
@ -18,6 +20,7 @@ using Microsoft.Extensions.DiagnosticAdapter;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Headers;
using Moq;
using Xunit;
namespace Microsoft.AspNetCore.TestHost
@ -191,6 +194,28 @@ namespace Microsoft.AspNetCore.TestHost
Assert.Equal("RequestServices:True", result);
}
[Fact]
public async Task DispoingTheRequestBodyDoesNotDisposeClientStreams()
{
var builder = new WebHostBuilder().Configure(app =>
{
app.Run(async context =>
{
using (var sr = new StreamReader(context.Request.Body))
{
await context.Response.WriteAsync(await sr.ReadToEndAsync());
}
});
});
var server = new TestServer(builder);
var stream = new ThrowOnDisposeStream();
stream.Write(Encoding.ASCII.GetBytes("Hello World"));
var response = await server.CreateClient().PostAsync("/", new StreamContent(stream));
Assert.True(response.IsSuccessStatusCode);
Assert.Equal("Hello World", await response.Content.ReadAsStringAsync());
}
public class CustomContainerStartup
{
public IServiceProvider Services;
@ -662,6 +687,19 @@ namespace Microsoft.AspNetCore.TestHost
Assert.Equal("otherhost:5678", responseBody);
}
private class ThrowOnDisposeStream : MemoryStream
{
protected override void Dispose(bool disposing)
{
throw new InvalidOperationException("Dispose should not happen!");
}
public override ValueTask DisposeAsync()
{
throw new InvalidOperationException("DisposeAsync should not happen!");
}
}
public class TestDiagnosticListener
{
public class OnBeginRequestEventData