|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Buffers;
using System.Text;
using Moq;
namespace Microsoft.AspNetCore.WebUtilities;
public class HttpResponseStreamWriterTest
{
private const int DefaultCharacterChunkSize = HttpResponseStreamWriter.DefaultBufferSize;
[Fact]
public async Task DoesNotWriteBOM()
{
// Arrange
var memoryStream = new MemoryStream();
var encodingWithBOM = new UTF8Encoding(encoderShouldEmitUTF8Identifier: true);
var writer = new HttpResponseStreamWriter(memoryStream, encodingWithBOM);
var expectedData = new byte[] { 97, 98, 99, 100 }; // without BOM
// Act
using (writer)
{
await writer.WriteAsync("abcd");
}
// Assert
Assert.Equal(expectedData, memoryStream.ToArray());
}
[Fact]
public async Task DoesNotFlush_UnderlyingStream_OnDisposingWriter()
{
// Arrange
var stream = new TestMemoryStream();
var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8);
// Act
await writer.WriteAsync("Hello");
writer.Dispose();
// Assert
Assert.Equal(0, stream.FlushCallCount);
Assert.Equal(0, stream.FlushAsyncCallCount);
}
[Fact]
public async Task DoesNotDispose_UnderlyingStream_OnDisposingWriter()
{
// Arrange
var stream = new TestMemoryStream();
var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8);
// Act
await writer.WriteAsync("Hello world");
writer.Dispose();
// Assert
Assert.Equal(0, stream.DisposeCallCount);
}
[Theory]
[InlineData(1023)]
[InlineData(1024)]
[InlineData(1050)]
[InlineData(2048)]
public async Task FlushesBuffer_OnClose(int byteLength)
{
// Arrange
var stream = new TestMemoryStream();
var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8);
await writer.WriteAsync(new string('a', byteLength));
// Act
writer.Dispose();
// Assert
Assert.Equal(0, stream.FlushCallCount);
Assert.Equal(0, stream.FlushAsyncCallCount);
Assert.Equal(byteLength, stream.Length);
}
[Theory]
[InlineData(1023)]
[InlineData(1024)]
[InlineData(1050)]
[InlineData(2048)]
public async Task FlushesBuffer_OnDispose(int byteLength)
{
// Arrange
var stream = new TestMemoryStream();
var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8);
await writer.WriteAsync(new string('a', byteLength));
// Act
writer.Dispose();
// Assert
Assert.Equal(0, stream.FlushCallCount);
Assert.Equal(0, stream.FlushAsyncCallCount);
Assert.Equal(byteLength, stream.Length);
}
[Fact]
public void NoDataWritten_Flush_DoesNotFlushUnderlyingStream()
{
// Arrange
var stream = new TestMemoryStream();
var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8);
// Act
writer.Flush();
// Assert
Assert.Equal(0, stream.FlushCallCount);
Assert.Equal(0, stream.Length);
}
[Theory]
[InlineData(1023)]
[InlineData(1024)]
[InlineData(1050)]
[InlineData(2048)]
public void FlushesBuffer_ButNotStream_OnFlush(int byteLength)
{
// Arrange
var stream = new TestMemoryStream();
var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8);
writer.Write(new string('a', byteLength));
var expectedWriteCount = Math.Ceiling((double)byteLength / HttpResponseStreamWriter.DefaultBufferSize);
// Act
writer.Flush();
// Assert
Assert.Equal(0, stream.FlushCallCount);
Assert.Equal(expectedWriteCount, stream.WriteCallCount);
Assert.Equal(byteLength, stream.Length);
}
[Fact]
public async Task NoDataWritten_FlushAsync_DoesNotFlushUnderlyingStream()
{
// Arrange
var stream = new TestMemoryStream();
var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8);
// Act
await writer.FlushAsync();
// Assert
Assert.Equal(0, stream.FlushAsyncCallCount);
Assert.Equal(0, stream.Length);
}
[Theory]
[InlineData(HttpResponseStreamWriter.DefaultBufferSize - 1)]
[InlineData(HttpResponseStreamWriter.DefaultBufferSize)]
[InlineData(HttpResponseStreamWriter.DefaultBufferSize + 1)]
[InlineData(HttpResponseStreamWriter.DefaultBufferSize * 2)]
public async Task FlushesBuffer_ButNotStream_OnFlushAsync(int byteLength)
{
// Arrange
var stream = new TestMemoryStream();
var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8);
await writer.WriteAsync(new string('a', byteLength));
var expectedWriteCount = Math.Ceiling((double)byteLength / HttpResponseStreamWriter.DefaultBufferSize);
// Act
await writer.FlushAsync();
// Assert
Assert.Equal(0, stream.FlushAsyncCallCount);
Assert.Equal(expectedWriteCount, stream.WriteAsyncCallCount);
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<IOException>(() => 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)]
[InlineData(1050)]
[InlineData(2048)]
public void WriteChar_WritesToStream(int byteLength)
{
// Arrange
var stream = new TestMemoryStream();
var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8);
// Act
using (writer)
{
for (var i = 0; i < byteLength; i++)
{
writer.Write('a');
}
}
// Assert
Assert.Equal(byteLength, stream.Length);
}
[Theory]
[InlineData(1023)]
[InlineData(1024)]
[InlineData(1050)]
[InlineData(2048)]
public void WriteCharArray_WritesToStream(int byteLength)
{
// Arrange
var stream = new TestMemoryStream();
var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8);
// Act
using (writer)
{
writer.Write((new string('a', byteLength)).ToCharArray());
}
// Assert
Assert.Equal(byteLength, stream.Length);
}
[Theory]
[InlineData(1023)]
[InlineData(1024)]
[InlineData(1050)]
[InlineData(2048)]
[InlineData(HttpResponseStreamWriter.DefaultBufferSize + 1)]
public void WriteReadOnlySpanChar_WritesToStream(int byteLength)
{
// Arrange
var stream = new TestMemoryStream();
var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8);
// Act
using (writer)
{
var array = new string('a', byteLength).ToCharArray();
var span = new ReadOnlySpan<char>(array);
writer.Write(span);
}
// Assert
Assert.Equal(byteLength, stream.Length);
}
[Theory]
[InlineData(1022, "\n")]
[InlineData(1023, "\n")]
[InlineData(1024, "\n")]
[InlineData(1050, "\n")]
[InlineData(2047, "\n")]
[InlineData(2048, "\n")]
[InlineData(1021, "\r\n")]
[InlineData(1022, "\r\n")]
[InlineData(1023, "\r\n")]
[InlineData(1024, "\r\n")]
[InlineData(1050, "\r\n")]
[InlineData(2046, "\r\n")]
[InlineData(2048, "\r\n")]
[InlineData(HttpResponseStreamWriter.DefaultBufferSize + 1, "\r\n")]
public void WriteLineReadOnlySpanChar_WritesToStream(int byteLength, string newLine)
{
// Arrange
var stream = new TestMemoryStream();
var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8);
writer.NewLine = newLine;
// Act
using (writer)
{
var array = new string('a', byteLength).ToCharArray();
var span = new ReadOnlySpan<char>(array);
writer.WriteLine(span);
}
// Assert
Assert.Equal(byteLength + newLine.Length, stream.Length);
}
[Theory]
[InlineData(1023)]
[InlineData(1024)]
[InlineData(1050)]
[InlineData(2048)]
public async Task WriteCharAsync_WritesToStream(int byteLength)
{
// Arrange
var stream = new TestMemoryStream();
var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8);
// Act
using (writer)
{
for (var i = 0; i < byteLength; i++)
{
await writer.WriteAsync('a');
}
}
// Assert
Assert.Equal(byteLength, stream.Length);
}
[Theory]
[InlineData(1023)]
[InlineData(1024)]
[InlineData(1050)]
[InlineData(2048)]
public async Task WriteCharArrayAsync_WritesToStream(int byteLength)
{
// Arrange
var stream = new TestMemoryStream();
var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8);
// Act
using (writer)
{
await writer.WriteAsync((new string('a', byteLength)).ToCharArray());
}
// Assert
Assert.Equal(byteLength, stream.Length);
}
[Theory]
[InlineData(0)]
[InlineData(1023)]
[InlineData(1024)]
[InlineData(1050)]
[InlineData(2048)]
[InlineData(HttpResponseStreamWriter.DefaultBufferSize + 1)]
public async Task WriteReadOnlyMemoryAsync_WritesToStream(int byteLength)
{
// Arrange
var stream = new TestMemoryStream();
var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8);
// Act
using (writer)
{
var array = new string('a', byteLength).ToCharArray();
var memory = new ReadOnlyMemory<char>(array);
await writer.WriteAsync(memory);
}
// Assert
Assert.Equal(byteLength, stream.Length);
}
[Fact]
public async Task WriteReadOnlyMemoryAsync_TokenCanceled_ReturnsCanceledTask()
{
// Arrange
var stream = new TestMemoryStream();
using var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8);
var memory = new ReadOnlyMemory<char>(new char[] { 'a' });
var cancellationToken = new CancellationToken(true);
// Act
await Assert.ThrowsAsync<TaskCanceledException>(async () => await writer.WriteAsync(memory, cancellationToken));
// Assert
Assert.Equal(0, stream.Length);
}
[Theory]
[InlineData(0, 1)]
[InlineData(1022, 1)]
[InlineData(1023, 1)]
[InlineData(1024, 1)]
[InlineData(1050, 1)]
[InlineData(2047, 1)]
[InlineData(2048, 1)]
[InlineData(1021, 2)]
[InlineData(1022, 2)]
[InlineData(1023, 2)]
[InlineData(1024, 2)]
[InlineData(1024, 1023)]
[InlineData(1024, 1024)]
[InlineData(1024, 1050)]
[InlineData(1050, 2)]
[InlineData(2046, 2)]
[InlineData(2048, 2)]
[InlineData(HttpResponseStreamWriter.DefaultBufferSize + 1, 1)]
[InlineData(HttpResponseStreamWriter.DefaultBufferSize + 1, 2)]
[InlineData(HttpResponseStreamWriter.DefaultBufferSize + 1, HttpResponseStreamWriter.DefaultBufferSize)]
public async Task WriteLineReadOnlyMemoryAsync_WritesToStream(int byteLength, int newLineLength)
{
// Arrange
var stream = new TestMemoryStream();
var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8);
writer.NewLine = new string('\n', newLineLength);
// Act
using (writer)
{
var array = new string('a', byteLength).ToCharArray();
var memory = new ReadOnlyMemory<char>(array);
await writer.WriteLineAsync(memory);
}
// Assert
Assert.Equal(byteLength + newLineLength, stream.Length);
}
[Fact]
public async Task WriteLineReadOnlyMemoryAsync_TokenCanceled_ReturnsCanceledTask()
{
// Arrange
var stream = new TestMemoryStream();
var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8);
var memory = new ReadOnlyMemory<char>(new char[] { 'a' });
var cancellationToken = new CancellationToken(true);
// Act
using (writer)
{
await Assert.ThrowsAsync<TaskCanceledException>(async () => await writer.WriteLineAsync(memory, cancellationToken));
}
// Assert
Assert.Equal(0, stream.Length);
}
[Theory]
[InlineData(0, 1)]
[InlineData(1022, 1)]
[InlineData(1023, 1)]
[InlineData(1024, 1)]
[InlineData(1050, 1)]
[InlineData(2047, 1)]
[InlineData(2048, 1)]
[InlineData(1021, 2)]
[InlineData(1022, 2)]
[InlineData(1023, 2)]
[InlineData(1024, 2)]
[InlineData(1024, 1023)]
[InlineData(1024, 1024)]
[InlineData(1024, 1050)]
[InlineData(1050, 2)]
[InlineData(2046, 2)]
[InlineData(2048, 2)]
[InlineData(HttpResponseStreamWriter.DefaultBufferSize + 1, 1)]
[InlineData(HttpResponseStreamWriter.DefaultBufferSize + 1, 2)]
[InlineData(HttpResponseStreamWriter.DefaultBufferSize + 1, HttpResponseStreamWriter.DefaultBufferSize)]
public async Task WriteLineAsyncCharArray_WritesToStream(int charCount, int newLineLength)
{
// Arrange
var content = new char[charCount];
var stream = new TestMemoryStream();
var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8);
writer.NewLine = new string('\n', newLineLength);
// Act
using (writer)
{
await writer.WriteLineAsync(content, 0, charCount);
}
// Assert
Assert.Equal(charCount + newLineLength, stream.Length);
}
[Theory]
[InlineData(1)]
[InlineData(2)]
[InlineData(HttpResponseStreamWriter.DefaultBufferSize + 1)]
public async Task WriteLineAsyncCharArray_OnlyWritesNewLineToStream_ForNullArgument(int newLineLength)
{
// Arrange
char[]? content = null;
var stream = new TestMemoryStream();
var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8);
writer.NewLine = new string('\n', newLineLength);
// Act
using (writer)
{
await writer.WriteLineAsync(content!, 0, 0);
}
// Assert
Assert.Equal(newLineLength, stream.Length);
}
[Theory]
[InlineData(1)]
[InlineData(2)]
[InlineData(HttpResponseStreamWriter.DefaultBufferSize + 1)]
public async Task WriteLineAsyncCharArray_OnlyWritesNewLineToStream_ForZeroCount(int newLineLength)
{
// Arrange
var content = new char[1];
var stream = new TestMemoryStream();
var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8);
writer.NewLine = new string('\n', newLineLength);
// Act
using (writer)
{
await writer.WriteLineAsync(content, 0, 0);
}
// Assert
Assert.Equal(newLineLength, stream.Length);
}
[Theory]
[InlineData(0)]
[InlineData(1)]
[InlineData(2)]
[InlineData(HttpResponseStreamWriter.DefaultBufferSize - 1)]
[InlineData(HttpResponseStreamWriter.DefaultBufferSize)]
public async Task WriteLineAsyncChar_WritesToStream(int newLineLength)
{
// Arrange
var content = 'a';
var stream = new TestMemoryStream();
var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8);
writer.NewLine = new string('\n', newLineLength);
// Act
using (writer)
{
await writer.WriteLineAsync(content);
}
// Assert
Assert.Equal(newLineLength + 1, stream.Length);
}
[Theory]
[InlineData(0, 1)]
[InlineData(1022, 1)]
[InlineData(1023, 1)]
[InlineData(1024, 1)]
[InlineData(1050, 1)]
[InlineData(2047, 1)]
[InlineData(2048, 1)]
[InlineData(1021, 2)]
[InlineData(1022, 2)]
[InlineData(1023, 2)]
[InlineData(1024, 2)]
[InlineData(1024, 1023)]
[InlineData(1024, 1024)]
[InlineData(1024, 1050)]
[InlineData(1050, 2)]
[InlineData(2046, 2)]
[InlineData(2048, 2)]
[InlineData(HttpResponseStreamWriter.DefaultBufferSize + 1, 1)]
[InlineData(HttpResponseStreamWriter.DefaultBufferSize + 1, 2)]
[InlineData(HttpResponseStreamWriter.DefaultBufferSize + 1, HttpResponseStreamWriter.DefaultBufferSize)]
public async Task WriteLineAsyncString_WritesToStream(int charCount, int newLineLength)
{
// Arrange
var content = new string('a', charCount);
var stream = new TestMemoryStream();
var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8);
writer.NewLine = new string('\n', newLineLength);
// Act
using (writer)
{
await writer.WriteLineAsync(content);
}
// Assert
Assert.Equal(charCount + newLineLength, stream.Length);
}
[Theory]
[InlineData(1)]
[InlineData(2)]
[InlineData(HttpResponseStreamWriter.DefaultBufferSize + 1)]
public async Task WriteLineAsyncString_OnlyWritesNewLineToStream_ForNullArgument(int newLineLength)
{
// Arrange
string? content = null;
var stream = new TestMemoryStream();
var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8);
writer.NewLine = new string('\n', newLineLength);
// Act
using (writer)
{
await writer.WriteLineAsync(content);
}
// Assert
Assert.Equal(newLineLength, stream.Length);
}
[Theory]
[InlineData("你好世界", "utf-16")]
[InlineData("హలో ప్రపంచ", "iso-8859-1")]
[InlineData("வணக்கம் உலக", "utf-32")]
public async Task WritesData_InExpectedEncoding(string data, string encodingName)
{
// Arrange
var encoding = Encoding.GetEncoding(encodingName);
var expectedBytes = encoding.GetBytes(data);
var stream = new MemoryStream();
var writer = new HttpResponseStreamWriter(stream, encoding);
// Act
using (writer)
{
await writer.WriteAsync(data);
}
// Assert
Assert.Equal(expectedBytes, stream.ToArray());
}
[Theory]
[InlineData('ん', 1023, "utf-8")]
[InlineData('ん', 1024, "utf-8")]
[InlineData('ん', 1050, "utf-8")]
[InlineData('你', 1023, "utf-16")]
[InlineData('你', 1024, "utf-16")]
[InlineData('你', 1050, "utf-16")]
[InlineData('హ', 1023, "iso-8859-1")]
[InlineData('హ', 1024, "iso-8859-1")]
[InlineData('హ', 1050, "iso-8859-1")]
[InlineData('வ', 1023, "utf-32")]
[InlineData('வ', 1024, "utf-32")]
[InlineData('வ', 1050, "utf-32")]
public async Task WritesData_OfDifferentLength_InExpectedEncoding(
char character,
int charCount,
string encodingName)
{
// Arrange
var encoding = Encoding.GetEncoding(encodingName);
string data = new string(character, charCount);
var expectedBytes = encoding.GetBytes(data);
var stream = new MemoryStream();
var writer = new HttpResponseStreamWriter(stream, encoding);
// Act
using (writer)
{
await writer.WriteAsync(data);
}
// Assert
Assert.Equal(expectedBytes, stream.ToArray());
}
// None of the code in HttpResponseStreamWriter differs significantly when using pooled buffers.
//
// This test effectively verifies that things are correctly constructed and disposed. Pooled buffers
// throw on the finalizer thread if not disposed, so that's why it's complicated.
[Fact]
public void HttpResponseStreamWriter_UsingPooledBuffers()
{
// Arrange
var encoding = Encoding.UTF8;
var stream = new MemoryStream();
var expectedBytes = encoding.GetBytes("Hello, World!");
using (var writer = new HttpResponseStreamWriter(
stream,
encoding,
1024,
ArrayPool<byte>.Shared,
ArrayPool<char>.Shared))
{
// Act
writer.Write("Hello, World!");
}
// Assert
Assert.Equal(expectedBytes, stream.ToArray());
}
[Theory]
[InlineData(DefaultCharacterChunkSize)]
[InlineData(DefaultCharacterChunkSize * 2)]
[InlineData(DefaultCharacterChunkSize * 3)]
public async Task HttpResponseStreamWriter_WritesDataCorrectly_ForCharactersHavingSurrogatePairs(int characterSize)
{
// Arrange
// Here "𐐀" (called Deseret Long I) actually represents 2 characters. Try to make this character split across
// the boundary
var content = new string('a', characterSize - 1) + "𐐀";
var stream = new TestMemoryStream();
var writer = new HttpResponseStreamWriter(stream, Encoding.Unicode);
// Act
await writer.WriteAsync(content);
await writer.FlushAsync();
// Assert
stream.Seek(0, SeekOrigin.Begin);
var streamReader = new StreamReader(stream, Encoding.Unicode);
var actualContent = await streamReader.ReadToEndAsync();
Assert.Equal(content, actualContent);
}
[Theory]
[MemberData(nameof(HttpResponseStreamWriterData))]
public static void NullInputsInConstructor_ExpectArgumentNullException(Stream stream, Encoding encoding, ArrayPool<byte> bytePool, ArrayPool<char> charPool)
{
Assert.Throws<ArgumentNullException>(() =>
{
var httpRequestStreamReader = new HttpResponseStreamWriter(stream, encoding, 1, bytePool, charPool);
});
}
[Theory]
[InlineData(0)]
[InlineData(-1)]
public static void NegativeOrZeroBufferSize_ExpectArgumentOutOfRangeException(int size)
{
Assert.Throws<ArgumentOutOfRangeException>(() =>
{
var httpRequestStreamReader = new HttpRequestStreamReader(new MemoryStream(), Encoding.UTF8, size, ArrayPool<byte>.Shared, ArrayPool<char>.Shared);
});
}
[Fact]
public static void StreamCannotRead_ExpectArgumentException()
{
var mockStream = new Mock<Stream>();
mockStream.Setup(m => m.CanWrite).Returns(false);
Assert.Throws<ArgumentException>(() =>
{
var httpRequestStreamReader = new HttpRequestStreamReader(mockStream.Object, Encoding.UTF8, 1, ArrayPool<byte>.Shared, ArrayPool<char>.Shared);
});
}
[Theory]
[MemberData(nameof(HttpResponseDisposeData))]
public static void StreamDisposed_ExpectedObjectDisposedException(Action<HttpResponseStreamWriter> action)
{
var httpResponseStreamWriter = new HttpResponseStreamWriter(new MemoryStream(), Encoding.UTF8, 10, ArrayPool<byte>.Shared, ArrayPool<char>.Shared);
httpResponseStreamWriter.Dispose();
Assert.Throws<ObjectDisposedException>(() =>
{
action(httpResponseStreamWriter);
});
}
[Theory]
[MemberData(nameof(HttpResponseDisposeDataAsync))]
public static async Task StreamDisposed_ExpectedObjectDisposedExceptionAsync(Func<HttpResponseStreamWriter, Task> function)
{
var httpResponseStreamWriter = new HttpResponseStreamWriter(new MemoryStream(), Encoding.UTF8, 10, ArrayPool<byte>.Shared, ArrayPool<char>.Shared);
httpResponseStreamWriter.Dispose();
await Assert.ThrowsAsync<ObjectDisposedException>(() =>
{
return function(httpResponseStreamWriter);
});
}
private class TestMemoryStream : MemoryStream
{
public int FlushCallCount { get; private set; }
public int FlushAsyncCallCount { get; private set; }
public int CloseCallCount { get; private set; }
public int DisposeCallCount { get; private set; }
public int WriteCallCount { get; private set; }
public int WriteAsyncCallCount { get; private set; }
public bool ThrowOnWrite { get; set; }
public override void Flush()
{
FlushCallCount++;
base.Flush();
}
public override Task FlushAsync(CancellationToken cancellationToken)
{
FlushAsyncCallCount++;
return base.FlushAsync(cancellationToken);
}
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)
=> WriteAsync(buffer.AsMemory(offset, count), cancellationToken).AsTask();
public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default)
{
WriteAsyncCallCount++;
if (ThrowOnWrite)
{
throw new IOException("Test IOException");
}
return base.WriteAsync(buffer, cancellationToken);
}
protected override void Dispose(bool disposing)
{
DisposeCallCount++;
base.Dispose(disposing);
}
}
public static IEnumerable<object?[]> HttpResponseStreamWriterData()
{
yield return new object?[] { null, Encoding.UTF8, ArrayPool<byte>.Shared, ArrayPool<char>.Shared };
yield return new object?[] { new MemoryStream(), null, ArrayPool<byte>.Shared, ArrayPool<char>.Shared };
yield return new object?[] { new MemoryStream(), Encoding.UTF8, null, ArrayPool<char>.Shared };
yield return new object?[] { new MemoryStream(), Encoding.UTF8, ArrayPool<byte>.Shared, null };
}
public static IEnumerable<object[]> HttpResponseDisposeData()
{
yield return new object[] { new Action<HttpResponseStreamWriter>((httpResponseStreamWriter) =>
{
httpResponseStreamWriter.Write('a');
})};
yield return new object[] { new Action<HttpResponseStreamWriter>((httpResponseStreamWriter) =>
{
httpResponseStreamWriter.Write(new char[] { 'a', 'b' }, 0, 1);
})};
yield return new object[] { new Action<HttpResponseStreamWriter>((httpResponseStreamWriter) =>
{
httpResponseStreamWriter.Write("hello");
})};
yield return new object[] { new Action<HttpResponseStreamWriter>((httpResponseStreamWriter) =>
{
httpResponseStreamWriter.Write(new ReadOnlySpan<char>(new char[] { 'a', 'b' }));
})};
yield return new object[] { new Action<HttpResponseStreamWriter>((httpResponseStreamWriter) =>
{
httpResponseStreamWriter.Flush();
})};
}
public static IEnumerable<object[]> HttpResponseDisposeDataAsync()
{
yield return new object[] { new Func<HttpResponseStreamWriter, Task>(async (httpResponseStreamWriter) =>
{
await httpResponseStreamWriter.WriteAsync('a');
})};
yield return new object[] { new Func<HttpResponseStreamWriter, Task>(async (httpResponseStreamWriter) =>
{
await httpResponseStreamWriter.WriteAsync(new char[] { 'a', 'b' }, 0, 1);
})};
yield return new object[] { new Func<HttpResponseStreamWriter, Task>(async (httpResponseStreamWriter) =>
{
await httpResponseStreamWriter.WriteAsync("hello");
})};
yield return new object[] { new Func<HttpResponseStreamWriter, Task>(async (httpResponseStreamWriter) =>
{
await httpResponseStreamWriter.WriteAsync(new ReadOnlyMemory<char>(new char[] { 'a', 'b' }));
})};
yield return new object[] { new Func<HttpResponseStreamWriter, Task>(async (httpResponseStreamWriter) =>
{
await httpResponseStreamWriter.WriteLineAsync(new ReadOnlyMemory<char>(new char[] { 'a', 'b' }));
})};
yield return new object[] { new Func<HttpResponseStreamWriter, Task>(async (httpResponseStreamWriter) =>
{
await httpResponseStreamWriter.WriteLineAsync(new char[] { 'a', 'b' }, 0, 1);
})};
yield return new object[] { new Func<HttpResponseStreamWriter, Task>(async (httpResponseStreamWriter) =>
{
await httpResponseStreamWriter.WriteLineAsync('a');
})};
yield return new object[] { new Func<HttpResponseStreamWriter, Task>(async (httpResponseStreamWriter) =>
{
await httpResponseStreamWriter.WriteLineAsync("hello");
})};
yield return new object[] { new Func<HttpResponseStreamWriter, Task>(async (httpResponseStreamWriter) =>
{
await httpResponseStreamWriter.FlushAsync();
})};
}
}
|