Make ListenerPrimaryTests more reliable

- The Task from ListenerSecondary.StartAsync() may complete before the
  PrimaryListener adds the pipe connection to its dispatch pipe list.
This commit is contained in:
Stephen Halter 2016-11-22 16:24:42 -08:00
parent fd7232616a
commit 02b84d7ae1
1 changed files with 43 additions and 5 deletions

View File

@ -48,7 +48,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
{
return new Frame<DefaultHttpContext>(new TestApplication(c =>
{
return c.Response.WriteAsync("Secondary"); ;
return c.Response.WriteAsync("Secondary");
}), context);
}
};
@ -76,7 +76,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
await listenerSecondary.StartAsync(pipeName, pipeMessage, address, kestrelThreadSecondary);
// Once a secondary listener is added, TCP connections start getting dispatched to it
Assert.Equal("Secondary", await HttpClientSlim.GetStringAsync(address.ToString()));
await AssertResponseEventually(address.ToString(), "Secondary", allowed: new[] { "Primary" });
// TCP connections will still get round-robined to the primary listener
Assert.Equal("Primary", await HttpClientSlim.GetStringAsync(address.ToString()));
@ -146,7 +146,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
await listenerSecondary.StartAsync(pipeName, pipeMessage, address, kestrelThreadSecondary);
// TCP Connections get round-robined
Assert.Equal("Secondary", await HttpClientSlim.GetStringAsync(address.ToString()));
await AssertResponseEventually(address.ToString(), "Secondary", allowed: new[] { "Primary" });
Assert.Equal("Primary", await HttpClientSlim.GetStringAsync(address.ToString()));
// Create a pipe connection and keep it open without sending any data
@ -189,6 +189,12 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
await kestrelThreadPrimary.PostAsync(_ => pipe.Dispose(), null);
// Wait up to 10 seconds for error to be logged
for (var i = 0; i < 10 && primaryTrace.Logger.TotalErrorsLogged == 0; i++)
{
await Task.Delay(100);
}
// Same for after the non-listener pipe connection is closed
Assert.Equal("Primary", await HttpClientSlim.GetStringAsync(address.ToString()));
Assert.Equal("Secondary", await HttpClientSlim.GetStringAsync(address.ToString()));
@ -237,7 +243,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
{
return new Frame<DefaultHttpContext>(new TestApplication(c =>
{
return c.Response.WriteAsync("Secondary"); ;
return c.Response.WriteAsync("Secondary");
}), context);
}
};
@ -260,7 +266,13 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
var listenerSecondary = new TcpListenerSecondary(serviceContextSecondary);
await listenerSecondary.StartAsync(pipeName, Guid.NewGuid().ToByteArray(), address, kestrelThreadSecondary);
// TCP Connections get round-robined
// Wait up to 10 seconds for error to be logged
for (var i = 0; i < 10 && primaryTrace.Logger.TotalErrorsLogged == 0; i++)
{
await Task.Delay(100);
}
// TCP Connections don't get round-robined
Assert.Equal("Primary", await HttpClientSlim.GetStringAsync(address.ToString()));
Assert.Equal("Primary", await HttpClientSlim.GetStringAsync(address.ToString()));
Assert.Equal("Primary", await HttpClientSlim.GetStringAsync(address.ToString()));
@ -278,6 +290,32 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
Assert.Contains("Bad data", errorMessage.Exception.ToString());
}
private static async Task AssertResponseEventually(
string address,
string expected,
string[] allowed = null,
int maxRetries = 100,
int retryDelay = 100)
{
for (var i = 0; i < maxRetries; i++)
{
var response = await HttpClientSlim.GetStringAsync(address);
if (response == expected)
{
return;
}
if (allowed != null)
{
Assert.Contains(response, allowed);
}
await Task.Delay(retryDelay);
}
Assert.True(false, $"'{address}' failed to respond with '{expected}' in {maxRetries} retries.");
}
private class TestApplication : IHttpApplication<DefaultHttpContext>
{
private readonly Func<DefaultHttpContext, Task> _app;