Skip to content

Commit e91e355

Browse files
authored
Improve management test coverage (#1520)
* Refactor tests for dbmigrations endpoint * Refactor tests for env endpoint - Only display changed values from placeholder/decryption providers - Show placeholder/decryption providers *after* the configuration providers they wrap - Hide providers that don't have any properties * Add internal file system abstraction for testability of disk space contributor * Order health check results in descending status * Simplify test health contributors (single purpose) * Refactor tests for health endpoint - Remove duplicate information in details for ASP.NET health checks - Fixed: X-Use-Status-Code-From-Response header not always respected - Fixed inconsistency in case-sensitivity of health group names * Refactor tests for health contributors, move availability contributors to matching namespace * Move HttpExchanges into MemoryDumps category * Refactor tests for heapdump endpoint * Refactor tests for threaddump endpoint * Refactor tests for httpexchanges endpoint - Replace IHttpExchangesRepository with IHttpExchangeRecorder, so that filtering logic becomes testable - Fixed: appsettings.json files from RazorPagesTestApp were still being copied by VS Build Acceleration - Fixed: options.IncludeTimeTaken was ignored * Reduce pressure when running all tests locally, so that DiagnosticObserverHttpExchangeRecorder doesn't fail * Refactor tests for hypermedia endpoint - Fixed: The value returned for "templated" was always false * Refactor tests for info endpoint - Fixed: adjust contributor nullability to allow null dictionary values - Fixed: do not skip lines in git.properties file that contain = character in their value * Refactor tests for loggers endpoint * Refactor tests for refresh endpoint - Fixed: order keys alphabetically, without duplicates - Fixed: throw when unable to reload, instead of silently do nothing * Refactor tests for mappings endpoint * Refactor tests for beans endpoint * Revise tests for dependent services: get middleware instance to ensure all downstream dependencies are registered * Simplify tests for options: there's no added value in using host builders * Cleanup tests for management/endpoint options - Fixed: allow clearing default exposure using Spring-style configuration keys - Fixed: remove duplicate entries in exposure over regular and Spring-style keys * Remove unused types * Add tests for Spring Boot Admin * Move content negotation tests for SBA * Refactor tests for all actuators * Adapt configuration key names to .NET naming convention, inline constants * Rename/inline test type * Refactor tests for cloudfoundryapplication endpoint - Order the returned list of endpoints by ID - Critical fix: block /cloudfoundryapplication and log warning when security middleware not added - Critical fix: don't turn off all security when the /cloudfoundryapplication hypermedia endpoint is turned off * Do not hide empty sources in env endpoint for Spring Boot compatibility * Fix line endings in *.git.properties files * Centralize "appsettings.json" constant
1 parent 86ae318 commit e91e355

File tree

246 files changed

+9345
-8848
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

246 files changed

+9345
-8848
lines changed

.gitattributes

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Enable running shell scripts from bash on Windows
2+
*.git.properties eol=lf

src/Common/src/Common/HealthChecks/HealthAggregator.cs

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
using System.Collections.Concurrent;
66
using Microsoft.Extensions.Diagnostics.HealthChecks;
7-
using Steeltoe.Common.CasingConventions;
87
using Steeltoe.Common.Extensions;
98
using MicrosoftHealthCheckResult = Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult;
109
using MicrosoftHealthStatus = Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus;
@@ -112,22 +111,14 @@ private static async Task<SteeltoeHealthCheckResult> RunMicrosoftHealthCheckAsyn
112111
IHealthCheck check = registration.Factory(serviceProvider);
113112
MicrosoftHealthCheckResult result = await check.CheckHealthAsync(context, cancellationToken);
114113

115-
SteeltoeHealthStatus status = ToHealthStatus(result.Status);
116-
healthCheckResult.Status = status; // Only used for aggregate, doesn't get reported
114+
healthCheckResult.Status = ToHealthStatus(result.Status);
117115
healthCheckResult.Description = result.Description;
118116

119117
foreach ((string key, object value) in result.Data)
120118
{
121119
healthCheckResult.Details[key] = value;
122120
}
123121

124-
healthCheckResult.Details["status"] = status.ToSnakeCaseString(SnakeCaseStyle.AllCaps);
125-
126-
if (result.Description != null)
127-
{
128-
healthCheckResult.Details.Add("description", result.Description);
129-
}
130-
131122
if (result.Exception != null && !string.IsNullOrEmpty(result.Exception.Message))
132123
{
133124
healthCheckResult.Details.Add("error", result.Exception.Message);
@@ -172,16 +163,61 @@ private static string GetKey(ConcurrentBag<string> keys, string key)
172163

173164
private static SteeltoeHealthCheckResult AddChecksSetStatus(SteeltoeHealthCheckResult result, IDictionary<string, SteeltoeHealthCheckResult> healthChecks)
174165
{
175-
foreach (KeyValuePair<string, SteeltoeHealthCheckResult> healthCheck in healthChecks)
166+
var orderedCheckResults = new SortedDictionary<CheckResultOrderingKey, SteeltoeHealthCheckResult>(CheckResultOrderingKeyComparer.Instance);
167+
168+
foreach ((string name, SteeltoeHealthCheckResult checkResult) in healthChecks)
176169
{
177-
if (healthCheck.Value.Status > result.Status)
170+
if (checkResult.Status > result.Status)
178171
{
179-
result.Status = healthCheck.Value.Status;
172+
result.Status = checkResult.Status;
180173
}
181174

182-
result.Details.Add(healthCheck.Key, healthCheck.Value);
175+
var orderingKey = new CheckResultOrderingKey(checkResult.Status, name);
176+
orderedCheckResults.Add(orderingKey, checkResult);
177+
}
178+
179+
foreach ((CheckResultOrderingKey orderingKey, SteeltoeHealthCheckResult checkResult) in orderedCheckResults)
180+
{
181+
result.Details.Add(orderingKey.Name, checkResult);
183182
}
184183

185184
return result;
186185
}
186+
187+
private sealed record CheckResultOrderingKey(SteeltoeHealthStatus Status, string Name);
188+
189+
private sealed class CheckResultOrderingKeyComparer : IComparer<CheckResultOrderingKey>
190+
{
191+
private static readonly List<SteeltoeHealthStatus> HealthStatusOrder =
192+
[
193+
SteeltoeHealthStatus.Down,
194+
SteeltoeHealthStatus.OutOfService,
195+
SteeltoeHealthStatus.Warning,
196+
SteeltoeHealthStatus.Unknown,
197+
SteeltoeHealthStatus.Up
198+
];
199+
200+
public static CheckResultOrderingKeyComparer Instance { get; } = new();
201+
202+
private CheckResultOrderingKeyComparer()
203+
{
204+
}
205+
206+
public int Compare(CheckResultOrderingKey? x, CheckResultOrderingKey? y)
207+
{
208+
if (x == null || y == null)
209+
{
210+
return Comparer<CheckResultOrderingKey>.Default.Compare(x, y);
211+
}
212+
213+
int result = HealthStatusOrder.IndexOf(x.Status).CompareTo(HealthStatusOrder.IndexOf(y.Status));
214+
215+
if (result == 0)
216+
{
217+
result = string.Compare(x.Name, y.Name, StringComparison.Ordinal);
218+
}
219+
220+
return result;
221+
}
222+
}
187223
}

src/Common/test/Common.Test/ApplicationInstanceInfoTest.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using Microsoft.Extensions.Configuration;
77
using Microsoft.Extensions.DependencyInjection;
88
using Steeltoe.Common.Extensions;
9+
using Steeltoe.Common.TestResources;
910
using Steeltoe.Common.TestResources.IO;
1011

1112
namespace Steeltoe.Common.Test;
@@ -34,7 +35,7 @@ public async Task ReadsApplicationConfiguration()
3435
""";
3536

3637
using var sandbox = new Sandbox();
37-
string path = sandbox.CreateFile("appsettings.json", configJson);
38+
string path = sandbox.CreateFile(MemoryFileProvider.DefaultAppSettingsFileName, configJson);
3839
string directory = Path.GetDirectoryName(path)!;
3940
string fileName = Path.GetFileName(path);
4041
var builder = new ConfigurationBuilder();
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System.Diagnostics;
6+
7+
namespace Steeltoe.Common.TestResources;
8+
9+
/// <summary>
10+
/// A no-op replacement for the built-in <see cref="DiagnosticListener" />.
11+
/// </summary>
12+
/// <para>
13+
/// This type is registered by host builders used in tests. It prevents failure in DiagnosticObserverHttpExchangeRecorder when many tests are running.
14+
/// </para>
15+
internal sealed class InactiveDiagnosticListener()
16+
: DiagnosticListener("Empty")
17+
{
18+
public override bool IsEnabled(string name)
19+
{
20+
return false;
21+
}
22+
23+
public override bool IsEnabled(string name, object? arg1, object? arg2 = null)
24+
{
25+
return false;
26+
}
27+
28+
public override IDisposable Subscribe(IObserver<KeyValuePair<string, object?>> observer)
29+
{
30+
return EmptyDisposable.Instance;
31+
}
32+
33+
public override IDisposable Subscribe(IObserver<KeyValuePair<string, object?>> observer, Func<string, object?, object?, bool>? isEnabled)
34+
{
35+
return EmptyDisposable.Instance;
36+
}
37+
38+
public override IDisposable Subscribe(IObserver<KeyValuePair<string, object?>> observer, Predicate<string>? isEnabled)
39+
{
40+
return EmptyDisposable.Instance;
41+
}
42+
43+
// ReSharper disable once MethodOverloadWithOptionalParameter
44+
public override IDisposable Subscribe(IObserver<KeyValuePair<string, object?>> observer, Func<string, object?, object?, bool>? isEnabled,
45+
Action<Activity, object?>? onActivityImport = null, Action<Activity, object?>? onActivityExport = null)
46+
{
47+
return EmptyDisposable.Instance;
48+
}
49+
50+
public override void Write(string name, object? value)
51+
{
52+
}
53+
54+
public override void OnActivityExport(Activity activity, object? payload)
55+
{
56+
}
57+
58+
public override void OnActivityImport(Activity activity, object? payload)
59+
{
60+
}
61+
}

src/Common/test/TestResources/MemoryFileProvider.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ namespace Steeltoe.Common.TestResources;
1212

1313
public sealed class MemoryFileProvider : IFileProvider
1414
{
15+
public const string DefaultAppSettingsFileName = "appsettings.json";
16+
1517
private static readonly char[] DirectorySeparators =
1618
[
1719
Path.DirectorySeparatorChar,

src/Common/test/TestResources/TestHostApplicationBuilderFactory.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
33
// See the LICENSE file in the project root for more information.
44

5+
using System.Diagnostics;
56
using Microsoft.Extensions.DependencyInjection;
7+
using Microsoft.Extensions.DependencyInjection.Extensions;
68
using Microsoft.Extensions.Hosting;
79

810
namespace Steeltoe.Common.TestResources;
@@ -21,7 +23,7 @@ public static class TestHostApplicationBuilderFactory
2123
public static HostApplicationBuilder Create()
2224
{
2325
HostApplicationBuilder builder = Host.CreateEmptyApplicationBuilder(new HostApplicationBuilderSettings());
24-
ConfigureBuilder(builder);
26+
ConfigureBuilder(builder, true);
2527

2628
return builder;
2729
}
@@ -39,13 +41,18 @@ public static HostApplicationBuilder Create(string[] args)
3941
Args = args
4042
});
4143

42-
ConfigureBuilder(builder);
44+
ConfigureBuilder(builder, true);
4345

4446
return builder;
4547
}
4648

47-
private static void ConfigureBuilder(HostApplicationBuilder builder)
49+
private static void ConfigureBuilder(HostApplicationBuilder builder, bool deactivateDiagnostics)
4850
{
4951
builder.ConfigureContainer(new DefaultServiceProviderFactory(ValidatingServiceProviderOptions));
52+
53+
if (deactivateDiagnostics)
54+
{
55+
builder.Services.Replace(ServiceDescriptor.Singleton<DiagnosticListener, InactiveDiagnosticListener>());
56+
}
5057
}
5158
}

src/Common/test/TestResources/TestHostBuilderFactory.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
33
// See the LICENSE file in the project root for more information.
44

5+
using System.Diagnostics;
56
using Microsoft.AspNetCore.Builder;
67
using Microsoft.AspNetCore.Hosting;
78
using Microsoft.AspNetCore.TestHost;
89
using Microsoft.Extensions.DependencyInjection;
10+
using Microsoft.Extensions.DependencyInjection.Extensions;
911
using Microsoft.Extensions.Hosting;
1012

1113
namespace Steeltoe.Common.TestResources;
@@ -25,20 +27,20 @@ public static class TestHostBuilderFactory
2527
public static HostBuilder Create()
2628
{
2729
var builder = new HostBuilder();
28-
ConfigureBuilder(builder, false, false);
30+
ConfigureBuilder(builder, false, false, true);
2931

3032
return builder;
3133
}
3234

3335
public static HostBuilder CreateWeb()
3436
{
3537
var builder = new HostBuilder();
36-
ConfigureBuilder(builder, true, true);
38+
ConfigureBuilder(builder, true, true, true);
3739

3840
return builder;
3941
}
4042

41-
private static void ConfigureBuilder(IHostBuilder builder, bool configureWebHost, bool useTestServer)
43+
private static void ConfigureBuilder(HostBuilder builder, bool configureWebHost, bool useTestServer, bool deactivateDiagnostics)
4244
{
4345
builder.UseDefaultServiceProvider(ConfigureServiceProvider);
4446

@@ -54,5 +56,10 @@ private static void ConfigureBuilder(IHostBuilder builder, bool configureWebHost
5456
}
5557
});
5658
}
59+
60+
if (deactivateDiagnostics)
61+
{
62+
builder.ConfigureServices(services => services.Replace(ServiceDescriptor.Singleton<DiagnosticListener, InactiveDiagnosticListener>()));
63+
}
5764
}
5865
}

src/Common/test/TestResources/TestWebApplicationBuilderFactory.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
33
// See the LICENSE file in the project root for more information.
44

5+
using System.Diagnostics;
56
using Microsoft.AspNetCore.Builder;
67
using Microsoft.AspNetCore.Hosting;
78
using Microsoft.AspNetCore.TestHost;
89
using Microsoft.Extensions.DependencyInjection;
10+
using Microsoft.Extensions.DependencyInjection.Extensions;
911

1012
namespace Steeltoe.Common.TestResources;
1113

@@ -52,7 +54,7 @@ public static WebApplicationBuilder Create(string[] args)
5254
public static WebApplicationBuilder Create(WebApplicationOptions options)
5355
{
5456
WebApplicationBuilder builder = WebApplication.CreateEmptyBuilder(options);
55-
ConfigureBuilder(builder, true);
57+
ConfigureBuilder(builder, true, true);
5658

5759
return builder;
5860
}
@@ -80,18 +82,23 @@ public static WebApplicationBuilder CreateDefault()
8082
public static WebApplicationBuilder CreateDefault(bool useTestServer)
8183
{
8284
WebApplicationBuilder builder = WebApplication.CreateBuilder();
83-
ConfigureBuilder(builder, useTestServer);
85+
ConfigureBuilder(builder, useTestServer, false);
8486

8587
return builder;
8688
}
8789

88-
private static void ConfigureBuilder(WebApplicationBuilder builder, bool useTestServer)
90+
private static void ConfigureBuilder(WebApplicationBuilder builder, bool useTestServer, bool deactivateDiagnostics)
8991
{
9092
builder.WebHost.UseDefaultServiceProvider(ConfigureServiceProvider);
9193

9294
if (useTestServer)
9395
{
9496
builder.WebHost.UseTestServer();
9597
}
98+
99+
if (deactivateDiagnostics)
100+
{
101+
builder.Services.Replace(ServiceDescriptor.Singleton<DiagnosticListener, InactiveDiagnosticListener>());
102+
}
96103
}
97104
}

src/Common/test/TestResources/TestWebHostBuilderFactory.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
33
// See the LICENSE file in the project root for more information.
44

5+
using System.Diagnostics;
56
using Microsoft.AspNetCore.Builder;
67
using Microsoft.AspNetCore.Hosting;
78
using Microsoft.AspNetCore.TestHost;
89
using Microsoft.Extensions.DependencyInjection;
10+
using Microsoft.Extensions.DependencyInjection.Extensions;
911

1012
namespace Steeltoe.Common.TestResources;
1113

@@ -29,12 +31,12 @@ public static WebHostBuilder Create()
2931
public static WebHostBuilder Create(bool useTestServer)
3032
{
3133
var builder = new WebHostBuilder();
32-
ConfigureBuilder(builder, useTestServer);
34+
ConfigureBuilder(builder, useTestServer, true);
3335

3436
return builder;
3537
}
3638

37-
private static void ConfigureBuilder(IWebHostBuilder builder, bool useTestServer)
39+
private static void ConfigureBuilder(WebHostBuilder builder, bool useTestServer, bool deactivateDiagnostics)
3840
{
3941
builder.UseDefaultServiceProvider(ConfigureServiceProvider);
4042
builder.Configure(EmptyAction);
@@ -43,5 +45,10 @@ private static void ConfigureBuilder(IWebHostBuilder builder, bool useTestServer
4345
{
4446
builder.UseTestServer();
4547
}
48+
49+
if (deactivateDiagnostics)
50+
{
51+
builder.ConfigureServices(services => services.Replace(ServiceDescriptor.Singleton<DiagnosticListener, InactiveDiagnosticListener>()));
52+
}
4653
}
4754
}

src/Configuration/src/Abstractions/ConfigurationProviderEnumerationExtensions.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,6 @@ private static IEnumerable<IConfigurationProvider> FilterProviders(IEnumerable<I
6666
{
6767
foreach (IConfigurationProvider provider in providers)
6868
{
69-
if (predicate(provider))
70-
{
71-
yield return provider;
72-
}
73-
7469
if (provider is ChainedConfigurationProvider chainedConfigurationProvider)
7570
{
7671
foreach (IConfigurationProvider match in EnumerateProviders(chainedConfigurationProvider.Configuration, predicate))
@@ -86,6 +81,11 @@ private static IEnumerable<IConfigurationProvider> FilterProviders(IEnumerable<I
8681
yield return match;
8782
}
8883
}
84+
85+
if (predicate(provider))
86+
{
87+
yield return provider;
88+
}
8989
}
9090
}
9191
}

0 commit comments

Comments
 (0)