Don't block so many threads in HeartbeatTests (#2610)

This commit is contained in:
Stephen Halter 2018-05-23 15:58:33 -07:00 committed by GitHub
parent cf684a1e8f
commit f70088c2d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 36 additions and 21 deletions

View File

@ -22,58 +22,73 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
} }
[Fact] [Fact]
public void BlockedHeartbeatDoesntCauseOverlapsAndIsLoggedAsError() public async Task BlockedHeartbeatDoesntCauseOverlapsAndIsLoggedAsError()
{ {
var systemClock = new MockSystemClock(); var systemClock = new MockSystemClock();
var heartbeatHandler = new Mock<IHeartbeatHandler>(); var heartbeatHandler = new Mock<IHeartbeatHandler>();
var debugger = new Mock<IDebugger>(); var debugger = new Mock<IDebugger>();
var kestrelTrace = new Mock<IKestrelTrace>(); var kestrelTrace = new Mock<IKestrelTrace>();
var handlerMre = new ManualResetEventSlim(); var handlerMre = new ManualResetEventSlim();
var traceMre = new ManualResetEventSlim(); var handlerStartedTcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
var onHeartbeatTasks = new Task[2];
heartbeatHandler.Setup(h => h.OnHeartbeat(systemClock.UtcNow)).Callback(() => handlerMre.Wait()); heartbeatHandler.Setup(h => h.OnHeartbeat(systemClock.UtcNow)).Callback(() =>
{
handlerStartedTcs.SetResult(null);
handlerMre.Wait();
});
debugger.Setup(d => d.IsAttached).Returns(false); debugger.Setup(d => d.IsAttached).Returns(false);
kestrelTrace.Setup(t => t.HeartbeatSlow(Heartbeat.Interval, systemClock.UtcNow)).Callback(() => traceMre.Set());
Task blockedHeartbeatTask;
using (var heartbeat = new Heartbeat(new[] { heartbeatHandler.Object }, systemClock, debugger.Object, kestrelTrace.Object)) using (var heartbeat = new Heartbeat(new[] { heartbeatHandler.Object }, systemClock, debugger.Object, kestrelTrace.Object))
{ {
onHeartbeatTasks[0] = Task.Run(() => heartbeat.OnHeartbeat()); blockedHeartbeatTask = Task.Run(() => heartbeat.OnHeartbeat());
onHeartbeatTasks[1] = Task.Run(() => heartbeat.OnHeartbeat());
Assert.True(traceMre.Wait(TimeSpan.FromSeconds(10))); await handlerStartedTcs.Task.DefaultTimeout();
heartbeat.OnHeartbeat();
} }
handlerMre.Set(); handlerMre.Set();
Task.WaitAll(onHeartbeatTasks);
await blockedHeartbeatTask.DefaultTimeout();
heartbeatHandler.Verify(h => h.OnHeartbeat(systemClock.UtcNow), Times.Once()); heartbeatHandler.Verify(h => h.OnHeartbeat(systemClock.UtcNow), Times.Once());
kestrelTrace.Verify(t => t.HeartbeatSlow(Heartbeat.Interval, systemClock.UtcNow), Times.Once()); kestrelTrace.Verify(t => t.HeartbeatSlow(Heartbeat.Interval, systemClock.UtcNow), Times.Once());
} }
[Fact] [Fact]
public void BlockedHeartbeatIsNotLoggedAsErrorIfDebuggerAttached() public async Task BlockedHeartbeatIsNotLoggedAsErrorIfDebuggerAttached()
{ {
var systemClock = new MockSystemClock(); var systemClock = new MockSystemClock();
var heartbeatHandler = new Mock<IHeartbeatHandler>(); var heartbeatHandler = new Mock<IHeartbeatHandler>();
var debugger = new Mock<IDebugger>(); var debugger = new Mock<IDebugger>();
var kestrelTrace = new Mock<IKestrelTrace>(); var kestrelTrace = new Mock<IKestrelTrace>();
var handlerMre = new ManualResetEventSlim(); var handlerMre = new ManualResetEventSlim();
var traceMre = new ManualResetEventSlim(); var handlerStartedTcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
var onHeartbeatTasks = new Task[2];
heartbeatHandler.Setup(h => h.OnHeartbeat(systemClock.UtcNow)).Callback(() => handlerMre.Wait()); heartbeatHandler.Setup(h => h.OnHeartbeat(systemClock.UtcNow)).Callback(() =>
debugger.Setup(d => d.IsAttached).Returns(true);
kestrelTrace.Setup(t => t.HeartbeatSlow(Heartbeat.Interval, systemClock.UtcNow)).Callback(() => traceMre.Set());
using (var heartbeat = new Heartbeat(new[] { heartbeatHandler.Object }, systemClock, debugger.Object, kestrelTrace.Object, TimeSpan.FromSeconds(0.01)))
{ {
onHeartbeatTasks[0] = Task.Run(() => heartbeat.OnHeartbeat()); handlerStartedTcs.SetResult(null);
onHeartbeatTasks[1] = Task.Run(() => heartbeat.OnHeartbeat()); handlerMre.Wait();
Assert.False(traceMre.Wait(TimeSpan.FromSeconds(2))); });
debugger.Setup(d => d.IsAttached).Returns(true);
Task blockedHeartbeatTask;
using (var heartbeat = new Heartbeat(new[] { heartbeatHandler.Object }, systemClock, debugger.Object, kestrelTrace.Object))
{
blockedHeartbeatTask = Task.Run(() => heartbeat.OnHeartbeat());
await handlerStartedTcs.Task.DefaultTimeout();
heartbeat.OnHeartbeat();
} }
handlerMre.Set(); handlerMre.Set();
Task.WaitAll(onHeartbeatTasks);
await blockedHeartbeatTask.DefaultTimeout();
heartbeatHandler.Verify(h => h.OnHeartbeat(systemClock.UtcNow), Times.Once()); heartbeatHandler.Verify(h => h.OnHeartbeat(systemClock.UtcNow), Times.Once());
kestrelTrace.Verify(t => t.HeartbeatSlow(Heartbeat.Interval, systemClock.UtcNow), Times.Never()); kestrelTrace.Verify(t => t.HeartbeatSlow(Heartbeat.Interval, systemClock.UtcNow), Times.Never());