Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
terencefan committed Jan 21, 2025
1 parent 83ac7a0 commit ea00052
Showing 1 changed file with 108 additions and 110 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Azure.SignalR.Tests;
using Microsoft.Azure.SignalR.Tests.Common;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging.Testing;
Expand All @@ -16,129 +17,126 @@
using Xunit;
using Xunit.Abstractions;

namespace Microsoft.Azure.SignalR.Management.Tests
namespace Microsoft.Azure.SignalR.Management.Tests;

public class RestHealthCheckServiceFacts(ITestOutputHelper output = null) : LoggedTest(output)
{
public class RestHealthCheckServiceFacts : LoggedTest
{
private const string HubName = "hub";
public static IEnumerable<object[]> HttpClientMockData
{
get
{
yield return new object[] { new TestRootHandler(HttpStatusCode.BadGateway) };
yield return new object[] { new TestRootHandler(HttpStatusCode.NotFound) };
yield return new object[] { new TestRootHandler((request, token) => throw new HttpRequestException()) };
}
}
public RestHealthCheckServiceFacts(ITestOutputHelper output = null) : base(output)
{
}
private const string HubName = "hub";

[Theory]
[MemberData(nameof(HttpClientMockData))]
internal async Task TestRestHealthCheckServiceWithUnhealthyEndpoint(TestRootHandler testHandler)
public static IEnumerable<object[]> HttpClientMockData
{
get
{
using var _ = StartLog(out var loggerFactory);
using var serviceHubContext = await new ServiceManagerBuilder()
.WithOptions(o => o.ConnectionString = FakeEndpointUtils.GetFakeConnectionString(1).Single())
.WithLoggerFactory(loggerFactory)
.ConfigureServices(services =>
{
services.AddHttpClient(Constants.HttpClientNames.InternalDefault)
.ConfigurePrimaryHttpMessageHandler(() => testHandler);
services.Configure<HealthCheckOption>(o => o.EnabledForSingleEndpoint = true);
})
.BuildServiceManager()
.CreateHubContextAsync(HubName, default);
var endpoint = (serviceHubContext as ServiceHubContextImpl).ServiceProvider.GetRequiredService<IServiceEndpointManager>().GetEndpoints(HubName).First();
Assert.False(endpoint.Online);
yield return new object[] { new TestRootHandler(HttpStatusCode.BadGateway) };
yield return new object[] { new TestRootHandler(HttpStatusCode.NotFound) };
yield return new object[] { new TestRootHandler((request, token) => throw new HttpRequestException()) };
}
}

[Fact]
public async Task TestRestHealthCheckServiceWithEndpointFromHealthyToUnhealthy()
{
var tcs = new TaskCompletionSource<bool>();
var handlerMock = new Mock<DelegatingHandler>();
// mock health api calls first return healthy then unhealthy.
handlerMock.Protected().SetupSequence<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
.ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK))
.ReturnsAsync(new HttpResponseMessage(HttpStatusCode.BadGateway))
.ReturnsAsync(new HttpResponseMessage(HttpStatusCode.BadGateway))
.ReturnsAsync(() =>
{
tcs.SetResult(true);
return new HttpResponseMessage(HttpStatusCode.BadGateway);
})
.ReturnsAsync(() =>
{
Assert.Fail("Unexpected invoke.");
return default;
});
[RetryFact]
public async Task TestRestHealthCheckServiceWithEndpointFromHealthyToUnhealthy()
{
var tcs = new TaskCompletionSource<bool>();
var handlerMock = new Mock<DelegatingHandler>();
// mock health api calls first return healthy then unhealthy.
handlerMock.Protected().SetupSequence<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
.ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK))
.ReturnsAsync(new HttpResponseMessage(HttpStatusCode.BadGateway))
.ReturnsAsync(new HttpResponseMessage(HttpStatusCode.BadGateway))
.ReturnsAsync(() =>
{
tcs.SetResult(true);
return new HttpResponseMessage(HttpStatusCode.BadGateway);
})
.ReturnsAsync(() =>
{
Assert.Fail("Unexpected invoke.");
return default;
});

var checkInterval = TimeSpan.FromSeconds(3);
var retryInterval = TimeSpan.FromSeconds(0.5);
using var _ = StartLog(out var loggerFactory);
var services = new ServiceCollection()
.AddSignalRServiceManager()
.AddHttpClient(Constants.HttpClientNames.InternalDefault).ConfigurePrimaryHttpMessageHandler(() => handlerMock.Object).Services
.Configure<HealthCheckOption>(o =>
{
o.CheckInterval = checkInterval;
o.RetryInterval = retryInterval;
o.EnabledForSingleEndpoint = true;
});
using var serviceHubContext = await new ServiceManagerBuilder(services)
.WithOptions(o => o.ConnectionString = FakeEndpointUtils.GetFakeConnectionString(1).Single())
.WithLoggerFactory(loggerFactory)
.BuildServiceManager()
.CreateHubContextAsync(HubName, default);
var checkInterval = TimeSpan.FromSeconds(3);
var retryInterval = TimeSpan.FromSeconds(0.5);
using var _ = StartLog(out var loggerFactory);
var services = new ServiceCollection()
.AddSignalRServiceManager()
.AddHttpClient(Constants.HttpClientNames.InternalDefault).ConfigurePrimaryHttpMessageHandler(() => handlerMock.Object).Services
.Configure<HealthCheckOption>(o =>
{
o.CheckInterval = checkInterval;
o.RetryInterval = retryInterval;
o.EnabledForSingleEndpoint = true;
});
using var serviceHubContext = await new ServiceManagerBuilder(services)
.WithOptions(o => o.ConnectionString = FakeEndpointUtils.GetFakeConnectionString(1).Single())
.WithLoggerFactory(loggerFactory)
.BuildServiceManager()
.CreateHubContextAsync(HubName, default);

