public async Task TrailersShouldBeCorrectlySent(bool isServer) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var r = await StreamCreator.CreateConnectionAndStream( isServer, loggerProvider, inPipe, outPipe); await r.stream.WriteAsync(new ArraySegment <byte>(new byte[0])); await outPipe.ReadAndDiscardData(1u, false, 0); // Send trailers await r.stream.WriteTrailersAsync(DefaultTrailingHeaders); // Check the received trailers var fh = await outPipe.ReadFrameHeaderWithTimeout(); Assert.Equal(FrameType.Headers, fh.Type); Assert.Equal(1u, fh.StreamId); var expectedFlags = HeadersFrameFlags.EndOfHeaders | HeadersFrameFlags.EndOfStream; Assert.Equal((byte)expectedFlags, fh.Flags); Assert.InRange(fh.Length, 1, 1024); var headerData = new byte[fh.Length]; await outPipe.ReadAllWithTimeout(new ArraySegment <byte>(headerData)); Assert.Equal(EncodedDefaultTrailingHeaders, headerData); }
public async Task OutgoingDataShouldRespectMaxFrameSize( bool isServer) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var r = await StreamCreator.CreateConnectionAndStream( isServer, loggerProvider, inPipe, outPipe); var dataSize = Settings.Default.MaxFrameSize + 10; var writeTask = Task.Run(async() => { var data = new byte[dataSize]; await r.stream.WriteAsync(new ArraySegment <byte>(data), true); }); // Expect to receive the data in fragments await outPipe.ReadAndDiscardData(1u, false, (int)Settings.Default.MaxFrameSize); await outPipe.ReadAndDiscardData(1u, true, 10); var doneTask = await Task.WhenAny(writeTask, Task.Delay(250)); Assert.True(writeTask == doneTask, "Expected write task to finish"); }
public async Task ReceivingHeadersOrDataOnAClosedStreamShouldTriggerAStreamReset( StreamState streamState, bool sendHeaders, bool sendData, bool sendTrailers) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var localCloseDone = new SemaphoreSlim(0); var res = await StreamCreator.CreateConnectionAndStream( streamState, loggerProvider, inPipe, outPipe); if (sendHeaders) { await inPipe.WriteHeaders(res.hEncoder, 1, false, DefaultGetHeaders); } if (sendData) { await inPipe.WriteData(1u, 0); } if (sendTrailers) { await inPipe.WriteHeaders(res.hEncoder, 1, true, DefaultGetHeaders); } await outPipe.AssertResetStreamReception(1u, ErrorCode.StreamClosed); var expectedState = streamState == StreamState.Closed ? StreamState.Closed : StreamState.Reset; Assert.Equal(expectedState, res.stream.State); }
public async Task ReceivingDataDirectlyAfterInformationalHeadersShouldBeAnError() { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var res = await StreamCreator.CreateConnectionAndStream( StreamState.Open, loggerProvider, inPipe, outPipe); // Send informational headers to the client var infoHeaders = new HeaderField[] { new HeaderField { Name = ":status", Value = "100" }, new HeaderField { Name = "extension-field", Value = "bar" }, }; await inPipe.WriteHeaders(res.hEncoder, 1u, false, infoHeaders); var recvdHeaders = await res.stream.ReadHeadersAsync(); Assert.True(infoHeaders.SequenceEqual(recvdHeaders)); // Try to send data await inPipe.WriteData(1u, 100, null, true); // Expect to receive an error await outPipe.AssertResetStreamReception(1u, ErrorCode.ProtocolError); Assert.Equal(StreamState.Reset, res.stream.State); await Assert.ThrowsAsync <StreamResetException>( () => res.stream.ReadHeadersAsync()); }
public async Task ClientsShouldBeAbleToReceiveInformationalHeaders() { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var res = await StreamCreator.CreateConnectionAndStream( StreamState.Open, loggerProvider, inPipe, outPipe); // Send and receive first set of informational headers var readInfoHeaders1Task = res.stream.ReadHeadersAsync(); Assert.False(readInfoHeaders1Task.IsCompleted); var infoHeaders1 = new HeaderField[] { new HeaderField { Name = ":status", Value = "100" }, new HeaderField { Name = "extension-field", Value = "bar" }, }; await inPipe.WriteHeaders(res.hEncoder, 1u, false, infoHeaders1); var recvdInfoHeaders1 = await readInfoHeaders1Task; Assert.True(infoHeaders1.SequenceEqual(recvdInfoHeaders1)); // Send and receive second set of informational headers var readInfoHeaders2Task = res.stream.ReadHeadersAsync(); Assert.False(readInfoHeaders2Task.IsCompleted); var infoHeaders2 = new HeaderField[] { new HeaderField { Name = ":status", Value = "108" }, new HeaderField { Name = "extension-field-b", Value = "bar2" }, }; await inPipe.WriteHeaders(res.hEncoder, 1u, false, infoHeaders2); var recvdInfoHeaders2 = await readInfoHeaders2Task; Assert.True(infoHeaders2.SequenceEqual(recvdInfoHeaders2)); // Send and receive final headers var recvHeadersTask = res.stream.ReadHeadersAsync(); Assert.False(recvHeadersTask.IsCompleted); await inPipe.WriteHeaders(res.hEncoder, 1u, true, DefaultStatusHeaders); var recvdHeaders = await recvHeadersTask; Assert.True(DefaultStatusHeaders.SequenceEqual(recvdHeaders)); }
public async Task StreamCreatorShouldCreateStreamInCorrectState( StreamState state) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var res = await StreamCreator.CreateConnectionAndStream( state, loggerProvider, inPipe, outPipe); Assert.NotNull(res.stream); Assert.Equal(state, res.stream.State); }
public async Task RespondingTrailersWithoutHeadersShouldThrowAnException() { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var r = await StreamCreator.CreateConnectionAndStream( StreamState.Open, loggerProvider, inPipe, outPipe); var ex = await Assert.ThrowsAsync<Exception>(async () => await r.stream.WriteTrailersAsync(DefaultTrailingHeaders)); Assert.Equal("Attempted to write trailers without data", ex.Message); }
public async Task CancellingAStreamShouldSendAResetFrame( bool isServer) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var r = await StreamCreator.CreateConnectionAndStream( isServer, loggerProvider, inPipe, outPipe); r.stream.Cancel(); await outPipe.AssertResetStreamReception(1, ErrorCode.Cancel); Assert.Equal(StreamState.Reset, r.stream.State); }
public async Task RespondingDataWithoutHeadersShouldThrowAnException( bool useEndOfStream) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var r = await StreamCreator.CreateConnectionAndStream( StreamState.Open, loggerProvider, inPipe, outPipe); var ex = await Assert.ThrowsAsync<Exception>(async () => await r.stream.WriteAsync( new ArraySegment<byte>(new byte[8]), useEndOfStream)); Assert.Equal("Attempted to write data before headers", ex.Message); }
public async Task ReceivingHeaders2TimesShouldTriggerAStreamReset( bool isServer, bool headersAreEndOfStream) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); // Establish open streams, which means headers are sent in both // directions var res = await StreamCreator.CreateConnectionAndStream( isServer, loggerProvider, inPipe, outPipe); // Write a second header await inPipe.WriteHeaders( res.hEncoder, 1, headersAreEndOfStream, DefaultGetHeaders); await outPipe.AssertResetStreamReception(1, ErrorCode.ProtocolError); Assert.Equal(StreamState.Reset, res.stream.State); }
public async Task ReceivingHeadersAndNoDataShouldBlockTheReader() { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var res = await StreamCreator.CreateConnectionAndStream( StreamState.Open, loggerProvider, inPipe, outPipe); var buf = new byte[1024]; try { await res.stream.ReadWithTimeout(new ArraySegment<byte>(buf)); } catch (TimeoutException) { return; } Assert.True(false, "Expected read timeout, but got data"); }
public async Task ItShouldBePossibleToSendInformationalHeaders() { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var r = await StreamCreator.CreateConnectionAndStream( StreamState.Open, loggerProvider, inPipe, outPipe); var infoHeaders = new HeaderField[] { new HeaderField { Name = ":status", Value = "100" }, new HeaderField { Name = "extension-field", Value = "bar" }, }; await r.stream.WriteHeadersAsync(infoHeaders, false); await r.stream.WriteHeadersAsync(DefaultStatusHeaders, false); await r.stream.WriteAsync(new ArraySegment<byte>(new byte[0]), true); await outPipe.ReadAndDiscardHeaders(1, false); await outPipe.ReadAndDiscardHeaders(1, false); await outPipe.ReadAndDiscardData(1, true, 0); }
public async Task ReceivingDataBeforeHeadersShouldYieldAResetException() { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var res = await StreamCreator.CreateConnectionAndStream( StreamState.Open, loggerProvider, inPipe, outPipe); await inPipe.WriteData(1u, 1); await outPipe.AssertResetStreamReception(1u, ErrorCode.ProtocolError); var ex = await Assert.ThrowsAsync <AggregateException>( () => res.stream.ReadWithTimeout(new ArraySegment <byte>( new byte[1]))); Assert.IsType <StreamResetException>(ex.InnerException); Assert.Equal(StreamState.Reset, res.stream.State); }
public async Task EmptyDataFramesShouldBeValidSeperatorsBeforeTrailers( bool isServer) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var res = await StreamCreator.CreateConnectionAndStream( isServer, loggerProvider, inPipe, outPipe); // Send a 0byte data frame await inPipe.WriteData(1u, 0); // Send trailers await inPipe.WriteHeaders(res.hEncoder, 1u, true, DefaultTrailingHeaders); // Check for no stream error await inPipe.WritePing(new byte[8], false); await outPipe.ReadAndDiscardPong(); }
public async Task EmptyDataFramesShouldNotWakeupPendingReads( bool isServer) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var res = await StreamCreator.CreateConnectionAndStream( isServer, loggerProvider, inPipe, outPipe); // Send a 0byte data frame await inPipe.WriteData(1u, 0); // Try to read - this should not unblock var readTask = res.stream.ReadAsync( new ArraySegment <byte>(new byte[1])).AsTask(); var doneTask = await Task.WhenAny(readTask, Task.Delay(100)); Assert.True( doneTask != readTask, "Expected read timeout but read finished"); }
public async Task ReceivingTrailersShouldUnblockDataReceptionAndPresentThem( bool isServer) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var res = await StreamCreator.CreateConnectionAndStream( isServer, loggerProvider, inPipe, outPipe); var readDataTask = res.stream.ReadAllToArrayWithTimeout(); var fh = new FrameHeader { Type = FrameType.Data, Length = 4, StreamId = 1, Flags = (byte)0, }; await inPipe.WriteFrameHeader(fh); await inPipe.WriteAsync( new ArraySegment <byte>( System.Text.Encoding.ASCII.GetBytes("ABCD"))); var trailers = new HeaderField[] { new HeaderField { Name = "trai", Value = "ler" }, }; await inPipe.WriteHeaders(res.hEncoder, 1, true, trailers); var bytes = await readDataTask; Assert.Equal(4, bytes.Length); Assert.Equal("ABCD", System.Text.Encoding.ASCII.GetString(bytes)); Assert.Equal(StreamState.HalfClosedRemote, res.stream.State); var rcvdTrailers = await res.stream.ReadTrailersAsync(); Assert.Equal(trailers, rcvdTrailers); }
public async Task ResponseHeadersShouldBeCorrectlySent( bool useEndOfStream) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var r = await StreamCreator.CreateConnectionAndStream( StreamState.Open, loggerProvider, inPipe, outPipe); await r.stream.WriteHeadersAsync(DefaultStatusHeaders, useEndOfStream); // Check the received headers var fh = await outPipe.ReadFrameHeaderWithTimeout(); Assert.Equal(FrameType.Headers, fh.Type); Assert.Equal(1u, fh.StreamId); var expectedFlags = HeadersFrameFlags.EndOfHeaders; if (useEndOfStream) expectedFlags |= HeadersFrameFlags.EndOfStream; Assert.Equal((byte)expectedFlags, fh.Flags); Assert.InRange(fh.Length, 1, 1024); var headerData = new byte[fh.Length]; await outPipe.ReadAllWithTimeout(new ArraySegment<byte>(headerData)); Assert.Equal(EncodedDefaultStatusHeaders, headerData); }
public async Task ReceivingHeadersOrDataOnAResetStreamShouldProduceAClosedStreamError( bool sendHeaders, bool sendData, bool sendTrailers) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var r = await StreamCreator.CreateConnectionAndStream( StreamState.Reset, loggerProvider, inPipe, outPipe); if (sendHeaders) { await inPipe.WriteHeaders(r.hEncoder, 1, false, DefaultGetHeaders); } if (sendData) { await inPipe.WriteData(1u, 0); } if (sendTrailers) { await inPipe.WriteHeaders(r.hEncoder, 1, true, DefaultGetHeaders); } await outPipe.AssertResetStreamReception(1, ErrorCode.StreamClosed); }
public async Task DataFromDataFramesShouldBeReceived( bool isServer, int[] dataLength) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var res = await StreamCreator.CreateConnectionAndStream( isServer, loggerProvider, inPipe, outPipe); var readTask = res.stream.ReadAllToArrayWithTimeout(); var totalToSend = dataLength.Aggregate(0, (sum, n) => sum + n); byte nr = 0; for (var i = 0; i < dataLength.Length; i++) { var toSend = dataLength[i]; var isEndOfStream = i == (dataLength.Length - 1); var flags = isEndOfStream ? DataFrameFlags.EndOfStream : 0; var fh = new FrameHeader { Type = FrameType.Data, StreamId = 1, Flags = (byte)flags, Length = toSend, }; await inPipe.WriteFrameHeaderWithTimeout(fh); var fdata = new byte[toSend]; for (var j = 0; j < toSend; j++) { fdata[j] = nr; nr++; if (nr > 122) { nr = 0; } } await inPipe.WriteWithTimeout(new ArraySegment <byte>(fdata)); // Wait for a short amount of time between DATA frames if (!isEndOfStream) { await Task.Delay(10); } } var doneTask = await Task.WhenAny( readTask, Task.Delay(ReadableStreamTestExtensions.ReadTimeout)); Assert.True(doneTask == readTask, "Expected read task to complete within timeout"); byte[] receivedData = await readTask; Assert.NotNull(receivedData); Assert.Equal(totalToSend, receivedData.Length); var expected = 0; for (var j = 0; j < totalToSend; j++) { Assert.Equal(expected, receivedData[j]); expected++; if (expected > 122) { expected = 0; } } }
public async Task DataShouldBeCorrectlySent( bool isServer, int[] dataLength) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var r = await StreamCreator.CreateConnectionAndStream( isServer, loggerProvider, inPipe, outPipe); var totalToSend = dataLength.Aggregate(0, (sum, n) => sum + n); var writeTask = Task.Run(async() => { byte nr = 0; for (var i = 0; i < dataLength.Length; i++) { var toSend = dataLength[i]; var isEndOfStream = i == (dataLength.Length - 1); var buffer = new byte[toSend]; for (var j = 0; j < toSend; j++) { buffer[j] = nr; nr++; if (nr > 122) { nr = 0; } } await r.stream.WriteAsync( new ArraySegment <byte>(buffer), isEndOfStream); } }); var data = new byte[totalToSend]; var offset = 0; for (var i = 0; i < dataLength.Length; i++) { var fh = await outPipe.ReadFrameHeaderWithTimeout(); Assert.Equal(FrameType.Data, fh.Type); Assert.Equal(1u, fh.StreamId); var expectEOS = i == dataLength.Length - 1; var gotEOS = (fh.Flags & (byte)DataFrameFlags.EndOfStream) != 0; Assert.Equal(expectEOS, gotEOS); Assert.Equal(dataLength[i], fh.Length); var part = new byte[fh.Length]; await outPipe.ReadAllWithTimeout(new ArraySegment <byte>(part)); Array.Copy(part, 0, data, offset, fh.Length); offset += fh.Length; } var doneTask = await Task.WhenAny(writeTask, Task.Delay(250)); Assert.True(writeTask == doneTask, "Expected write task to finish"); // Check if the correct data was received var expected = 0; for (var j = 0; j < totalToSend; j++) { Assert.Equal(expected, data[j]); expected++; if (expected > 122) { expected = 0; } } }
public async Task DataFramesWithPaddingShouldBeCorrectlyReceived( bool isServer, int nrFrames, byte numPadding, int bytesToSend) { var inPipe = new BufferedPipe(10 * 1024); var outPipe = new BufferedPipe(10 * 1024); var receiveOk = true; var settings = Settings.Default; settings.MaxFrameSize = 100 * 1024; settings.InitialWindowSize = int.MaxValue; var r = await StreamCreator.CreateConnectionAndStream( isServer, loggerProvider, inPipe, outPipe, localSettings : settings); for (var nrSends = 0; nrSends < nrFrames; nrSends++) { var buf = new byte[1 + bytesToSend + numPadding]; buf[0] = numPadding; byte nr = 0; for (var i = 0; i < bytesToSend; i++) { buf[1 + i] = nr; nr++; if (nr > 123) { nr = 0; } } var fh = new FrameHeader { Type = FrameType.Data, StreamId = 1, Flags = (byte)DataFrameFlags.Padded, Length = buf.Length, }; await inPipe.WriteFrameHeaderWithTimeout(fh); await inPipe.WriteWithTimeout(new ArraySegment <byte>(buf)); } for (var nrSends = 0; nrSends < nrFrames; nrSends++) { var buf1 = new byte[bytesToSend]; await r.stream.ReadAllWithTimeout(new ArraySegment <byte>(buf1)); var expected = 0; for (var j = 0; j < bytesToSend; j++) { if (buf1[j] != expected) { receiveOk = false; } expected++; if (expected > 123) { expected = 0; } } } Assert.True(receiveOk, "Expected to receive correct data"); }