From e07008ddec3e5eb45cd68ce5f6e8d984f76494bc Mon Sep 17 00:00:00 2001 From: Chris R Date: Tue, 5 Apr 2016 09:25:54 -0700 Subject: [PATCH] Prevent double flush in HttpResponseStreamWriter. --- .../HttpResponseStreamWriter.cs | 8 ++--- .../HttpResponseStreamWriterTest.cs | 33 +++++++++++++++++++ 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.AspNetCore.WebUtilities/HttpResponseStreamWriter.cs b/src/Microsoft.AspNetCore.WebUtilities/HttpResponseStreamWriter.cs index 9ec8da2338..f5568fb4a3 100644 --- a/src/Microsoft.AspNetCore.WebUtilities/HttpResponseStreamWriter.cs +++ b/src/Microsoft.AspNetCore.WebUtilities/HttpResponseStreamWriter.cs @@ -302,12 +302,12 @@ namespace Microsoft.AspNetCore.WebUtilities 0, flush: flushEncoder); + _charBufferCount = 0; + if (count > 0) { _stream.Write(_byteBuffer, 0, count); } - - _charBufferCount = 0; } // Note: our FlushInternalAsync method does NOT flush the underlying stream. This would result in @@ -327,12 +327,12 @@ namespace Microsoft.AspNetCore.WebUtilities 0, flush: flushEncoder); + _charBufferCount = 0; + if (count > 0) { await _stream.WriteAsync(_byteBuffer, 0, count); } - - _charBufferCount = 0; } private void CopyToCharBuffer(string value, ref int index, ref int count) diff --git a/test/Microsoft.AspNetCore.WebUtilities.Tests/HttpResponseStreamWriterTest.cs b/test/Microsoft.AspNetCore.WebUtilities.Tests/HttpResponseStreamWriterTest.cs index 372525731d..9c1d7dcb6b 100644 --- a/test/Microsoft.AspNetCore.WebUtilities.Tests/HttpResponseStreamWriterTest.cs +++ b/test/Microsoft.AspNetCore.WebUtilities.Tests/HttpResponseStreamWriterTest.cs @@ -220,6 +220,29 @@ namespace Microsoft.AspNetCore.WebUtilities.Test Assert.Equal(byteLength, stream.Length); } + [Theory] + [InlineData(1023)] + [InlineData(1024)] + public async Task FlushWriteThrows_DontFlushInDispose(int byteLength) + { + // Arrange + var stream = new TestMemoryStream() { ThrowOnWrite = true }; + var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8); + + await writer.WriteAsync(new string('a', byteLength)); + await Assert.ThrowsAsync(() => writer.FlushAsync()); + + // Act + writer.Dispose(); + + // Assert + Assert.Equal(1, stream.WriteAsyncCallCount); + Assert.Equal(0, stream.WriteCallCount); + Assert.Equal(0, stream.FlushCallCount); + Assert.Equal(0, stream.FlushAsyncCallCount); + Assert.Equal(0, stream.Length); + } + [Theory] [InlineData(1023)] [InlineData(1024)] @@ -419,6 +442,8 @@ namespace Microsoft.AspNetCore.WebUtilities.Test public int WriteAsyncCallCount { get; private set; } + public bool ThrowOnWrite { get; set; } + public override void Flush() { FlushCallCount++; @@ -434,12 +459,20 @@ namespace Microsoft.AspNetCore.WebUtilities.Test public override void Write(byte[] buffer, int offset, int count) { WriteCallCount++; + if (ThrowOnWrite) + { + throw new IOException("Test IOException"); + } base.Write(buffer, offset, count); } public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { WriteAsyncCallCount++; + if (ThrowOnWrite) + { + throw new IOException("Test IOException"); + } return base.WriteAsync(buffer, offset, count, cancellationToken); }