diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json
index 0763ef1c5b..24ea9f438e 100644
--- a/.config/dotnet-tools.json
+++ b/.config/dotnet-tools.json
@@ -15,6 +15,13 @@
"regitlint"
],
"rollForward": false
+ },
+ "dotnet-reportgenerator-globaltool": {
+ "version": "5.5.0",
+ "commands": [
+ "reportgenerator"
+ ],
+ "rollForward": false
}
}
}
\ No newline at end of file
diff --git a/.github/workflows/Steeltoe.All.yml b/.github/workflows/Steeltoe.All.yml
index d4b5897ca1..a5b65e8c0c 100644
--- a/.github/workflows/Steeltoe.All.yml
+++ b/.github/workflows/Steeltoe.All.yml
@@ -17,12 +17,14 @@ permissions:
pull-requests: write
env:
+ STEELTOE_MACOS_DIAGNOSE_HOSTNAME_LOOKUP: true
DOTNET_CLI_TELEMETRY_OPTOUT: 1
DOTNET_NOLOGO: true
SOLUTION_FILE: 'src/Steeltoe.All.sln'
+ TEST_OUTPUT_DIRECTORY: '${{ github.workspace }}/TestOutput'
COMMON_TEST_ARGS: >-
- --no-build --configuration Release --collect "XPlat Code Coverage" --logger trx --results-directory ${{ github.workspace }}/dumps
- --settings coverlet.runsettings --blame-crash --blame-hang-timeout 3m
+ --no-build --no-progress --configuration Release --results-directory '${{ github.workspace }}/TestOutput'
+ --report-trx --coverage --coverage-settings coverage.config --crashdump --hangdump --hangdump-timeout 1m
jobs:
analyze:
@@ -36,9 +38,9 @@ jobs:
- os: ubuntu-latest
runDockerContainers: true
- os: windows-latest
- skipFilter: Category!=Integration
+ skipIntegrationTests: true
- os: macos-latest
- skipFilter: Category!=Integration
+ skipIntegrationTests: true
runs-on: ${{ matrix.os }}
continue-on-error: true
@@ -89,29 +91,11 @@ jobs:
- name: Build solution
run: dotnet build ${{ env.SOLUTION_FILE }} --no-restore --configuration Release --verbosity minimal
- - name: Set skip filters for tests
- shell: bash
- run: |
- echo SKIP_FILTER_NO_MEMORY_DUMPS="${{ matrix.skipFilter && format('{0}&Category!=MemoryDumps', matrix.skipFilter) || 'Category!=MemoryDumps' }}" >> $GITHUB_ENV
- echo SKIP_FILTER_WITH_MEMORY_DUMPS="${{ matrix.skipFilter && format('{0}&Category=MemoryDumps', matrix.skipFilter) || 'Category=MemoryDumps' }}" >> $GITHUB_ENV
-
- - name: Test (net10.0)
- run: dotnet test ${{ env.SOLUTION_FILE }} --framework net10.0 --filter "${{ env.SKIP_FILTER_NO_MEMORY_DUMPS }}" ${{ env.COMMON_TEST_ARGS }}
-
- - name: Test (net10.0) (memory dumps)
- run: dotnet test ${{ env.SOLUTION_FILE }} --framework net10.0 --filter "${{ env.SKIP_FILTER_WITH_MEMORY_DUMPS }}" ${{ env.COMMON_TEST_ARGS }}
-
- - name: Test (net9.0)
- run: dotnet test ${{ env.SOLUTION_FILE }} --framework net9.0 --filter "${{ env.SKIP_FILTER_NO_MEMORY_DUMPS }}" ${{ env.COMMON_TEST_ARGS }}
-
- - name: Test (net9.0) (memory dumps)
- run: dotnet test ${{ env.SOLUTION_FILE }} --framework net9.0 --filter "${{ env.SKIP_FILTER_WITH_MEMORY_DUMPS }}" ${{ env.COMMON_TEST_ARGS }}
-
- - name: Test (net8.0)
- run: dotnet test ${{ env.SOLUTION_FILE }} --framework net8.0 --filter "${{ env.SKIP_FILTER_NO_MEMORY_DUMPS }}" ${{ env.COMMON_TEST_ARGS }}
+ - name: Test
+ run: dotnet test --solution ${{ env.SOLUTION_FILE }} --filter-query "${{ matrix.skipIntegrationTests == true && '/[(Category!=MemoryDumps)&(Category!=Integration)]' || '/[Category!=MemoryDumps]' }}" ${{ env.COMMON_TEST_ARGS }}
- - name: Test (net8.0) (memory dumps)
- run: dotnet test ${{ env.SOLUTION_FILE }} --framework net8.0 --filter "${{ env.SKIP_FILTER_WITH_MEMORY_DUMPS }}" ${{ env.COMMON_TEST_ARGS }}
+ - name: Test (memory dumps)
+ run: dotnet test --project src/Management/test/Endpoint.Test/Steeltoe.Management.Endpoint.Test.csproj --filter-trait "Category=MemoryDumps" ${{ env.COMMON_TEST_ARGS }}
- name: Upload crash/hang dumps (on failure)
if: ${{ failure() }}
@@ -119,8 +103,8 @@ jobs:
with:
name: FailedTestOutput-${{ matrix.os }}
path: |
- ${{ github.workspace }}/dumps/**/*.dmp
- ${{ github.workspace }}/dumps/**/Sequence_*.xml
+ ${{ env.TEST_OUTPUT_DIRECTORY }}/*.dmp
+ ${{ env.TEST_OUTPUT_DIRECTORY }}/Sequence_*.xml
if-no-files-found: ignore
- name: Report test results
@@ -129,14 +113,15 @@ jobs:
with:
name: ${{ matrix.os }} test results
reporter: dotnet-trx
- path: '**/*.trx'
+ path: '${{ env.TEST_OUTPUT_DIRECTORY }}/*.trx'
+ path-replace-backslashes: true
fail-on-empty: 'true'
fail-on-error: 'false'
- name: Generate code coverage report
uses: danielpalme/ReportGenerator-GitHub-Action@v5
with:
- reports: '**/coverage.opencover.xml'
+ reports: '${{ env.TEST_OUTPUT_DIRECTORY }}/*cobertura.xml'
targetdir: 'coveragereport'
reporttypes: 'MarkdownAssembliesSummary;MarkdownSummaryGithub'
filefilters: '-*.g.cs'
diff --git a/.github/workflows/component-shared-workflow.yml b/.github/workflows/component-shared-workflow.yml
index 229e2f5801..1df0267540 100644
--- a/.github/workflows/component-shared-workflow.yml
+++ b/.github/workflows/component-shared-workflow.yml
@@ -19,12 +19,14 @@ permissions:
pull-requests: write
env:
+ STEELTOE_MACOS_DIAGNOSE_HOSTNAME_LOOKUP: true
DOTNET_CLI_TELEMETRY_OPTOUT: 1
DOTNET_NOLOGO: true
SOLUTION_FILE: 'src/Steeltoe.${{ inputs.component }}.slnf'
+ TEST_OUTPUT_DIRECTORY: '${{ github.workspace }}/TestOutput'
COMMON_TEST_ARGS: >-
- --no-build --configuration Release --collect "XPlat Code Coverage" --logger trx --results-directory ${{ github.workspace }}/dumps
- --settings coverlet.runsettings --blame-crash --blame-hang-timeout 3m
+ --no-build --no-progress --configuration Release --results-directory '${{ github.workspace }}/TestOutput'
+ --report-trx --coverage --coverage-settings coverage.config --crashdump --hangdump --hangdump-timeout 1m
jobs:
build:
@@ -79,26 +81,12 @@ jobs:
- name: Build solution
run: dotnet build ${{ env.SOLUTION_FILE }} --no-restore --configuration Release --verbosity minimal
- - name: Test (net10.0)
- run: dotnet test ${{ env.SOLUTION_FILE }} --framework net10.0 --filter "Category!=MemoryDumps" ${{ env.COMMON_TEST_ARGS }}
+ - name: Test
+ run: dotnet test --solution ${{ env.SOLUTION_FILE }} --filter-not-trait "Category=MemoryDumps" ${{ env.COMMON_TEST_ARGS }}
- - name: Test (net10.0) (memory dumps)
+ - name: Test (memory dumps)
if: ${{ inputs.component == 'Management' }}
- run: dotnet test ${{ env.SOLUTION_FILE }} --framework net10.0 --filter "Category=MemoryDumps" ${{ env.COMMON_TEST_ARGS }}
-
- - name: Test (net9.0)
- run: dotnet test ${{ env.SOLUTION_FILE }} --framework net9.0 --filter "Category!=MemoryDumps" ${{ env.COMMON_TEST_ARGS }}
-
- - name: Test (net9.0) (memory dumps)
- if: ${{ inputs.component == 'Management' }}
- run: dotnet test ${{ env.SOLUTION_FILE }} --framework net9.0 --filter "Category=MemoryDumps" ${{ env.COMMON_TEST_ARGS }}
-
- - name: Test (net8.0)
- run: dotnet test ${{ env.SOLUTION_FILE }} --framework net8.0 --filter "Category!=MemoryDumps" ${{ env.COMMON_TEST_ARGS }}
-
- - name: Test (net8.0) (memory dumps)
- if: ${{ inputs.component == 'Management' }}
- run: dotnet test ${{ env.SOLUTION_FILE }} --framework net8.0 --filter "Category=MemoryDumps" ${{ env.COMMON_TEST_ARGS }}
+ run: dotnet test --project src/Management/test/Endpoint.Test/Steeltoe.Management.Endpoint.Test.csproj --filter-trait "Category=MemoryDumps" ${{ env.COMMON_TEST_ARGS }}
- name: Upload crash/hang dumps (on failure)
if: ${{ failure() }}
@@ -106,8 +94,8 @@ jobs:
with:
name: FailedTestOutput-${{ inputs.OS }}-latest
path: |
- ${{ github.workspace }}/dumps/**/*.dmp
- ${{ github.workspace }}/dumps/**/Sequence_*.xml
+ ${{ env.TEST_OUTPUT_DIRECTORY }}/*.dmp
+ ${{ env.TEST_OUTPUT_DIRECTORY }}/Sequence_*.xml
if-no-files-found: ignore
- name: Report test results
@@ -116,6 +104,7 @@ jobs:
with:
name: ${{ inputs.OS }}-latest test results
reporter: dotnet-trx
- path: '**/*.trx'
+ path: '${{ env.TEST_OUTPUT_DIRECTORY }}/*.trx'
+ path-replace-backslashes: true
fail-on-empty: 'true'
fail-on-error: 'false'
diff --git a/.github/workflows/sonarcube.yml b/.github/workflows/sonarcube.yml
index 2fcebd9f8a..bac19c61a1 100644
--- a/.github/workflows/sonarcube.yml
+++ b/.github/workflows/sonarcube.yml
@@ -18,12 +18,14 @@ permissions:
pull-requests: write
env:
+ STEELTOE_MACOS_DIAGNOSE_HOSTNAME_LOOKUP: true
DOTNET_CLI_TELEMETRY_OPTOUT: 1
DOTNET_NOLOGO: true
SOLUTION_FILE: 'src/Steeltoe.All.sln'
+ TEST_OUTPUT_DIRECTORY: '${{ github.workspace }}/TestOutput'
SONAR_TEST_ARGS: >-
- --no-build --configuration Release --collect "XPlat Code Coverage" --logger trx --results-directory ${{ github.workspace }}
- --settings coverlet.runsettings -- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.UseSourceLink=false
+ --no-build --no-progress --configuration Release --results-directory '${{ github.workspace }}/TestOutput'
+ --report-trx --coverage --coverage-settings coverage.config
jobs:
analyze:
@@ -73,29 +75,33 @@ jobs:
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: >-
+ # TODO: Revert to OpenCover, see https://github.com/microsoft/testfx/issues/7104
+ # /d:sonar.cs.opencover.reportsPaths=**/coverage.opencover.xml
dotnet sonarscanner begin /k:"SteeltoeOSS_steeltoe" /o:"steeltoeoss" /d:sonar.token="${{ secrets.SONAR_TOKEN }}"
- /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.opencover.reportsPaths=**/coverage.opencover.xml
+ /d:sonar.host.url="https://sonarcloud.io" /d:sonar.coverageReportPaths=TestOutput/SonarQube.xml
- name: Build solution
run: dotnet build ${{ env.SOLUTION_FILE }} --no-restore --configuration Release --verbosity minimal
- - name: Test (net10.0)
- run: dotnet test ${{ env.SOLUTION_FILE }} --filter "Category!=MemoryDumps" --framework net10.0 ${{ env.SONAR_TEST_ARGS }}
+ - name: Test
+ run: dotnet test --solution ${{ env.SOLUTION_FILE }} --filter-not-trait "Category=MemoryDumps" ${{ env.SONAR_TEST_ARGS }}
- - name: Test (net10.0) (memory dumps)
- run: dotnet test ${{ env.SOLUTION_FILE }} --filter "Category=MemoryDumps" --framework net10.0 ${{ env.SONAR_TEST_ARGS }}
+ - name: Test (memory dumps)
+ run: dotnet test --project src/Management/test/Endpoint.Test/Steeltoe.Management.Endpoint.Test.csproj --filter-trait "Category=MemoryDumps" ${{ env.SONAR_TEST_ARGS }}
- - name: Test (net9.0)
- run: dotnet test ${{ env.SOLUTION_FILE }} --filter "Category!=MemoryDumps" --framework net9.0 ${{ env.SONAR_TEST_ARGS }}
+ - name: 'TEMP: List files before coverage conversion'
+ run: find ${{ env.TEST_OUTPUT_DIRECTORY }}
- - name: Test (net9.0) (memory dumps)
- run: dotnet test ${{ env.SOLUTION_FILE }} --filter "Category=MemoryDumps" --framework net9.0 ${{ env.SONAR_TEST_ARGS }}
-
- - name: Test (net8.0)
- run: dotnet test ${{ env.SOLUTION_FILE }} --filter "Category!=MemoryDumps" --framework net8.0 ${{ env.SONAR_TEST_ARGS }}
+ - name: Convert Cobertura to Sonar format using ReportGenerator
+ uses: danielpalme/ReportGenerator-GitHub-Action@5.5.1
+ with:
+ reports: '${{ env.TEST_OUTPUT_DIRECTORY }}/*cobertura.xml'
+ targetdir: '${{ env.TEST_OUTPUT_DIRECTORY }}'
+ reporttypes: 'SonarQube'
+ filefilters: '-*.g.cs'
- - name: Test (net8.0) (memory dumps)
- run: dotnet test ${{ env.SOLUTION_FILE }} --filter "Category=MemoryDumps" --framework net8.0 ${{ env.SONAR_TEST_ARGS }}
+ - name: 'TEMP: List files after coverage conversion'
+ run: find ${{ env.TEST_OUTPUT_DIRECTORY }}
- name: End Sonar .NET scanner
if: ${{ !cancelled() && steps.sonar_begin.outcome == 'success' }}
diff --git a/Directory.Build.targets b/Directory.Build.targets
index b59583d8cd..65ab7c7c73 100644
--- a/Directory.Build.targets
+++ b/Directory.Build.targets
@@ -1,6 +1,12 @@
+
+
+
+
+
@@ -101,7 +107,7 @@
-
+
@@ -123,7 +129,7 @@
+ Text="ConfigurationSchema.json is out of date for $(MSBuildProjectFile). Run 'dotnet build --no-incremental /p:UpdateConfigurationSchema=true' to update it." />
diff --git a/coverage.config b/coverage.config
new file mode 100644
index 0000000000..9210688ee0
--- /dev/null
+++ b/coverage.config
@@ -0,0 +1,29 @@
+
+
+
+ cobertura
+ true
+
+
+
+ .*ConfigurationSchemaGenerator.*
+
+
+
+
+ ^System\.ObsoleteAttribute$
+ ^System\.CodeDom\.Compiler\.GeneratedCodeAttribute$
+ ^System\.Runtime\.CompilerServices\.CompilerGeneratedAttribute$
+ ^System\.Diagnostics\.CodeAnalysis\.ExcludeFromCodeCoverageAttribute$
+
+
+
+
+ .*\\test\\.*
+
+
+
+
diff --git a/coverlet.runsettings b/coverlet.runsettings
deleted file mode 100644
index fe0adb82b8..0000000000
--- a/coverlet.runsettings
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
-
- opencover
- [ConfigurationSchemaGenerator]*
- **/test/**/*.*
- ObsoleteAttribute,GeneratedCodeAttribute,CompilerGeneratedAttribute
- true
-
-
-
-
-
diff --git a/global.json b/global.json
new file mode 100644
index 0000000000..3140116df3
--- /dev/null
+++ b/global.json
@@ -0,0 +1,5 @@
+{
+ "test": {
+ "runner": "Microsoft.Testing.Platform"
+ }
+}
diff --git a/macos-dump-entitlements.plist b/macos-dump-entitlements.plist
new file mode 100644
index 0000000000..41bb93a0c7
--- /dev/null
+++ b/macos-dump-entitlements.plist
@@ -0,0 +1,16 @@
+
+
+
+
+ com.apple.security.cs.allow-jit
+
+ com.apple.security.cs.allow-dyld-environment-variables
+
+ com.apple.security.cs.disable-library-validation
+
+ com.apple.security.cs.debugger
+
+ com.apple.security.get-task-allow
+
+
+
\ No newline at end of file
diff --git a/mtp-test-entitlements.plist b/mtp-test-entitlements.plist
new file mode 100644
index 0000000000..41bb93a0c7
--- /dev/null
+++ b/mtp-test-entitlements.plist
@@ -0,0 +1,16 @@
+
+
+
+
+ com.apple.security.cs.allow-jit
+
+ com.apple.security.cs.allow-dyld-environment-variables
+
+ com.apple.security.cs.disable-library-validation
+
+ com.apple.security.cs.debugger
+
+ com.apple.security.get-task-allow
+
+
+
\ No newline at end of file
diff --git a/nuget.config b/nuget.config
index 128d95e590..94d8574860 100644
--- a/nuget.config
+++ b/nuget.config
@@ -3,10 +3,6 @@
+
-
-
-
-
-
diff --git a/shared-test.props b/shared-test.props
index 16dad857a8..58c1999cb1 100644
--- a/shared-test.props
+++ b/shared-test.props
@@ -1,13 +1,14 @@
Exe
+ false
$(NoWarn);S2094;S3717;SA1602;CA1062;CA1707;NU5104
-
- false
- true
+ true
+
+ $(NoWarn);NU3018;NU3027;NU3042
@@ -16,14 +17,15 @@
-
-
+
+
+
+
-
-
+
diff --git a/src/Common/src/Common/Calculator.cs b/src/Common/src/Common/Calculator.cs
new file mode 100644
index 0000000000..7ac7bba3dc
--- /dev/null
+++ b/src/Common/src/Common/Calculator.cs
@@ -0,0 +1,23 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information.
+
+namespace Steeltoe.Common;
+
+public sealed class Calculator
+{
+ public int Add(int left, int right)
+ {
+ if (left < 0 || right < 0)
+ {
+ throw new ArgumentException("Only non-negative integers are allowed.");
+ }
+
+ return left + right;
+ }
+
+ public int Subtract(int left, int right)
+ {
+ return left - right;
+ }
+}
diff --git a/src/Common/src/Common/Net/DomainNameResolver.cs b/src/Common/src/Common/Net/DomainNameResolver.cs
index 0b1da12ddd..30fd0e55bd 100644
--- a/src/Common/src/Common/Net/DomainNameResolver.cs
+++ b/src/Common/src/Common/Net/DomainNameResolver.cs
@@ -9,6 +9,8 @@ namespace Steeltoe.Common.Net;
internal sealed class DomainNameResolver : IDomainNameResolver
{
+ private static readonly bool IsInDiagnosticsMode = Environment.GetEnvironmentVariable("STEELTOE_MACOS_DIAGNOSE_HOSTNAME_LOOKUP") == "true";
+
public static DomainNameResolver Instance { get; } = new();
private DomainNameResolver()
@@ -42,22 +44,44 @@ private DomainNameResolver()
public string? ResolveHostName(bool throwOnError = false)
{
+ // Gather diagnostic information to investigate intermittent failures on macOS.
+ string? resultFromGetHostName = null;
+ string? resultFromGetHostEntry = null;
+ bool? workaroundApplied = null;
+
try
{
string hostName = Dns.GetHostName();
+ resultFromGetHostName = hostName;
if (string.IsNullOrEmpty(hostName))
{
// Workaround for failure when running on macOS.
// See https://github.com/actions/runner-images/issues/1335 and https://github.com/dotnet/runtime/issues/36849.
+
hostName = "localhost";
+ workaroundApplied = true;
}
IPHostEntry hostEntry = Dns.GetHostEntry(hostName);
- return hostEntry.HostName;
+ resultFromGetHostEntry = hostEntry.HostName;
+
+ if (IsInDiagnosticsMode && string.IsNullOrEmpty(resultFromGetHostEntry))
+ {
+ throw new InvalidOperationException($"IPHostEntry.HostName returned {GetTextFor(resultFromGetHostEntry)}.");
+ }
+
+ return resultFromGetHostEntry;
}
- catch (Exception)
+ catch (Exception exception)
{
+ if (IsInDiagnosticsMode)
+ {
+ throw new InvalidOperationException(
+ $"Failed to resolve hostname. GetHostName={GetTextFor(resultFromGetHostName)}, GetHostEntry={GetTextFor(resultFromGetHostEntry)}, WorkaroundApplied={workaroundApplied}",
+ exception);
+ }
+
if (throwOnError)
{
throw;
@@ -66,4 +90,14 @@ private DomainNameResolver()
return null;
}
}
+
+ private static string GetTextFor(string? value)
+ {
+ if (value == null)
+ {
+ return "(null)";
+ }
+
+ return value.Length == 0 ? "(empty)" : value;
+ }
}
diff --git a/src/Common/src/Common/PublicAPI.Unshipped.txt b/src/Common/src/Common/PublicAPI.Unshipped.txt
index 4d8338db45..37bf23d14d 100644
--- a/src/Common/src/Common/PublicAPI.Unshipped.txt
+++ b/src/Common/src/Common/PublicAPI.Unshipped.txt
@@ -1,4 +1,8 @@
#nullable enable
+Steeltoe.Common.Calculator
+Steeltoe.Common.Calculator.Add(int left, int right) -> int
+Steeltoe.Common.Calculator.Calculator() -> void
+Steeltoe.Common.Calculator.Subtract(int left, int right) -> int
Steeltoe.Common.Discovery.IServiceInstance.InstanceId.get -> string!
Steeltoe.Common.Discovery.IServiceInstance.NonSecureUri.get -> System.Uri?
Steeltoe.Common.Discovery.IServiceInstance.SecureUri.get -> System.Uri?
diff --git a/src/Common/test/Common.Test/CalculatorTest.cs b/src/Common/test/Common.Test/CalculatorTest.cs
new file mode 100644
index 0000000000..0707844391
--- /dev/null
+++ b/src/Common/test/Common.Test/CalculatorTest.cs
@@ -0,0 +1,22 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information.
+
+namespace Steeltoe.Common.Test;
+
+public sealed class CalculatorTest
+{
+ [Fact]
+ public void Add_Returns_Correct_Sum()
+ {
+ var calculator = new Calculator();
+ int result = calculator.Add(3, 5);
+ result.Should().Be(8);
+ }
+
+ [Fact(Skip = "ExampleSkippedTest")]
+ public void SkippedTest()
+ {
+ true.Should().BeFalse();
+ }
+}
diff --git a/src/Common/test/TestResources/FluentAssertionsExtensions.cs b/src/Common/test/TestResources/FluentAssertionsExtensions.cs
index ef96ceb3b3..2b41838878 100644
--- a/src/Common/test/TestResources/FluentAssertionsExtensions.cs
+++ b/src/Common/test/TestResources/FluentAssertionsExtensions.cs
@@ -52,4 +52,48 @@ private static string ToJsonString(JsonDocument document)
writer.Flush();
return Encoding.UTF8.GetString(stream.ToArray());
}
+
+ ///
+ /// Same as the built-in Be() method, but allows specifying a custom comparer.
+ ///
+ ///
+ /// The source text to assert on.
+ ///
+ ///
+ /// The expected text.
+ ///
+ ///
+ /// An equality comparer to compare values.
+ ///
+ [CustomAssertion]
+ public static void Be(this StringAssertions source, string expected, IEqualityComparer comparer)
+ {
+ ArgumentNullException.ThrowIfNull(source);
+ ArgumentNullException.ThrowIfNull(expected);
+ ArgumentNullException.ThrowIfNull(comparer);
+
+ object subject = source.Subject;
+ subject.Should().Be(expected, comparer);
+ }
+
+ ///
+ /// Same as the built-in Contain() method, but normalizes line endings upfront.
+ ///
+ ///
+ /// The source text to assert on.
+ ///
+ ///
+ /// The expected text.
+ ///
+ [CustomAssertion]
+ public static void ContainLines(this StringAssertions source, string expected)
+ {
+ ArgumentNullException.ThrowIfNull(source);
+ ArgumentNullException.ThrowIfNull(expected);
+
+ string sourceText = source.Subject.ReplaceLineEndings();
+ string expectedText = expected.ReplaceLineEndings();
+
+ sourceText.Should().Contain(expectedText);
+ }
}
diff --git a/src/Connectors/test/Connectors.Test/Steeltoe.Connectors.Test.csproj b/src/Connectors/test/Connectors.Test/Steeltoe.Connectors.Test.csproj
index bf2405d3f8..4002d54b0e 100644
--- a/src/Connectors/test/Connectors.Test/Steeltoe.Connectors.Test.csproj
+++ b/src/Connectors/test/Connectors.Test/Steeltoe.Connectors.Test.csproj
@@ -14,6 +14,7 @@
+
diff --git a/src/Discovery/src/Consul/Registry/ConsulRegistration.cs b/src/Discovery/src/Consul/Registry/ConsulRegistration.cs
index c8861fd4d4..81bd573afc 100644
--- a/src/Discovery/src/Consul/Registry/ConsulRegistration.cs
+++ b/src/Discovery/src/Consul/Registry/ConsulRegistration.cs
@@ -35,7 +35,7 @@ internal sealed class ConsulRegistration : IServiceInstance
public bool IsSecure => _optionsMonitor.CurrentValue.EffectiveScheme == "https";
///
- public Uri Uri => new($"{_optionsMonitor.CurrentValue.EffectiveScheme}://{Host}:{Port}");
+ public Uri Uri => FormatUri();
///
public Uri? NonSecureUri => IsSecure ? null : Uri;
@@ -73,6 +73,20 @@ internal ConsulRegistration(AgentServiceRegistration innerRegistration, IOptions
Metadata = innerRegistration.Meta.AsReadOnly();
}
+ private Uri FormatUri()
+ {
+ string scheme = _optionsMonitor.CurrentValue.EffectiveScheme;
+
+ try
+ {
+ return new Uri($"{scheme}://{Host}:{Port}");
+ }
+ catch (UriFormatException exception)
+ {
+ throw new UriFormatException($"Failed to build URI from components. Scheme={scheme}, Host={Host},Port={Port}.", exception);
+ }
+ }
+
///
/// Creates a registration for the currently running app, to be submitted to the Consul server.
///
diff --git a/src/Logging/test/DynamicConsole.Test/DynamicConsoleLoggerProviderTest.cs b/src/Logging/test/DynamicConsole.Test/DynamicConsoleLoggerProviderTest.cs
index 9e237a86a9..3e85796499 100644
--- a/src/Logging/test/DynamicConsole.Test/DynamicConsoleLoggerProviderTest.cs
+++ b/src/Logging/test/DynamicConsole.Test/DynamicConsoleLoggerProviderTest.cs
@@ -504,7 +504,7 @@ public async Task CanUseJsonFormatterWithScopes()
]
}
- """);
+ """, IgnoreLineEndingsComparer.Instance);
}
[Fact]
diff --git a/src/Logging/test/DynamicSerilog.Test/DynamicSerilogLoggerProviderTest.cs b/src/Logging/test/DynamicSerilog.Test/DynamicSerilogLoggerProviderTest.cs
index 36c985c212..682a90fdc4 100644
--- a/src/Logging/test/DynamicSerilog.Test/DynamicSerilogLoggerProviderTest.cs
+++ b/src/Logging/test/DynamicSerilog.Test/DynamicSerilogLoggerProviderTest.cs
@@ -287,7 +287,7 @@ public void CanUseScopes()
[INF] Fully.Qualified.Type: {InnerScopeKey="InnerScopeValue", Scope=["OuterScope", "InnerScope=InnerScopeValue"]}
TestInfo
- """);
+ """, IgnoreLineEndingsComparer.Instance);
}
[Fact]
@@ -331,7 +331,7 @@ public void CanUseSerilogEnrichers()
[INF] Fully.Qualified.Type: {A=1}
Carries property A = 1, again
- """);
+ """, IgnoreLineEndingsComparer.Instance);
}
[Fact]
@@ -360,7 +360,7 @@ public void CanUseSerilogDestructuring()
logOutput.Should().Be("""
[INF] Fully.Qualified.Type: Processing of {"RequestUrl": "https://www.example.com", "UserAgent": "Steeltoe"} started.
- """);
+ """, IgnoreLineEndingsComparer.Instance);
}
[Fact]
@@ -391,7 +391,7 @@ public void CallsIntoMessageProcessors()
[INF] {SourceContext="Test", Scope=["TwoOne"]}
Three
- """);
+ """, IgnoreLineEndingsComparer.Instance);
}
private static IDynamicLoggerProvider CreateLoggerProvider(Action? configure = null)
diff --git a/src/Logging/test/DynamicSerilog.Test/HostBuilderTest.cs b/src/Logging/test/DynamicSerilog.Test/HostBuilderTest.cs
index fa38276223..151b001ca2 100644
--- a/src/Logging/test/DynamicSerilog.Test/HostBuilderTest.cs
+++ b/src/Logging/test/DynamicSerilog.Test/HostBuilderTest.cs
@@ -91,12 +91,12 @@ public async Task CanPreserveDefaultConsoleLoggerProvider()
logOutput.Should().Contain("SERILOG [INF] TestInfo");
logOutput.Should().Contain("SERILOG [ERR] TestError");
- logOutput.Should().Contain($"""
+ logOutput.Should().ContainLines($"""
info: {typeof(HostBuilderTest)}[0]
TestInfo
""");
- logOutput.Should().Contain($"""
+ logOutput.Should().ContainLines($"""
fail: {typeof(HostBuilderTest)}[0]
TestError
""");
@@ -133,7 +133,7 @@ public async Task CanConfigureSerilogWithoutLevelsConfiguration()
[INF] TestInfo
[ERR] TestError
- """);
+ """, IgnoreLineEndingsComparer.Instance);
}
[Fact]
@@ -167,7 +167,7 @@ public async Task CanConfigureSerilogFromConfigurationWithDefaultLevel()
logOutput.Should().Be("""
[ERR] TestError
- """);
+ """, IgnoreLineEndingsComparer.Instance);
}
[Fact]
@@ -201,7 +201,7 @@ public async Task CanConfigureSerilogFromConfigurationWithShortKeyForDefaultLeve
logOutput.Should().Be("""
[ERR] TestError
- """);
+ """, IgnoreLineEndingsComparer.Instance);
}
[Fact]
@@ -236,7 +236,7 @@ public async Task CanConfigureSerilogFromConfigurationWithOnlyOverrides()
logOutput.Should().Be("""
[ERR] TestError
- """);
+ """, IgnoreLineEndingsComparer.Instance);
}
[Fact]
@@ -273,7 +273,7 @@ public async Task CanConfigureSerilogFromCodeWithDefaultLevel()
logOutput.Should().Be("""
[ERR] TestError
- """);
+ """, IgnoreLineEndingsComparer.Instance);
}
[Fact]
@@ -311,7 +311,7 @@ public async Task CanConfigureSerilogFromCodeWithOnlyOverrides()
logOutput.Should().Be("""
[ERR] TestError
- """);
+ """, IgnoreLineEndingsComparer.Instance);
}
[Fact]
diff --git a/src/Management/src/Endpoint/Actuators/Health/Contributors/FileSystem/NetworkShareWrapper.cs b/src/Management/src/Endpoint/Actuators/Health/Contributors/FileSystem/NetworkShareWrapper.cs
index a62227d27d..c39452957d 100644
--- a/src/Management/src/Endpoint/Actuators/Health/Contributors/FileSystem/NetworkShareWrapper.cs
+++ b/src/Management/src/Endpoint/Actuators/Health/Contributors/FileSystem/NetworkShareWrapper.cs
@@ -2,7 +2,6 @@
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information.
-using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
namespace Steeltoe.Management.Endpoint.Actuators.Health.Contributors.FileSystem;
@@ -27,7 +26,6 @@ private NetworkShareWrapper(ulong freeBytesAvailable, ulong totalNumberOfBytes)
: null;
}
- [ExcludeFromCodeCoverage(Justification = "Workaround for https://github.com/coverlet-coverage/coverlet/issues/1762")]
private static partial class NativeMethods
{
[LibraryImport("kernel32.dll", EntryPoint = "GetDiskFreeSpaceExW", StringMarshalling = StringMarshalling.Utf16, SetLastError = true)]
diff --git a/src/Management/test/Endpoint.Test/Actuators/RouteMappings/AppTypes/ApiControllerTest.cs b/src/Management/test/Endpoint.Test/Actuators/RouteMappings/AppTypes/ApiControllerTest.cs
index 24036e793d..5d17186e73 100644
--- a/src/Management/test/Endpoint.Test/Actuators/RouteMappings/AppTypes/ApiControllerTest.cs
+++ b/src/Management/test/Endpoint.Test/Actuators/RouteMappings/AppTypes/ApiControllerTest.cs
@@ -91,7 +91,7 @@ public async Task Can_get_routes_for_simple_controller()
}
}
}
- """);
+ """, IgnoreLineEndingsComparer.Instance);
}
[Fact]
@@ -208,7 +208,7 @@ public async Task Can_get_routes_for_controller_with_parameters_and_annotations(
}
}
}
- """);
+ """, IgnoreLineEndingsComparer.Instance);
}
[Fact]
@@ -398,7 +398,7 @@ public async Task Can_get_routes_for_multiple_verbs_in_single_action_method()
}
}
}
- """);
+ """, IgnoreLineEndingsComparer.Instance);
}
[Fact]
@@ -461,7 +461,7 @@ public async Task Can_get_routes_for_any_verb_in_single_action_method()
}
}
}
- """);
+ """, IgnoreLineEndingsComparer.Instance);
}
[Fact]
@@ -536,7 +536,7 @@ public async Task Can_get_routes_using_WebHostBuilder()
}
}
}
- """);
+ """, IgnoreLineEndingsComparer.Instance);
}
[Fact]
@@ -613,6 +613,6 @@ public async Task Can_get_routes_using_HostBuilder()
}
}
}
- """);
+ """, IgnoreLineEndingsComparer.Instance);
}
}
diff --git a/src/Management/test/Endpoint.Test/Actuators/RouteMappings/AppTypes/MinimalApiTest.cs b/src/Management/test/Endpoint.Test/Actuators/RouteMappings/AppTypes/MinimalApiTest.cs
index f4c586a17f..774a7248e1 100644
--- a/src/Management/test/Endpoint.Test/Actuators/RouteMappings/AppTypes/MinimalApiTest.cs
+++ b/src/Management/test/Endpoint.Test/Actuators/RouteMappings/AppTypes/MinimalApiTest.cs
@@ -83,7 +83,7 @@ public async Task Can_get_routes_for_handler_method()
}
}
}
- """);
+ """, IgnoreLineEndingsComparer.Instance);
}
[Fact]
@@ -145,7 +145,7 @@ public async Task Can_get_routes_for_inline_lambda()
}
}
}
- """);
+ """, IgnoreLineEndingsComparer.Instance);
}
[Fact]
@@ -268,7 +268,7 @@ public async Task Can_get_routes_for_inline_lambda_with_parameters_and_annotatio
}
}
}
- """);
+ """, IgnoreLineEndingsComparer.Instance);
}
[Fact]
@@ -364,7 +364,7 @@ public async Task Can_get_routes_for_multiple_verbs_in_single_endpoint()
}
}
}
- """);
+ """, IgnoreLineEndingsComparer.Instance);
}
[Fact]
@@ -432,7 +432,7 @@ public async Task Can_get_routes_for_any_verb_in_single_endpoint()
}
}
}
- """);
+ """, IgnoreLineEndingsComparer.Instance);
}
[Fact]
@@ -523,7 +523,7 @@ public async Task Can_get_routes_for_separate_verbs_in_single_endpoint()
}
}
}
- """);
+ """, IgnoreLineEndingsComparer.Instance);
}
[Fact]
@@ -615,7 +615,7 @@ public async Task Can_get_routes_for_groups_using_same_handler_method()
}
}
}
- """);
+ """, IgnoreLineEndingsComparer.Instance);
}
[Fact]
@@ -720,7 +720,7 @@ public async Task Can_get_routes_for_groups_using_inline_lambdas()
}
}
}
- """);
+ """, IgnoreLineEndingsComparer.Instance);
}
[Fact]
@@ -781,7 +781,7 @@ public async Task Can_get_routes_using_WebHostBuilder()
}
}
}
- """);
+ """, IgnoreLineEndingsComparer.Instance);
}
[Fact]
@@ -845,7 +845,7 @@ public async Task Can_get_routes_using_HostBuilder()
}
}
}
- """);
+ """, IgnoreLineEndingsComparer.Instance);
}
private static string HandlePingRequest()
diff --git a/src/Management/test/Endpoint.Test/Actuators/RouteMappings/AppTypes/MvcControllerTest.cs b/src/Management/test/Endpoint.Test/Actuators/RouteMappings/AppTypes/MvcControllerTest.cs
index f261f0b125..f61f0f26ff 100644
--- a/src/Management/test/Endpoint.Test/Actuators/RouteMappings/AppTypes/MvcControllerTest.cs
+++ b/src/Management/test/Endpoint.Test/Actuators/RouteMappings/AppTypes/MvcControllerTest.cs
@@ -136,7 +136,7 @@ public async Task Can_get_routes_for_simple_controller()
}
}
}
- """);
+ """, IgnoreLineEndingsComparer.Instance);
}
[Fact]
@@ -300,7 +300,7 @@ public async Task Can_get_routes_for_controller_with_parameters_and_annotations(
}
}
}
- """);
+ """, IgnoreLineEndingsComparer.Instance);
}
[Fact]
@@ -432,7 +432,7 @@ public async Task Can_get_routes_for_multiple_verbs_in_single_action_method()
}
}
}
- """);
+ """, IgnoreLineEndingsComparer.Instance);
}
[Fact]
@@ -511,7 +511,7 @@ public async Task Can_get_routes_for_any_verb_in_single_action_method()
}
}
}
- """);
+ """, IgnoreLineEndingsComparer.Instance);
}
[Fact]
@@ -630,7 +630,7 @@ public async Task Can_get_routes_using_WebHostBuilder()
}
}
}
- """);
+ """, IgnoreLineEndingsComparer.Instance);
}
[Fact]
@@ -750,6 +750,6 @@ public async Task Can_get_routes_using_HostBuilder()
}
}
}
- """);
+ """, IgnoreLineEndingsComparer.Instance);
}
}
diff --git a/src/Management/test/Endpoint.Test/Actuators/RouteMappings/AppTypes/RazorPagesExternalAppTest.cs b/src/Management/test/Endpoint.Test/Actuators/RouteMappings/AppTypes/RazorPagesExternalAppTest.cs
index 83bbcdaa92..8b0f91b08a 100644
--- a/src/Management/test/Endpoint.Test/Actuators/RouteMappings/AppTypes/RazorPagesExternalAppTest.cs
+++ b/src/Management/test/Endpoint.Test/Actuators/RouteMappings/AppTypes/RazorPagesExternalAppTest.cs
@@ -3,14 +3,13 @@
// See the LICENSE file in the project root for more information.
using System.Net;
-using Microsoft.AspNetCore.Mvc.Testing;
-using Steeltoe.Management.Endpoint.RazorPagesTestWebApp.Pages;
+using Steeltoe.Common.TestResources;
namespace Steeltoe.Management.Endpoint.Test.Actuators.RouteMappings.AppTypes;
-public sealed class RazorPagesExternalAppTest(WebApplicationFactory factory) : IClassFixture>
+public sealed class RazorPagesExternalAppTest(RazorPagesWebApplicationFactory factory) : IClassFixture
{
- private readonly WebApplicationFactory _factory = factory;
+ private readonly RazorPagesWebApplicationFactory _factory = factory;
[Fact]
public async Task Can_get_routes_for_razor_pages()
@@ -272,6 +271,6 @@ public async Task Can_get_routes_for_razor_pages()
}
}
}
- """);
+ """, IgnoreLineEndingsComparer.Instance);
}
}
diff --git a/src/Management/test/Endpoint.Test/Actuators/RouteMappings/RazorPagesWebApplicationFactory.cs b/src/Management/test/Endpoint.Test/Actuators/RouteMappings/RazorPagesWebApplicationFactory.cs
new file mode 100644
index 0000000000..322e07311b
--- /dev/null
+++ b/src/Management/test/Endpoint.Test/Actuators/RouteMappings/RazorPagesWebApplicationFactory.cs
@@ -0,0 +1,29 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Mvc.Testing;
+using Steeltoe.Management.Endpoint.RazorPagesTestWebApp.Pages;
+using Steeltoe.Management.Endpoint.Test.Actuators.RouteMappings.AppTypes;
+
+namespace Steeltoe.Management.Endpoint.Test.Actuators.RouteMappings;
+
+public sealed class RazorPagesWebApplicationFactory : WebApplicationFactory
+{
+ protected override void ConfigureWebHost(IWebHostBuilder builder)
+ {
+ string? testAssemblyName = typeof(RazorPagesExternalAppTest).Assembly.GetName().Name;
+ string? appAssemblyName = typeof(IndexModel).Assembly.GetName().Name;
+
+ string absoluteContentRoot = System.Environment.CurrentDirectory;
+ absoluteContentRoot = absoluteContentRoot.Replace($"/{testAssemblyName}/", $"/{appAssemblyName}/", StringComparison.Ordinal);
+ absoluteContentRoot = absoluteContentRoot.Replace($@"\{testAssemblyName}\", $@"\{appAssemblyName}\", StringComparison.Ordinal);
+
+ // Workaround for https://github.com/dotnet/aspnetcore/issues/55867.
+ builder.UseContentRoot(absoluteContentRoot);
+
+ // Workaround for https://github.com/dotnet/aspnetcore/issues/55867#issuecomment-3046941805.
+ builder.UseEnvironment("Production");
+ }
+}
diff --git a/src/Steeltoe.All.sln b/src/Steeltoe.All.sln
index 1e8a438ee2..61e38a2678 100644
--- a/src/Steeltoe.All.sln
+++ b/src/Steeltoe.All.sln
@@ -1,6 +1,6 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 18
-VisualStudioVersion = 18.0.11222.15 d18.0
+VisualStudioVersion = 18.0.11222.15
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Steeltoe.Common", "Common\src\Common\Steeltoe.Common.csproj", "{61812938-5132-4AB6-B48D-2DF4189B3E37}"
EndProject
@@ -29,7 +29,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_shared", "_shared", "{DC1B
..\.gitattributes = ..\.gitattributes
..\.gitignore = ..\.gitignore
..\cleanupcode.ps1 = ..\cleanupcode.ps1
- ..\coverlet.runsettings = ..\coverlet.runsettings
+ ..\coverage.config = ..\coverage.config
+ ..\coverage.sonar.config = ..\coverage.sonar.config
..\Directory.Build.targets = ..\Directory.Build.targets
..\nuget.config = ..\nuget.config
..\PackageReadme.md = ..\PackageReadme.md
diff --git a/src/testenvironments.json b/src/testenvironments.json
index 539ead6b04..ebd64f1380 100644
--- a/src/testenvironments.json
+++ b/src/testenvironments.json
@@ -1,10 +1,15 @@
{
- "version": "1",
- "environments": [
- {
- "name": "Ubuntu",
- "type": "wsl",
- "wslDistribution": "Ubuntu"
- }
- ]
+ "version": "1",
+ "environments": [
+ {
+ "name": "Ubuntu",
+ "type": "wsl",
+ "wslDistribution": "Ubuntu"
+ },
+ {
+ "name": "Ubuntu-22.04",
+ "type": "wsl",
+ "wslDistribution": "Ubuntu-22.04"
+ }
+ ]
}
diff --git a/versions.props b/versions.props
index 20d9d10375..160c46d1b1 100644
--- a/versions.props
+++ b/versions.props
@@ -6,10 +6,11 @@
-->
9.0.*
- 6.0.*
7.2.*
3.54.*
4.14.*
+ 18.3.0-preview.25611.1
+ 2.1.0-preview.25611.7
6.1.*
7.0.*
3.5.*
@@ -26,9 +27,7 @@
2.0.*
8.14.*
4.9.*
- 18.0.*
3.2.*
- 3.1.*