From c139d00640485e8c231c54d1573dc02d7c9e8daf Mon Sep 17 00:00:00 2001 From: Pavel Savara Date: Fri, 25 Jun 2021 10:56:28 +0200 Subject: [PATCH] [wasm] browser http response stream could be seekable (#54603) - browser http response stream could be seekable - test WebAssemblyEnableStreamingResponse --- .../tests/System/Net/Http/HttpClientHandlerTest.cs | 155 ++++++++++++++------- 1 file changed, 101 insertions(+), 54 deletions(-) diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs index 912f356..44dfc1a 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs @@ -937,7 +937,6 @@ namespace System.Net.Http.Functional.Tests [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) @@ -960,6 +959,11 @@ namespace System.Net.Http.Functional.Tests await LoopbackServerFactory.CreateClientAndServerAsync(async uri => { var request = new HttpRequestMessage(HttpMethod.Get, uri) { Version = UseVersion }; + if (PlatformDetection.IsBrowser) + { + request.Options.Set(new HttpRequestOptionsKey("WebAssemblyEnableStreamingResponse"), true); + } + using (var client = new HttpMessageInvoker(CreateHttpClientHandler())) using (HttpResponseMessage response = await client.SendAsync(TestAsync, request, CancellationToken.None)) { @@ -974,17 +978,20 @@ namespace System.Net.Http.Functional.Tests // Not supported operations Assert.Throws(() => responseStream.BeginWrite(new byte[1], 0, 1, null, null)); - Assert.Throws(() => responseStream.Length); - Assert.Throws(() => responseStream.Position); - Assert.Throws(() => responseStream.Position = 0); - Assert.Throws(() => responseStream.Seek(0, SeekOrigin.Begin)); + if (!responseStream.CanSeek) + { + Assert.Throws(() => responseStream.Length); + Assert.Throws(() => responseStream.Position); + Assert.Throws(() => responseStream.Position = 0); + Assert.Throws(() => responseStream.Seek(0, SeekOrigin.Begin)); + } Assert.Throws(() => responseStream.SetLength(0)); Assert.Throws(() => responseStream.Write(new byte[1], 0, 1)); #if !NETFRAMEWORK Assert.Throws(() => responseStream.Write(new Span(new byte[1]))); - Assert.Throws(() => { responseStream.WriteAsync(new Memory(new byte[1])); }); + await Assert.ThrowsAsync(async () => await responseStream.WriteAsync(new Memory(new byte[1]))); #endif - Assert.Throws(() => { responseStream.WriteAsync(new byte[1], 0, 1); }); + await Assert.ThrowsAsync(async () => await responseStream.WriteAsync(new byte[1], 0, 1)); Assert.Throws(() => responseStream.WriteByte(1)); // Invalid arguments @@ -998,11 +1005,14 @@ namespace System.Net.Http.Functional.Tests Assert.Throws(() => { responseStream.CopyToAsync(Stream.Null, -1, default); }); Assert.Throws(() => { responseStream.CopyToAsync(nonWritableStream, 100, default); }); Assert.Throws(() => { responseStream.CopyToAsync(disposedStream, 100, default); }); - Assert.Throws(() => responseStream.Read(null, 0, 100)); - Assert.Throws(() => responseStream.Read(new byte[1], -1, 1)); - Assert.ThrowsAny(() => responseStream.Read(new byte[1], 2, 1)); - Assert.Throws(() => responseStream.Read(new byte[1], 0, -1)); - Assert.ThrowsAny(() => responseStream.Read(new byte[1], 0, 2)); + if (PlatformDetection.IsNotBrowser) + { + Assert.Throws(() => responseStream.Read(null, 0, 100)); + Assert.Throws(() => responseStream.Read(new byte[1], -1, 1)); + Assert.ThrowsAny(() => responseStream.Read(new byte[1], 2, 1)); + Assert.Throws(() => responseStream.Read(new byte[1], 0, -1)); + Assert.ThrowsAny(() => responseStream.Read(new byte[1], 0, 2)); + } Assert.Throws(() => responseStream.BeginRead(null, 0, 100, null, null)); Assert.Throws(() => responseStream.BeginRead(new byte[1], -1, 1, null, null)); Assert.ThrowsAny(() => responseStream.BeginRead(new byte[1], 2, 1, null, null)); @@ -1018,62 +1028,97 @@ namespace System.Net.Http.Functional.Tests // 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(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.Empty)); + Assert.Equal(0, await responseStream.ReadAsync(Array.Empty(), 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(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(buffer))); + Assert.Equal(1, await responseStream.ReadAsync(new Memory(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(buffer))); + Assert.Equal(1, responseStream.Read(new Span(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(), 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(), 0, 0, null)); #if !NETFRAMEWORK - Assert.Equal(0, await responseStream.ReadAsync(Memory.Empty)); + Assert.Equal(0, await responseStream.ReadAsync(Memory.Empty)); #endif - Assert.Equal(0, await responseStream.ReadAsync(Array.Empty(), 0, 0)); + Assert.Equal(0, await responseStream.ReadAsync(Array.Empty(), 0, 0)); #if !NETFRAMEWORK - Assert.Equal(0, responseStream.Read(Span.Empty)); + Assert.Equal(0, responseStream.Read(Span.Empty)); #endif - Assert.Equal(0, responseStream.Read(Array.Empty(), 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(), 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(buffer))); + Assert.Equal(0, responseStream.Read(new Span(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(buffer))); + Assert.Equal(0, await responseStream.ReadAsync(new Memory(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 => @@ -1103,7 +1148,6 @@ namespace System.Net.Http.Functional.Tests } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/54159", TestPlatforms.Browser)] public async Task ReadAsStreamAsync_EmptyResponseBody_HandlerProducesWellBehavedResponseStream() { if (IsWinHttpHandler && UseVersion >= HttpVersion20.Value) @@ -1123,14 +1167,17 @@ namespace System.Net.Http.Functional.Tests // 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(() => responseStream.BeginWrite(new byte[1], 0, 1, null, null)); - Assert.Throws(() => responseStream.Length); - Assert.Throws(() => responseStream.Position); - Assert.Throws(() => responseStream.Position = 0); - Assert.Throws(() => responseStream.Seek(0, SeekOrigin.Begin)); + if (!responseStream.CanSeek) + { + Assert.Throws(() => responseStream.Length); + Assert.Throws(() => responseStream.Position); + Assert.Throws(() => responseStream.Position = 0); + Assert.Throws(() => responseStream.Seek(0, SeekOrigin.Begin)); + } Assert.Throws(() => responseStream.SetLength(0)); Assert.Throws(() => responseStream.Write(new byte[1], 0, 1)); #if !NETFRAMEWORK -- 2.7.4