var endpoint = (serviceHubContext as ServiceHubContextImpl).ServiceProvider.GetRequiredService<IServiceEndpointManager>().GetEndpoints(HubName).First();
var endpoint = (serviceHubContext as ServiceHubContextImpl).ServiceProvider.GetRequiredService<IServiceEndpointManager>().GetEndpoints(HubName)[0];

//The first health check is OK
Assert.True(endpoint.Online);
//The first health check is OK
Assert.True(endpoint.Online);

//Wait until the next health check finish
await tcs.Task;
// let our handler handle the response.
await Task.Delay(1);
//Wait until the next health check finish
await tcs.Task;
// let our handler handle the response.
await Task.Delay(1);

Assert.False(endpoint.Online);
}
Assert.False(endpoint.Online);
}

[Fact]
public async Task TestTimeoutAsync()
{
using var _ = StartLog(out var loggerFactory);
var taskSource = new TaskCompletionSource();
var services = new ServiceCollection()
.AddSignalRServiceManager()
.AddHttpClient(Constants.HttpClientNames.InternalDefault).ConfigurePrimaryHttpMessageHandler(() => new TestRootHandler(async (message, token) =>
[Fact]
public async Task TestTimeoutAsync()
{
using var _ = StartLog(out var loggerFactory);
var taskSource = new TaskCompletionSource();
var services = new ServiceCollection()
.AddSignalRServiceManager()
.AddHttpClient(Constants.HttpClientNames.InternalDefault).ConfigurePrimaryHttpMessageHandler(() => new TestRootHandler(async (message, token) =>
{
try
{
try
{
await Task.Delay(-1, token);
}
catch (OperationCanceledException) when (token.IsCancellationRequested)
{
taskSource.SetResult();
}
})).Services
.Configure<HealthCheckOption>(o =>
await Task.Delay(-1, token);
}
catch (OperationCanceledException) when (token.IsCancellationRequested)
{
// Never retry
o.RetryInterval = Timeout.InfiniteTimeSpan;
// Make the timeout happens as soon as quickly.
o.HttpTimeout = TimeSpan.FromMilliseconds(1);
o.EnabledForSingleEndpoint = true;
});
using var serviceHubContext = await new ServiceManagerBuilder(services)
.WithOptions(o => o.ConnectionString = FakeEndpointUtils.GetFakeConnectionString(1).Single())
.WithLoggerFactory(loggerFactory)
.BuildServiceManager()
.CreateHubContextAsync(HubName, default);
taskSource.SetResult();
}
})).Services
.Configure<HealthCheckOption>(o =>
{
// Never retry
o.RetryInterval = Timeout.InfiniteTimeSpan;
// Make the timeout happens as soon as quickly.
o.HttpTimeout = TimeSpan.FromMilliseconds(1);
o.EnabledForSingleEndpoint = true;
});
using var serviceHubContext = await new ServiceManagerBuilder(services)
.WithOptions(o => o.ConnectionString = FakeEndpointUtils.GetFakeConnectionString(1).Single())
.WithLoggerFactory(loggerFactory)
.BuildServiceManager()
.CreateHubContextAsync(HubName, default);

await taskSource.Task.OrTimeout();
}
await taskSource.Task.OrTimeout();
}

[Theory]
[MemberData(nameof(HttpClientMockData))]
internal async Task TestRestHealthCheckServiceWithUnhealthyEndpoint(TestRootHandler testHandler)
{
using var _ = StartLog(out var loggerFactory);
using var serviceHubContext = await new ServiceManagerBuilder()
.WithOptions(o => o.ConnectionString = FakeEndpointUtils.GetFakeConnectionString(1).Single())
.WithLoggerFactory(loggerFactory)
.ConfigureServices(services =>
{
services.AddHttpClient(Constants.HttpClientNames.InternalDefault)
.ConfigurePrimaryHttpMessageHandler(() => testHandler);
services.Configure<HealthCheckOption>(o => o.EnabledForSingleEndpoint = true);
})
.BuildServiceManager()
.CreateHubContextAsync(HubName, default);
var endpoint = (serviceHubContext as ServiceHubContextImpl).ServiceProvider.GetRequiredService<IServiceEndpointManager>().GetEndpoints(HubName)[0];
Assert.False(endpoint.Online);
}
}

0 comments on commit ea00052

Please sign in to comment.