Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add tests
  • Loading branch information
rzikm committed Apr 11, 2022
commit ac3bfbfb18cc956d6ba48f0544f2f31c03af7cef
121 changes: 107 additions & 14 deletions src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -388,19 +388,36 @@ public async Task ConnectWithClientCertificate(bool sendCerttificate)
serverConnection.Dispose();
}

[Fact]
public async Task WaitForAvailableUnidirectionStreamsAsyncWorks()
[Theory]
[InlineData(false)]
[InlineData(true)]
public async Task WaitForAvailableStreamsAsyncWorks(bool unidirectional)
{
ValueTask WaitForAvailableStreamsAsync(QuicConnection connection)
{
return unidirectional
? connection.WaitForAvailableUnidirectionalStreamsAsync()
: connection.WaitForAvailableBidirectionalStreamsAsync();
}

ValueTask<QuicStream> OpenStreamAsync(QuicConnection connection)
{
return unidirectional
? connection.OpenUnidirectionalStreamAsync()
: connection.OpenBidirectionalStreamAsync();
}

QuicListenerOptions listenerOptions = CreateQuicListenerOptions();
listenerOptions.MaxUnidirectionalStreams = 1;
listenerOptions.MaxBidirectionalStreams = 1;
(QuicConnection clientConnection, QuicConnection serverConnection) = await CreateConnectedQuicConnection(null, listenerOptions);

// No stream opened yet, should return immediately.
Assert.True(clientConnection.WaitForAvailableUnidirectionalStreamsAsync().IsCompletedSuccessfully);
Assert.True(WaitForAvailableStreamsAsync(clientConnection).IsCompletedSuccessfully);

// Open one stream, should wait till it closes.
QuicStream stream = await clientConnection.OpenUnidirectionalStreamAsync();
ValueTask waitTask = clientConnection.WaitForAvailableUnidirectionalStreamsAsync();
QuicStream stream = await OpenStreamAsync(clientConnection);
ValueTask waitTask = WaitForAvailableStreamsAsync(clientConnection);
Assert.False(waitTask.IsCompleted);

// Close the streams, the waitTask should finish as a result.
Expand All @@ -413,27 +430,103 @@ public async Task WaitForAvailableUnidirectionStreamsAsyncWorks()
serverConnection.Dispose();
}

[Fact]
public async Task WaitForAvailableBidirectionStreamsAsyncWorks()
[Theory]
[InlineData(false)]
[InlineData(true)]
public async Task OpenStreamAsync_BlocksUntilAvailable(bool unidirectional)
{
ValueTask<QuicStream> OpenStreamAsync(QuicConnection connection)
{
return unidirectional
? connection.OpenUnidirectionalStreamAsync()
: connection.OpenBidirectionalStreamAsync();
}

QuicListenerOptions listenerOptions = CreateQuicListenerOptions();
listenerOptions.MaxUnidirectionalStreams = 1;
listenerOptions.MaxBidirectionalStreams = 1;
(QuicConnection clientConnection, QuicConnection serverConnection) = await CreateConnectedQuicConnection(null, listenerOptions);

// No stream opened yet, should return immediately.
Assert.True(clientConnection.WaitForAvailableBidirectionalStreamsAsync().IsCompletedSuccessfully);
// Open one stream, second call should block
QuicStream stream = await OpenStreamAsync(clientConnection);
ValueTask<QuicStream> waitTask = OpenStreamAsync(clientConnection);
Assert.False(waitTask.IsCompleted);

// Open one stream, should wait till it closes.
QuicStream stream = await clientConnection.OpenBidirectionalStreamAsync();
ValueTask waitTask = clientConnection.WaitForAvailableBidirectionalStreamsAsync();
// Close the streams, the waitTask should finish as a result.
stream.Dispose();
QuicStream newStream = await serverConnection.AcceptStreamAsync();
newStream.Dispose();

newStream = await waitTask.AsTask().WaitAsync(TimeSpan.FromSeconds(10));
newStream.Dispose();

clientConnection.Dispose();
serverConnection.Dispose();
}

[Theory]
[InlineData(false)]
[InlineData(true)]
public async Task OpenStreamAsync_Canceled_Throws(bool unidirectional)
{
ValueTask<QuicStream> OpenStreamAsync(QuicConnection connection, CancellationToken token = default)
{
return unidirectional
? connection.OpenUnidirectionalStreamAsync(token)
: connection.OpenBidirectionalStreamAsync(token);
}

QuicListenerOptions listenerOptions = CreateQuicListenerOptions();
listenerOptions.MaxUnidirectionalStreams = 1;
listenerOptions.MaxBidirectionalStreams = 1;
(QuicConnection clientConnection, QuicConnection serverConnection) = await CreateConnectedQuicConnection(null, listenerOptions);

CancellationTokenSource cts = new CancellationTokenSource();

// Open one stream, second call should block
QuicStream stream = await OpenStreamAsync(clientConnection);
ValueTask<QuicStream> waitTask = OpenStreamAsync(clientConnection, cts.Token);
Assert.False(waitTask.IsCompleted);

// Close the streams, the waitTask and nextStreamTask should finish as a result.
cts.Cancel();

// awaiting the task should throw
var ex = await Assert.ThrowsAsync<OperationCanceledException>(async () => await waitTask);
Assert.Equal(cts.Token, ex.CancellationToken);

// Close the streams, the waitTask should finish as a result.
stream.Dispose();
QuicStream newStream = await serverConnection.AcceptStreamAsync();
newStream.Dispose();

await waitTask.AsTask().WaitAsync(TimeSpan.FromSeconds(10));
// next call should work as intended
newStream = await OpenStreamAsync(clientConnection).AsTask().WaitAsync(TimeSpan.FromSeconds(10));
newStream.Dispose();

clientConnection.Dispose();
serverConnection.Dispose();
}

[Theory]
[InlineData(false)]
[InlineData(true)]
public async Task OpenStreamAsync_PreCanceled_Throws(bool unidirectional)
{
ValueTask<QuicStream> OpenStreamAsync(QuicConnection connection, CancellationToken token = default)
{
return unidirectional
? connection.OpenUnidirectionalStreamAsync(token)
: connection.OpenBidirectionalStreamAsync(token);
}

(QuicConnection clientConnection, QuicConnection serverConnection) = await CreateConnectedQuicConnection(null, CreateQuicListenerOptions());

CancellationTokenSource cts = new CancellationTokenSource();
cts.Cancel();

var ex = await Assert.ThrowsAsync<OperationCanceledException>(async () => await OpenStreamAsync(clientConnection, cts.Token));
Assert.Equal(cts.Token, ex.CancellationToken);

clientConnection.Dispose();
serverConnection.Dispose();
}
Expand Down