public async Task ConnectionShouldCloseAndSignalDoneInCaseOfAProtocolError(bool isServer) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var http2Con = await ConnectionUtils.BuildEstablishedConnection( isServer, inPipe, outPipe, loggerProvider); // Cause a protocol error var fh = new FrameHeader { Type = FrameType.Data, StreamId = 0u, Flags = 0, Length = 0, }; await inPipe.WriteFrameHeader(fh); await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 0u); await outPipe.AssertStreamEnd(); await inPipe.CloseAsync(); // Expect the connection to close within timeout var closed = http2Con.Done; Assert.True( closed == await Task.WhenAny(closed, Task.Delay(1000)), "Expected connection to close"); }
public async Task ConnectionShouldCloseAndSignalDoneWhenReadingFromInputFails(bool isServer) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var failableInPipe = new FailingPipe(inPipe); var http2Con = await ConnectionUtils.BuildEstablishedConnection( isServer, failableInPipe, outPipe, loggerProvider); // Make the next write attempt fail failableInPipe.FailNextRead = true; // Send something which triggers no response but will start a new read call await inPipe.WriteWindowUpdate(0, 128); // Wait for the connection to close the outgoing part await outPipe.AssertStreamEnd(); // If the connection was successfully closed close the incoming data // stream, since this is expected from a bidirectional stream implementation await inPipe.CloseAsync(); // Expect the connection to close within timeout var closed = http2Con.Done; Assert.True( closed == await Task.WhenAny(closed, Task.Delay(1000)), "Expected connection to close"); }
public async Task ConnectionShouldCloseAndStreamsShouldGetResetWhenExternalCloseIsRequested() { // TODO: Add a variant of this test for clients as soon as they are supported var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var res = await ServerStreamTests.StreamCreator.CreateConnectionAndStream( StreamState.Open, loggerProvider, inPipe, outPipe); // Close the connection var closeTask = res.conn.CloseNow(); // Expect end of stream await outPipe.AssertStreamEnd(); // If the connection was successfully closed close the incoming data // stream, since this is expected from a bidirectional stream implementation await inPipe.CloseAsync(); // Close should now be completed await closeTask; // The stream should be reset Assert.Equal(StreamState.Reset, res.stream.State); // Which also means that further writes/reads should fail await Assert.ThrowsAsync <StreamResetException>(async() => { await res.stream.WriteHeadersAsync( TestHeaders.DefaultStatusHeaders, true); }); await Assert.ThrowsAsync <StreamResetException>(async() => { await res.stream.ReadAllToArray(); }); }
public async Task PingShouldFailWhenConnectionIsClosedAfterPingStart() { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var http2Con = await ConnectionUtils.BuildEstablishedConnection( true, inPipe, outPipe, loggerProvider); // Request ping var pingTask = http2Con.PingAsync(); // Expect ping emission var fh = await outPipe.ReadFrameHeaderWithTimeout(); Assert.Equal(FrameType.Ping, fh.Type); Assert.Equal(8, fh.Length); Assert.Equal(0, fh.Flags); Assert.Equal(0u, fh.StreamId); var pingData = new ArraySegment <byte>(new byte[8]); await outPipe.ReadAllWithTimeout(pingData); // Close the connection await inPipe.CloseAsync(); await outPipe.AssertStreamEnd(); // Await ping to finish with exception var timeoutTask = Task.Delay(200); Assert.True( pingTask == await Task.WhenAny(pingTask, timeoutTask), "Expected pingTask to finish"); await Assert.ThrowsAsync <ConnectionClosedException>( async() => await pingTask); }
public async Task ConnectionShouldCloseAndSignalDoneWhenWritingToOutputFails(bool isServer) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var failableOutPipe = new FailingPipe(outPipe); var http2Con = await ConnectionUtils.BuildEstablishedConnection( isServer, inPipe, failableOutPipe, loggerProvider); // Make the next write attempt fail failableOutPipe.FailNextWrite = true; // Send something which triggers a response await inPipe.WritePing(new byte[8], false); // Wait for the connection to close the outgoing part await outPipe.AssertStreamEnd(); Assert.True(failableOutPipe.CloseCalled); // If the connection was successfully closed close the incoming data // stream, since this is expected from a bidirectional stream implementation await inPipe.CloseAsync(); // Expect the connection to close within timeout var closed = http2Con.Done; Assert.True( closed == await Task.WhenAny(closed, Task.Delay(1000)), "Expected connection to close"); }
public async Task CloseShouldUnblockReads() { var p = new BufferedPipe(128); var input = new byte[70]; var output = new byte[50]; for (var i = 0; i < 70; i++) { input[i] = (byte)i; } // Start read first var task = p.ReadAsync(new ArraySegment <byte>(output)).AsTask(); // Schedule close var writeTask = Task.Run(async() => { await Task.Delay(10); await p.CloseAsync(); }); // And wait for read to unblock var res = await task; Assert.Equal(true, res.EndOfStream); Assert.Equal(0, res.BytesRead); // The writeTask should also finish await writeTask; }
public async Task WritingOnOneEndShallYieldInDataOnTheOtherEnd() { var p = new BufferedPipe(128); var input = new byte[70]; var output = new byte[50]; for (var i = 0; i < 70; i++) { input[i] = (byte)i; } await p.WriteAsync(new ArraySegment <byte>(input)); var res = await p.ReadAsync(new ArraySegment <byte>(output)); Assert.Equal(false, res.EndOfStream); Assert.Equal(50, res.BytesRead); for (var i = 0; i < 50; i++) { Assert.Equal(i, output[i]); } await p.CloseAsync(); res = await p.ReadAsync(new ArraySegment <byte>(output)); Assert.Equal(false, res.EndOfStream); Assert.Equal(20, res.BytesRead); for (var i = 0; i < 20; i++) { Assert.Equal(50 + i, output[i]); } await p.CloseAsync(); res = await p.ReadAsync(new ArraySegment <byte>(output)); Assert.Equal(true, res.EndOfStream); Assert.Equal(0, res.BytesRead); }
public async Task ShouldErrorIfStreamWasClosedWithinTimeout() { var timeout = 200; var pipe = new BufferedPipe(50); var _ = Task.Run(async() => { await Task.Delay(10); await pipe.CloseAsync(); }); var ex = await Assert.ThrowsAsync <AggregateException>( () => ClientPreface.ReadAsync(pipe, timeout).AsTask()); Assert.IsType <EndOfStreamException>(ex.InnerException); }
public async Task ConnectionShouldSignalDoneWhenInputIsClosed(bool isServer) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var http2Con = await ConnectionUtils.BuildEstablishedConnection( isServer, inPipe, outPipe, loggerProvider); await inPipe.CloseAsync(); // Expect the connection to close within timeout var closed = http2Con.Done; Assert.True( closed == await Task.WhenAny(closed, Task.Delay(1000)), "Expected connection to close"); }
public async Task RemoteGoAwayReasonTaskShouldYieldExceptionIfNoGoAwayIsSent() { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var res = await ServerStreamTests.StreamCreator.CreateConnectionAndStream( StreamState.Open, loggerProvider, inPipe, outPipe); var readGoAwayTask = res.conn.RemoteGoAwayReason; await inPipe.CloseAsync(); Assert.True( readGoAwayTask == await Task.WhenAny(readGoAwayTask, Task.Delay(200)), "Expected readGoAwayTask to finish"); await Assert.ThrowsAsync <EndOfStreamException>( async() => await readGoAwayTask); }
public async Task PingShouldFailWhenConnectionIsClosedBeforePingStart() { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var http2Con = await ConnectionUtils.BuildEstablishedConnection( true, inPipe, outPipe, loggerProvider); // Close the connection await inPipe.CloseAsync(); await outPipe.AssertStreamEnd(); // Request ping var pingTask = http2Con.PingAsync(); // Await ping to finish with exception var timeoutTask = Task.Delay(200); Assert.True( pingTask == await Task.WhenAny(pingTask, timeoutTask), "Expected pingTask to finish"); await Assert.ThrowsAsync <ConnectionClosedException>( async() => await pingTask); }
public async Task CloseShouldAllowRemainingDataToBeReadBeforeSignalClose() { var p = new BufferedPipe(128); var input = new byte[20]; var output = new byte[10]; for (var i = 0; i < 20; i++) { input[i] = (byte)i; } await p.WriteAsync(new ArraySegment <byte>(input)); await p.CloseAsync(); var res = await p.ReadAsync(new ArraySegment <byte>(output)); Assert.Equal(false, res.EndOfStream); Assert.Equal(10, res.BytesRead); for (var i = 0; i < 10; i++) { Assert.Equal(i, output[i]); } res = await p.ReadAsync(new ArraySegment <byte>(output)); Assert.Equal(false, res.EndOfStream); Assert.Equal(10, res.BytesRead); for (var i = 0; i < 10; i++) { Assert.Equal(i + 10, output[i]); } res = await p.ReadAsync(new ArraySegment <byte>(output)); Assert.Equal(true, res.EndOfStream); Assert.Equal(0, res.BytesRead); }
public async Task GoAwayShouldBeSendable(bool withConnectionClose) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var res = await ServerStreamTests.StreamCreator.CreateConnectionAndStream( StreamState.Open, loggerProvider, inPipe, outPipe); // Start the GoAway process in a background task. // As waiting for this will block the current task in case // of connection close var closeTask = Task.Run(() => res.conn.GoAwayAsync(ErrorCode.InternalError, withConnectionClose)); // Expect the GoAway message await outPipe.AssertGoAwayReception(ErrorCode.InternalError, 1u); if (withConnectionClose) { await outPipe.AssertStreamEnd(); await inPipe.CloseAsync(); } await closeTask; }