protected override async Task <Stream> CreateReadOnlyStreamCore(byte[] initialData) { (Stream httpConnection, Stream server) = ConnectedStreams.CreateBidirectional(4096, int.MaxValue); using var hc = new HttpClient(new SocketsHttpHandler() { ConnectCallback = delegate { return(ValueTask.FromResult(httpConnection)); } }); Task <Stream> clientTask = hc.GetStreamAsync($"http://doesntmatter:12345/"); await ResponseConnectedStreamConformanceTests.ReadHeadersAsync(server); initialData ??= Array.Empty <byte>(); await WriteResponseAsync(server, initialData); server.Dispose(); return(await clientTask); }
public async Task ZeroByteRead_IssuesZeroByteReadOnUnderlyingStream(StreamConformanceTests.ReadWriteMode readMode, bool useSsl) { (Stream httpConnection, Stream server) = ConnectedStreams.CreateBidirectional(4096, int.MaxValue); try { var sawZeroByteRead = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); httpConnection = new ReadInterceptStream(httpConnection, read => { if (read == 0) { sawZeroByteRead.TrySetResult(); } }); using var handler = new SocketsHttpHandler { ConnectCallback = delegate { return(ValueTask.FromResult(httpConnection)); } }; handler.SslOptions.RemoteCertificateValidationCallback = delegate { return(true); }; using var client = new HttpClient(handler); Task <HttpResponseMessage> clientTask = client.GetAsync($"http{(useSsl ? "s" : "")}://doesntmatter", HttpCompletionOption.ResponseHeadersRead); if (useSsl) { var sslStream = new SslStream(server, false, delegate { return(true); }); server = sslStream; using (X509Certificate2 cert = Test.Common.Configuration.Certificates.GetServerCertificate()) { await((SslStream)server).AuthenticateAsServerAsync( cert, clientCertificateRequired: true, enabledSslProtocols: SslProtocols.Tls12, checkCertificateRevocation: false).WaitAsync(TimeSpan.FromSeconds(10)); } } await ResponseConnectedStreamConformanceTests.ReadHeadersAsync(server).WaitAsync(TimeSpan.FromSeconds(10)); await server.WriteAsync(Encoding.ASCII.GetBytes(GetResponseHeaders())); using HttpResponseMessage response = await clientTask.WaitAsync(TimeSpan.FromSeconds(10)); using Stream clientStream = response.Content.ReadAsStream(); Assert.False(sawZeroByteRead.Task.IsCompleted); Task <int> zeroByteReadTask = Task.Run(() => StreamConformanceTests.ReadAsync(readMode, clientStream, Array.Empty <byte>(), 0, 0, CancellationToken.None)); Assert.False(zeroByteReadTask.IsCompleted); // The zero-byte read should block until data is actually available await sawZeroByteRead.Task.WaitAsync(TimeSpan.FromSeconds(10)); Assert.False(zeroByteReadTask.IsCompleted); byte[] data = "Hello" u8.ToArray(); await WriteAsync(server, data); await server.FlushAsync(); Assert.Equal(0, await zeroByteReadTask.WaitAsync(TimeSpan.FromSeconds(10))); // Now that data is available, a zero-byte read should complete synchronously zeroByteReadTask = StreamConformanceTests.ReadAsync(readMode, clientStream, Array.Empty <byte>(), 0, 0, CancellationToken.None); Assert.True(zeroByteReadTask.IsCompleted); Assert.Equal(0, await zeroByteReadTask); var readBuffer = new byte[10]; int read = 0; while (read < data.Length) { read += await StreamConformanceTests.ReadAsync(readMode, clientStream, readBuffer, read, readBuffer.Length - read, CancellationToken.None).WaitAsync(TimeSpan.FromSeconds(10)); } Assert.Equal(data.Length, read); Assert.Equal(data, readBuffer.AsSpan(0, read).ToArray()); } finally { httpConnection.Dispose(); server.Dispose(); } }