Skip to content

Commit

Permalink
[wasm] browser http response stream could be seekable (#54603)
Browse files Browse the repository at this point in the history
- browser http response stream could be seekable
- test WebAssemblyEnableStreamingResponse
  • Loading branch information
pavelsavara committed Jun 25, 2021
1 parent e9f101c commit c139d00
Showing 1 changed file with 101 additions and 54 deletions.
155 changes: 101 additions & 54 deletions src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -937,7 +937,6 @@ await connection.WriteStringAsync(
[InlineData(true)]
[InlineData(false)]
[InlineData(null)]
[ActiveIssue("https://github.com/dotnet/runtime/issues/54159", TestPlatforms.Browser)]
public async Task ReadAsStreamAsync_HandlerProducesWellBehavedResponseStream(bool? chunked)
{
if (IsWinHttpHandler && UseVersion >= HttpVersion20.Value)
Expand All @@ -960,6 +959,11 @@ public async Task ReadAsStreamAsync_HandlerProducesWellBehavedResponseStream(boo
await LoopbackServerFactory.CreateClientAndServerAsync(async uri =>
{
var request = new HttpRequestMessage(HttpMethod.Get, uri) { Version = UseVersion };
if (PlatformDetection.IsBrowser)
{
request.Options.Set(new HttpRequestOptionsKey<bool>("WebAssemblyEnableStreamingResponse"), true);
}
using (var client = new HttpMessageInvoker(CreateHttpClientHandler()))
using (HttpResponseMessage response = await client.SendAsync(TestAsync, request, CancellationToken.None))
{
Expand All @@ -974,17 +978,20 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri =>
// Not supported operations
Assert.Throws<NotSupportedException>(() => responseStream.BeginWrite(new byte[1], 0, 1, null, null));
Assert.Throws<NotSupportedException>(() => responseStream.Length);
Assert.Throws<NotSupportedException>(() => responseStream.Position);
Assert.Throws<NotSupportedException>(() => responseStream.Position = 0);
Assert.Throws<NotSupportedException>(() => responseStream.Seek(0, SeekOrigin.Begin));
if (!responseStream.CanSeek)
{
Assert.Throws<NotSupportedException>(() => responseStream.Length);
Assert.Throws<NotSupportedException>(() => responseStream.Position);
Assert.Throws<NotSupportedException>(() => responseStream.Position = 0);
Assert.Throws<NotSupportedException>(() => responseStream.Seek(0, SeekOrigin.Begin));
}
Assert.Throws<NotSupportedException>(() => responseStream.SetLength(0));
Assert.Throws<NotSupportedException>(() => responseStream.Write(new byte[1], 0, 1));
#if !NETFRAMEWORK
Assert.Throws<NotSupportedException>(() => responseStream.Write(new Span<byte>(new byte[1])));
Assert.Throws<NotSupportedException>(() => { responseStream.WriteAsync(new Memory<byte>(new byte[1])); });
await Assert.ThrowsAsync<NotSupportedException>(async () => await responseStream.WriteAsync(new Memory<byte>(new byte[1])));
#endif
Assert.Throws<NotSupportedException>(() => { responseStream.WriteAsync(new byte[1], 0, 1); });
await Assert.ThrowsAsync<NotSupportedException>(async () => await responseStream.WriteAsync(new byte[1], 0, 1));
Assert.Throws<NotSupportedException>(() => responseStream.WriteByte(1));
// Invalid arguments
Expand All @@ -998,11 +1005,14 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri =>
Assert.Throws<ArgumentOutOfRangeException>(() => { responseStream.CopyToAsync(Stream.Null, -1, default); });
Assert.Throws<NotSupportedException>(() => { responseStream.CopyToAsync(nonWritableStream, 100, default); });
Assert.Throws<ObjectDisposedException>(() => { responseStream.CopyToAsync(disposedStream, 100, default); });
Assert.Throws<ArgumentNullException>(() => responseStream.Read(null, 0, 100));
Assert.Throws<ArgumentOutOfRangeException>(() => responseStream.Read(new byte[1], -1, 1));
Assert.ThrowsAny<ArgumentException>(() => responseStream.Read(new byte[1], 2, 1));
Assert.Throws<ArgumentOutOfRangeException>(() => responseStream.Read(new byte[1], 0, -1));
Assert.ThrowsAny<ArgumentException>(() => responseStream.Read(new byte[1], 0, 2));
if (PlatformDetection.IsNotBrowser)
{
Assert.Throws<ArgumentNullException>(() => responseStream.Read(null, 0, 100));
Assert.Throws<ArgumentOutOfRangeException>(() => responseStream.Read(new byte[1], -1, 1));
Assert.ThrowsAny<ArgumentException>(() => responseStream.Read(new byte[1], 2, 1));
Assert.Throws<ArgumentOutOfRangeException>(() => responseStream.Read(new byte[1], 0, -1));
Assert.ThrowsAny<ArgumentException>(() => responseStream.Read(new byte[1], 0, 2));
}
Assert.Throws<ArgumentNullException>(() => responseStream.BeginRead(null, 0, 100, null, null));
Assert.Throws<ArgumentOutOfRangeException>(() => responseStream.BeginRead(new byte[1], -1, 1, null, null));
Assert.ThrowsAny<ArgumentException>(() => responseStream.BeginRead(new byte[1], 2, 1, null, null));
Expand All @@ -1018,62 +1028,97 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri =>
// Various forms of reading
var buffer = new byte[1];
Assert.Equal('h', responseStream.ReadByte());
if (PlatformDetection.IsBrowser)
{
Assert.Equal('h', await responseStream.ReadByteAsync());
Assert.Equal('e', await responseStream.ReadByteAsync());
Assert.Equal(1, await responseStream.ReadAsync(new Memory<byte>(buffer)));
Assert.Equal((byte)'l', buffer[0]);
Assert.Equal(1, await responseStream.ReadAsync(buffer, 0, 1));
Assert.Equal((byte)'l', buffer[0]);
Assert.Equal(1, await responseStream.ReadAsync(buffer));
Assert.Equal((byte)'o', buffer[0]);
Assert.Equal(1, await responseStream.ReadAsync(buffer, 0, 1));
Assert.Equal((byte)' ', buffer[0]);
// Doing any of these 0-byte reads causes the connection to fail.
Assert.Equal(0, await responseStream.ReadAsync(Memory<byte>.Empty));
Assert.Equal(0, await responseStream.ReadAsync(Array.Empty<byte>(), 0, 0));
// And copying
var ms = new MemoryStream();
await responseStream.CopyToAsync(ms);
Assert.Equal("world", Encoding.ASCII.GetString(ms.ToArray()));
// Read and copy again once we've exhausted all data
ms = new MemoryStream();
await responseStream.CopyToAsync(ms);
Assert.Equal(0, ms.Length);
Assert.Equal(0, await responseStream.ReadAsync(buffer, 0, 1));
Assert.Equal(0, await responseStream.ReadAsync(new Memory<byte>(buffer)));
}
else
{
Assert.Equal('h', responseStream.ReadByte());
Assert.Equal(1, await Task.Factory.FromAsync(responseStream.BeginRead, responseStream.EndRead, buffer, 0, 1, null));
Assert.Equal((byte)'e', buffer[0]);
Assert.Equal(1, await Task.Factory.FromAsync(responseStream.BeginRead, responseStream.EndRead, buffer, 0, 1, null));
Assert.Equal((byte)'e', buffer[0]);
#if !NETFRAMEWORK
Assert.Equal(1, await responseStream.ReadAsync(new Memory<byte>(buffer)));
Assert.Equal(1, await responseStream.ReadAsync(new Memory<byte>(buffer)));
#else
Assert.Equal(1, await responseStream.ReadAsync(buffer, 0, 1));
Assert.Equal(1, await responseStream.ReadAsync(buffer, 0, 1));
#endif
Assert.Equal((byte)'l', buffer[0]);
Assert.Equal((byte)'l', buffer[0]);
Assert.Equal(1, await responseStream.ReadAsync(buffer, 0, 1));
Assert.Equal((byte)'l', buffer[0]);
Assert.Equal(1, await responseStream.ReadAsync(buffer, 0, 1));
Assert.Equal((byte)'l', buffer[0]);
#if !NETFRAMEWORK
Assert.Equal(1, responseStream.Read(new Span<byte>(buffer)));
Assert.Equal(1, responseStream.Read(new Span<byte>(buffer)));
#else
Assert.Equal(1, await responseStream.ReadAsync(buffer, 0, 1));
Assert.Equal(1, await responseStream.ReadAsync(buffer, 0, 1));
#endif
Assert.Equal((byte)'o', buffer[0]);
Assert.Equal((byte)'o', buffer[0]);
Assert.Equal(1, responseStream.Read(buffer, 0, 1));
Assert.Equal((byte)' ', buffer[0]);
Assert.Equal(1, responseStream.Read(buffer, 0, 1));
Assert.Equal((byte)' ', buffer[0]);
// Doing any of these 0-byte reads causes the connection to fail.
Assert.Equal(0, await Task.Factory.FromAsync(responseStream.BeginRead, responseStream.EndRead, Array.Empty<byte>(), 0, 0, null));
// Doing any of these 0-byte reads causes the connection to fail.
Assert.Equal(0, await Task.Factory.FromAsync(responseStream.BeginRead, responseStream.EndRead, Array.Empty<byte>(), 0, 0, null));
#if !NETFRAMEWORK
Assert.Equal(0, await responseStream.ReadAsync(Memory<byte>.Empty));
Assert.Equal(0, await responseStream.ReadAsync(Memory<byte>.Empty));
#endif
Assert.Equal(0, await responseStream.ReadAsync(Array.Empty<byte>(), 0, 0));
Assert.Equal(0, await responseStream.ReadAsync(Array.Empty<byte>(), 0, 0));
#if !NETFRAMEWORK
Assert.Equal(0, responseStream.Read(Span<byte>.Empty));
Assert.Equal(0, responseStream.Read(Span<byte>.Empty));
#endif
Assert.Equal(0, responseStream.Read(Array.Empty<byte>(), 0, 0));
// And copying
var ms = new MemoryStream();
await responseStream.CopyToAsync(ms);
Assert.Equal("world", Encoding.ASCII.GetString(ms.ToArray()));
// Read and copy again once we've exhausted all data
ms = new MemoryStream();
await responseStream.CopyToAsync(ms);
responseStream.CopyTo(ms);
Assert.Equal(0, ms.Length);
Assert.Equal(-1, responseStream.ReadByte());
Assert.Equal(0, responseStream.Read(buffer, 0, 1));
Assert.Equal(0, responseStream.Read(Array.Empty<byte>(), 0, 0));
// And copying
var ms = new MemoryStream();
await responseStream.CopyToAsync(ms);
Assert.Equal("world", Encoding.ASCII.GetString(ms.ToArray()));
// Read and copy again once we've exhausted all data
ms = new MemoryStream();
await responseStream.CopyToAsync(ms);
responseStream.CopyTo(ms);
Assert.Equal(0, ms.Length);
Assert.Equal(-1, responseStream.ReadByte());
Assert.Equal(0, responseStream.Read(buffer, 0, 1));
#if !NETFRAMEWORK
Assert.Equal(0, responseStream.Read(new Span<byte>(buffer)));
Assert.Equal(0, responseStream.Read(new Span<byte>(buffer)));
#endif
Assert.Equal(0, await responseStream.ReadAsync(buffer, 0, 1));
Assert.Equal(0, await responseStream.ReadAsync(buffer, 0, 1));
#if !NETFRAMEWORK
Assert.Equal(0, await responseStream.ReadAsync(new Memory<byte>(buffer)));
Assert.Equal(0, await responseStream.ReadAsync(new Memory<byte>(buffer)));
#endif
Assert.Equal(0, await Task.Factory.FromAsync(responseStream.BeginRead, responseStream.EndRead, buffer, 0, 1, null));
Assert.Equal(0, await Task.Factory.FromAsync(responseStream.BeginRead, responseStream.EndRead, buffer, 0, 1, null));
}
}
}
}, async server =>
Expand Down Expand Up @@ -1103,7 +1148,6 @@ await server.AcceptConnectionAsync(async connection =>
}

[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/54159", TestPlatforms.Browser)]
public async Task ReadAsStreamAsync_EmptyResponseBody_HandlerProducesWellBehavedResponseStream()
{
if (IsWinHttpHandler && UseVersion >= HttpVersion20.Value)
Expand All @@ -1123,14 +1167,17 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri =>
// Boolean properties returning correct values
Assert.True(responseStream.CanRead);
Assert.False(responseStream.CanWrite);
Assert.False(responseStream.CanSeek);
Assert.Equal(PlatformDetection.IsBrowser, responseStream.CanSeek);
// Not supported operations
Assert.Throws<NotSupportedException>(() => responseStream.BeginWrite(new byte[1], 0, 1, null, null));
Assert.Throws<NotSupportedException>(() => responseStream.Length);
Assert.Throws<NotSupportedException>(() => responseStream.Position);
Assert.Throws<NotSupportedException>(() => responseStream.Position = 0);
Assert.Throws<NotSupportedException>(() => responseStream.Seek(0, SeekOrigin.Begin));
if (!responseStream.CanSeek)
{
Assert.Throws<NotSupportedException>(() => responseStream.Length);
Assert.Throws<NotSupportedException>(() => responseStream.Position);
Assert.Throws<NotSupportedException>(() => responseStream.Position = 0);
Assert.Throws<NotSupportedException>(() => responseStream.Seek(0, SeekOrigin.Begin));
}
Assert.Throws<NotSupportedException>(() => responseStream.SetLength(0));
Assert.Throws<NotSupportedException>(() => responseStream.Write(new byte[1], 0, 1));
#if !NETFRAMEWORK
Expand Down

0 comments on commit c139d00

Please sign in to comment.