diff --git a/src/Connectors/test/Connectors.Test/RelationalDatabaseHealthContributorTest.cs b/src/Connectors/test/Connectors.Test/RelationalDatabaseHealthContributorTest.cs index 267d293dac..42da1e5d2d 100644 --- a/src/Connectors/test/Connectors.Test/RelationalDatabaseHealthContributorTest.cs +++ b/src/Connectors/test/Connectors.Test/RelationalDatabaseHealthContributorTest.cs @@ -111,7 +111,10 @@ public async Task SQLServer_Not_Connected_Returns_Down_Status() result.Description.Should().Be("SQL Server health check failed"); result.Details.Should().Contain("host", "localhost"); result.Details.Should().Contain("service", "Example"); - result.Details.Should().ContainKey("error").WhoseValue.As().Should().StartWith("SqlException: Connection Timeout Expired."); + + result.Details.Should().ContainKey("error").WhoseValue.As().Should().Match(exception => + exception.StartsWith("SqlException: Connection Timeout Expired.", StringComparison.Ordinal) || + exception.StartsWith("SqlException: A network-related or instance-specific error", StringComparison.Ordinal)); } [Fact(Skip = "Integration test - Requires local SQL Server instance")] diff --git a/src/Discovery/test/Eureka.Test/EurekaServiceCollectionExtensionsTest.cs b/src/Discovery/test/Eureka.Test/EurekaServiceCollectionExtensionsTest.cs index 6d22358713..745c012afb 100644 --- a/src/Discovery/test/Eureka.Test/EurekaServiceCollectionExtensionsTest.cs +++ b/src/Discovery/test/Eureka.Test/EurekaServiceCollectionExtensionsTest.cs @@ -62,7 +62,7 @@ public async Task AddEurekaDiscoveryClient_UsesServerTimeout() var appSettings = new Dictionary { ["Eureka:Client:EurekaServer:ConnectTimeoutSeconds"] = "1", - ["Eureka:Client:EurekaServer:RetryCount"] = "1" + ["Eureka:Client:EurekaServer:RetryCount"] = "0" }; IConfiguration configuration = new ConfigurationBuilder().AddInMemoryCollection(appSettings).Build(); diff --git a/src/Management/src/Endpoint/SpringBootAdminClient/SpringBootAdminPeriodicRefresh.cs b/src/Management/src/Endpoint/SpringBootAdminClient/SpringBootAdminPeriodicRefresh.cs index 6426993f12..9477238be3 100644 --- a/src/Management/src/Endpoint/SpringBootAdminClient/SpringBootAdminPeriodicRefresh.cs +++ b/src/Management/src/Endpoint/SpringBootAdminClient/SpringBootAdminPeriodicRefresh.cs @@ -44,15 +44,20 @@ private async Task TimerLoopAsync(TimeSpan interval) do { - LogStartingRefreshCycle(); - - try - { - await _runner.RunAsync(isFirstTime, _timerTokenSource.Token); - } - catch (Exception exception) when (!exception.IsCancellation()) + // A tick queued just before periodic refresh was disabled would still be delivered here. + // Checking the period prevents executing a stale tick when refresh has been turned off. + if (isFirstTime || _periodicTimer.Period != Timeout.InfiniteTimeSpan) { - LogRefreshCycleFailed(exception); + LogStartingRefreshCycle(); + + try + { + await _runner.RunAsync(isFirstTime, _timerTokenSource.Token); + } + catch (Exception exception) when (!exception.IsCancellation()) + { + LogRefreshCycleFailed(exception); + } } isFirstTime = false; diff --git a/src/Management/test/Endpoint.Test/Actuators/Health/HealthAggregationTest.cs b/src/Management/test/Endpoint.Test/Actuators/Health/HealthAggregationTest.cs index ad76b9eaad..172f589c1c 100644 --- a/src/Management/test/Endpoint.Test/Actuators/Health/HealthAggregationTest.cs +++ b/src/Management/test/Endpoint.Test/Actuators/Health/HealthAggregationTest.cs @@ -366,9 +366,9 @@ public async Task Aggregates_contributors_in_parallel() { List contributors = [ - new SlowContributor(1.Seconds()), new SlowContributor(2.Seconds()), - new SlowContributor(3.Seconds()) + new SlowContributor(3.Seconds()), + new SlowContributor(4.Seconds()) ]; WebApplicationBuilder builder = TestWebApplicationBuilderFactory.Create(); @@ -408,7 +408,8 @@ public async Task Aggregates_contributors_in_parallel() } """); - stopwatch.Elapsed.Should().BeGreaterThan(500.Milliseconds()).And.BeLessThan(5.Seconds()); + // Upper bound must be less than 2+3+4=9s if contributors ran sequentially. + stopwatch.Elapsed.Should().BeGreaterThan(500.Milliseconds()).And.BeLessThan(9.Seconds()); } [Fact] diff --git a/src/Management/test/Endpoint.Test/Actuators/ThreadDump/EventPipeThreadDumperTest.cs b/src/Management/test/Endpoint.Test/Actuators/ThreadDump/EventPipeThreadDumperTest.cs index 3e46e42afd..43711fff72 100644 --- a/src/Management/test/Endpoint.Test/Actuators/ThreadDump/EventPipeThreadDumperTest.cs +++ b/src/Management/test/Endpoint.Test/Actuators/ThreadDump/EventPipeThreadDumperTest.cs @@ -16,19 +16,30 @@ public sealed class EventPipeThreadDumperTest public async Task Can_resolve_source_location_from_pdb() { using var backgroundCancellationSource = new CancellationTokenSource(); + using var threadStarted = new ManualResetEventSlim(false); var backgroundThread = new Thread(NestedType.BackgroundThreadCallback) { IsBackground = true }; - backgroundThread.Start(backgroundCancellationSource.Token); + backgroundThread.Start((backgroundCancellationSource.Token, threadStarted)); + threadStarted.Wait(TestContext.Current.CancellationToken); using var loggerProvider = new CapturingLoggerProvider(); using var loggerFactory = new LoggerFactory([loggerProvider]); ILogger logger = loggerFactory.CreateLogger(); +#if NET8_0 + // Use a longer collection window on .NET 8 to compensate for the Sleep(0) yield. + var optionsMonitor = TestOptionsMonitor.Create(new ThreadDumpEndpointOptions + { + Duration = 100 + }); +#else var optionsMonitor = new TestOptionsMonitor(); +#endif + var dumper = new EventPipeThreadDumper(optionsMonitor, logger); IList threads = await dumper.DumpThreadsAsync(TestContext.Current.CancellationToken); @@ -87,11 +98,18 @@ private static class NestedType { public static void BackgroundThreadCallback(object? argument) { - var cancellationToken = (CancellationToken)argument!; + (CancellationToken cancellationToken, ManualResetEventSlim threadStarted) = ((CancellationToken, ManualResetEventSlim))argument!; + + threadStarted.Set(); while (!cancellationToken.IsCancellationRequested) { - Thread.Sleep(TimeSpan.FromMilliseconds(50)); + // Only actively-running threads are shown in the thread dump, so we need to make sure the CPU is in use. + Thread.SpinWait(250); +#if NET8_0 + // Yield to allow the EventPipe rundown thread to make progress on .NET 8. + Thread.Sleep(0); +#endif } } }