aspnetcore/test/Microsoft.AspNetCore.Http.T.../FlushResultCancellationTest...

69 lines
2.4 KiB
C#

// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.IO.Pipelines;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
namespace Microsoft.AspNetCore.Http.Tests
{
public class FlushResultCancellationTests : PipeTest
{
[Fact]
public void FlushAsyncCancellationDeadlock()
{
var cts = new CancellationTokenSource();
var cts2 = new CancellationTokenSource();
PipeWriter buffer = Writer.WriteEmpty(MaximumSizeHigh);
var e = new ManualResetEventSlim();
ValueTaskAwaiter<FlushResult> awaiter = buffer.FlushAsync(cts.Token).GetAwaiter();
awaiter.OnCompleted(
() => {
// We are on cancellation thread and need to wait until another FlushAsync call
// takes pipe state lock
e.Wait();
// Make sure we had enough time to reach _cancellationTokenRegistration.Dispose
Thread.Sleep(100);
// Try to take pipe state lock
buffer.FlushAsync();
});
// Start a thread that would run cancellation callbacks
Task cancellationTask = Task.Run(() => cts.Cancel());
// Start a thread that would call FlushAsync with different token
// and block on _cancellationTokenRegistration.Dispose
Task blockingTask = Task.Run(
() => {
e.Set();
buffer.FlushAsync(cts2.Token);
});
bool completed = Task.WhenAll(cancellationTask, blockingTask).Wait(TimeSpan.FromSeconds(10));
Assert.True(completed);
}
[Fact]
public async Task FlushAsyncWithNewCancellationTokenNotAffectedByPrevious()
{
var cancellationTokenSource1 = new CancellationTokenSource();
PipeWriter buffer = Writer.WriteEmpty(10);
await buffer.FlushAsync(cancellationTokenSource1.Token);
cancellationTokenSource1.Cancel();
var cancellationTokenSource2 = new CancellationTokenSource();
buffer = Writer.WriteEmpty(10);
await buffer.FlushAsync(cancellationTokenSource2.Token);
}
}
}