diff --git a/.github/workflows/pipelines.yml b/.github/workflows/pipelines.yml index ae33294..fefb5a7 100644 --- a/.github/workflows/pipelines.yml +++ b/.github/workflows/pipelines.yml @@ -18,6 +18,9 @@ on: - Debug - Release +permissions: + contents: read + jobs: build: name: 🛠️ Build @@ -146,6 +149,8 @@ jobs: name: call-codeql needs: [build,test] uses: codebeltnet/jobs-codeql/.github/workflows/default.yml@v1 + permissions: + security-events: write deploy: if: github.event_name != 'pull_request' @@ -154,6 +159,9 @@ jobs: timeout-minutes: 15 needs: [build, pack, test, sonarcloud, codecov, codeql] environment: Production + permissions: + contents: write + packages: write steps: - uses: codebeltnet/nuget-push@v1 with: diff --git a/Directory.Build.props b/Directory.Build.props index 85a53c4..5be2bb7 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -34,6 +34,9 @@ true true $(MSBuildThisFileDirectory)xunit.snk + true + latest + Recommended 7035,CA2260 diff --git a/src/Codebelt.Extensions.Xunit.App/Codebelt.Extensions.Xunit.App.csproj b/src/Codebelt.Extensions.Xunit.App/Codebelt.Extensions.Xunit.App.csproj index f09b6e9..ffdf4ed 100644 --- a/src/Codebelt.Extensions.Xunit.App/Codebelt.Extensions.Xunit.App.csproj +++ b/src/Codebelt.Extensions.Xunit.App/Codebelt.Extensions.Xunit.App.csproj @@ -9,6 +9,7 @@ false false Provides a convenient set of default API additions for building .NET test projects based on xUnit. + NU5128 diff --git a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/GlobalSuppressions.cs b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/GlobalSuppressions.cs index d969af7..72b8b95 100644 --- a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/GlobalSuppressions.cs +++ b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/GlobalSuppressions.cs @@ -9,3 +9,4 @@ [assembly: SuppressMessage("Blocker Code Smell", "S3427:Method overloads with default parameter values should not overlap", Justification = "Avoid bumping major version by providing an extra overloaded member as optional argument.", Scope = "member", Target = "~M:Codebelt.Extensions.Xunit.Hosting.AspNetCore.WebHostTestFactory.CreateWithHostBuilderContext(System.Action{Microsoft.Extensions.Hosting.HostBuilderContext,Microsoft.Extensions.DependencyInjection.IServiceCollection},System.Action{Microsoft.Extensions.Hosting.HostBuilderContext,Microsoft.AspNetCore.Builder.IApplicationBuilder},System.Action{Microsoft.Extensions.Hosting.IHostBuilder},Codebelt.Extensions.Xunit.Hosting.AspNetCore.IAspNetCoreHostFixture)~Codebelt.Extensions.Xunit.Hosting.AspNetCore.IWebHostTest")] [assembly: SuppressMessage("Blocker Code Smell", "S3427:Method overloads with default parameter values should not overlap", Justification = "Avoid bumping major version by providing an extra overloaded member as optional argument.", Scope = "member", Target = "~M:Codebelt.Extensions.Xunit.Hosting.AspNetCore.WebHostTestFactory.RunAsync(System.Action{Microsoft.Extensions.DependencyInjection.IServiceCollection},System.Action{Microsoft.AspNetCore.Builder.IApplicationBuilder},System.Action{Microsoft.Extensions.Hosting.IHostBuilder},System.Func{System.Net.Http.HttpClient,System.Threading.Tasks.Task{System.Net.Http.HttpResponseMessage}},Codebelt.Extensions.Xunit.Hosting.AspNetCore.IAspNetCoreHostFixture)~System.Threading.Tasks.Task{System.Net.Http.HttpResponseMessage}")] [assembly: SuppressMessage("Blocker Code Smell", "S3427:Method overloads with default parameter values should not overlap", Justification = "Avoid bumping major version by providing an extra overloaded member as optional argument.", Scope = "member", Target = "~M:Codebelt.Extensions.Xunit.Hosting.AspNetCore.WebHostTestFactory.RunWithHostBuilderContextAsync(System.Action{Microsoft.Extensions.Hosting.HostBuilderContext,Microsoft.Extensions.DependencyInjection.IServiceCollection},System.Action{Microsoft.Extensions.Hosting.HostBuilderContext,Microsoft.AspNetCore.Builder.IApplicationBuilder},System.Action{Microsoft.Extensions.Hosting.IHostBuilder},System.Func{System.Net.Http.HttpClient,System.Threading.Tasks.Task{System.Net.Http.HttpResponseMessage}},Codebelt.Extensions.Xunit.Hosting.AspNetCore.IAspNetCoreHostFixture)~System.Threading.Tasks.Task{System.Net.Http.HttpResponseMessage}")] +[assembly: SuppressMessage("Performance", "CA1859:Use concrete types when possible for improved performance", Justification = "Nitpick.", Scope = "member", Target = "~M:Codebelt.Extensions.Xunit.Hosting.AspNetCore.Http.FakeHttpContextAccessor.MakeGreeting(System.String)~System.IO.Stream")] diff --git a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/Http/FakeHttpContextAccessor.cs b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/Http/FakeHttpContextAccessor.cs index 9ca0c80..a6c7cb1 100644 --- a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/Http/FakeHttpContextAccessor.cs +++ b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/Http/FakeHttpContextAccessor.cs @@ -31,7 +31,7 @@ public FakeHttpContextAccessor(IServiceScopeFactory factory = null) HttpContext = context; } - private Stream MakeGreeting(string greeting) + private static Stream MakeGreeting(string greeting) { Stream interim = null; Stream result = null; diff --git a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/Http/Features/FakeHttpResponseFeature.cs b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/Http/Features/FakeHttpResponseFeature.cs index 41309a4..721e8b1 100644 --- a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/Http/Features/FakeHttpResponseFeature.cs +++ b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/Http/Features/FakeHttpResponseFeature.cs @@ -23,7 +23,7 @@ public FakeHttpResponseFeature() } /// - /// Registers a callback to be invoked just before the response starts. This is the last chance to modify the , , or . + /// Registers a callback to be invoked just before the response starts. This is the last chance to modify the , , or . /// /// The callback to invoke when starting the response. /// The state to pass into the callback. @@ -35,8 +35,8 @@ public override void OnStarting(Func callback, object state) } /// - /// Indicates if the response has started. If true, the , - /// , and are now immutable, and + /// Indicates if the response has started. If true, the , + /// , and are now immutable, and /// OnStarting should no longer be called. /// /// true if this instance has started; otherwise, false. diff --git a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/HttpClientExtensions.cs b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/HttpClientExtensions.cs index a112465..888561c 100644 --- a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/HttpClientExtensions.cs +++ b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/HttpClientExtensions.cs @@ -21,7 +21,7 @@ public static class HttpClientExtensions /// Designed to be used in conjunction with and . public static async Task ToHttpResponseMessageAsync(this HttpClient client, Func> responseFactory = null) { - if (client == null) { throw new ArgumentNullException(nameof(client)); } + ArgumentNullException.ThrowIfNull(client); responseFactory ??= c => c.GetAsync("/"); return await responseFactory(client).ConfigureAwait(false); } diff --git a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/ManagedWebHostFixture.cs b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/ManagedWebHostFixture.cs index 05cb73c..0c9f0cb 100644 --- a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/ManagedWebHostFixture.cs +++ b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/ManagedWebHostFixture.cs @@ -38,7 +38,7 @@ public ManagedWebHostFixture() /// public override void ConfigureHost(Test hostTest) { - if (hostTest == null) { throw new ArgumentNullException(nameof(hostTest)); } + ArgumentNullException.ThrowIfNull(hostTest); if (!HasTypes(hostTest.GetType(), typeof(WebHostTest<>))) { throw new ArgumentOutOfRangeException(nameof(hostTest), typeof(WebHostTest<>), $"{nameof(hostTest)} is not assignable from WebHostTest."); } var hb = new HostBuilder() diff --git a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/ManagedWebMinimalHostFixture.cs b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/ManagedWebMinimalHostFixture.cs index 663d084..2f1b1e7 100644 --- a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/ManagedWebMinimalHostFixture.cs +++ b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/ManagedWebMinimalHostFixture.cs @@ -34,7 +34,7 @@ public ManagedWebMinimalHostFixture() /// public override void ConfigureHost(Test hostTest) { - if (hostTest == null) { throw new ArgumentNullException(nameof(hostTest)); } + ArgumentNullException.ThrowIfNull(hostTest); if (!HasTypes(hostTest.GetType(), typeof(MinimalWebHostTest<>))) { throw new ArgumentOutOfRangeException(nameof(hostTest), typeof(MinimalWebHostTest<>), $"{nameof(hostTest)} is not assignable from MinimalWebHostTest."); } var hb = WebApplication.CreateBuilder(new WebApplicationOptions() diff --git a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/MinimalWebHostTest.cs b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/MinimalWebHostTest.cs index 71668f2..7619643 100644 --- a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/MinimalWebHostTest.cs +++ b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/MinimalWebHostTest.cs @@ -38,7 +38,7 @@ protected MinimalWebHostTest(T hostFixture, ITestOutputHelper output = null, Typ /// protected MinimalWebHostTest(bool skipHostFixtureInitialization, T hostFixture, ITestOutputHelper output = null, Type callerType = null) : base(output, callerType) { - if (hostFixture == null) { throw new ArgumentNullException(nameof(hostFixture)); } + ArgumentNullException.ThrowIfNull(hostFixture); if (skipHostFixtureInitialization) { return; } if (!hostFixture.HasValidState()) { diff --git a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/WebHostTest.cs b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/WebHostTest.cs index 221fce0..c5e2a1a 100644 --- a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/WebHostTest.cs +++ b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/WebHostTest.cs @@ -32,7 +32,7 @@ protected WebHostTest(T hostFixture, ITestOutputHelper output = null, Type calle /// The of caller that ends up invoking this instance. protected WebHostTest(bool skipHostFixtureInitialization, T hostFixture, ITestOutputHelper output = null, Type callerType = null) : base(skipHostFixtureInitialization, hostFixture, output, callerType) { - if (hostFixture == null) { throw new ArgumentNullException(nameof(hostFixture)); } + ArgumentNullException.ThrowIfNull(hostFixture); if (skipHostFixtureInitialization) { return; } if (!hostFixture.HasValidState()) { diff --git a/src/Codebelt.Extensions.Xunit.Hosting/GlobalSuppressions.cs b/src/Codebelt.Extensions.Xunit.Hosting/GlobalSuppressions.cs index f899e98..c2de754 100644 --- a/src/Codebelt.Extensions.Xunit.Hosting/GlobalSuppressions.cs +++ b/src/Codebelt.Extensions.Xunit.Hosting/GlobalSuppressions.cs @@ -9,3 +9,11 @@ [assembly: SuppressMessage("Major Code Smell", "S3971:\"GC.SuppressFinalize\" should not be called", Justification = "False-Positive due to IAsyncDisposable living side-by-side with IDisposable.", Scope = "member", Target = "~M:Codebelt.Extensions.Xunit.Hosting.HostFixture.DisposeAsync~System.Threading.Tasks.ValueTask")] [assembly: SuppressMessage("Blocker Code Smell", "S3427:Method overloads with default parameter values should not overlap", Justification = "Avoid bumping major version by providing an extra overloaded member as optional argument.", Scope = "member", Target = "~M:Codebelt.Extensions.Xunit.Hosting.GenericHostTestFactory.Create(System.Action{Microsoft.Extensions.DependencyInjection.IServiceCollection},System.Action{Microsoft.Extensions.Hosting.IHostBuilder},Codebelt.Extensions.Xunit.Hosting.IHostFixture)~Codebelt.Extensions.Xunit.Hosting.IGenericHostTest")] [assembly: SuppressMessage("Blocker Code Smell", "S3427:Method overloads with default parameter values should not overlap", Justification = "Avoid bumping major version by providing an extra overloaded member as optional argument.", Scope = "member", Target = "~M:Codebelt.Extensions.Xunit.Hosting.GenericHostTestFactory.CreateWithHostBuilderContext(System.Action{Microsoft.Extensions.Hosting.HostBuilderContext,Microsoft.Extensions.DependencyInjection.IServiceCollection},System.Action{Microsoft.Extensions.Hosting.IHostBuilder},Codebelt.Extensions.Xunit.Hosting.IHostFixture)~Codebelt.Extensions.Xunit.Hosting.IGenericHostTest")] +[assembly: SuppressMessage("Maintainability", "CA1510:Use ArgumentNullException throw helper", Justification = "Wont fix. Multi-TFMs. Only supported with >= .NET 7.", Scope = "member", Target = "~M:Codebelt.Extensions.Xunit.Hosting.HostTest`1.#ctor(System.Boolean,`0,Xunit.Abstractions.ITestOutputHelper,System.Type)")] +[assembly: SuppressMessage("Maintainability", "CA1510:Use ArgumentNullException throw helper", Justification = "Wont fix. Multi-TFMs. Only supported with >= .NET 7.", Scope = "member", Target = "~M:Codebelt.Extensions.Xunit.Hosting.LoggerExtensions.GetTestStore(Microsoft.Extensions.Logging.ILogger,System.String)~Codebelt.Extensions.Xunit.ITestStore{Codebelt.Extensions.Xunit.Hosting.XunitTestLoggerEntry}")] +[assembly: SuppressMessage("Maintainability", "CA1510:Use ArgumentNullException throw helper", Justification = "Wont fix. Multi-TFMs. Only supported with >= .NET 7.", Scope = "member", Target = "~M:Codebelt.Extensions.Xunit.Hosting.ManagedHostFixture.ConfigureHost(Codebelt.Extensions.Xunit.Test)")] +[assembly: SuppressMessage("Maintainability", "CA1510:Use ArgumentNullException throw helper", Justification = "Wont fix. Multi-TFMs. Only supported with >= .NET 7.", Scope = "member", Target = "~M:Codebelt.Extensions.Xunit.Hosting.ManagedMinimalHostFixture.ConfigureHost(Codebelt.Extensions.Xunit.Test)")] +[assembly: SuppressMessage("Maintainability", "CA1510:Use ArgumentNullException throw helper", Justification = "Wont fix. Multi-TFMs. Only supported with >= .NET 7.", Scope = "member", Target = "~M:Codebelt.Extensions.Xunit.Hosting.MinimalHostTest`1.#ctor(System.Boolean,`0,Xunit.Abstractions.ITestOutputHelper,System.Type)")] +[assembly: SuppressMessage("Maintainability", "CA1510:Use ArgumentNullException throw helper", Justification = "Wont fix. Multi-TFMs. Only supported with >= .NET 7.", Scope = "member", Target = "~M:Codebelt.Extensions.Xunit.Hosting.ServiceCollectionExtensions.AddXunitTestLogging(Microsoft.Extensions.DependencyInjection.IServiceCollection,Microsoft.Extensions.Logging.LogLevel)~Microsoft.Extensions.DependencyInjection.IServiceCollection")] +[assembly: SuppressMessage("Maintainability", "CA1510:Use ArgumentNullException throw helper", Justification = "Wont fix. Multi-TFMs. Only supported with >= .NET 7.", Scope = "member", Target = "~M:Codebelt.Extensions.Xunit.Hosting.ServiceCollectionExtensions.AddXunitTestLogging(Microsoft.Extensions.DependencyInjection.IServiceCollection,Xunit.Abstractions.ITestOutputHelper,Microsoft.Extensions.Logging.LogLevel)~Microsoft.Extensions.DependencyInjection.IServiceCollection")] +[assembly: SuppressMessage("Maintainability", "CA1510:Use ArgumentNullException throw helper", Justification = "Wont fix. Multi-TFMs. Only supported with >= .NET 7.", Scope = "member", Target = "~M:Codebelt.Extensions.Xunit.Hosting.ServiceCollectionExtensions.AddXunitTestLoggingOutputHelperAccessor``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)~Microsoft.Extensions.DependencyInjection.IServiceCollection")] diff --git a/src/Codebelt.Extensions.Xunit/DelimitedStringOptions.cs b/src/Codebelt.Extensions.Xunit/DelimitedStringOptions.cs index 2cff67b..e918c49 100644 --- a/src/Codebelt.Extensions.Xunit/DelimitedStringOptions.cs +++ b/src/Codebelt.Extensions.Xunit/DelimitedStringOptions.cs @@ -2,7 +2,7 @@ namespace Codebelt.Extensions.Xunit { - internal class DelimitedStringOptions + internal sealed class DelimitedStringOptions { internal DelimitedStringOptions() { diff --git a/src/Codebelt.Extensions.Xunit/GlobalSuppressions.cs b/src/Codebelt.Extensions.Xunit/GlobalSuppressions.cs index 8023644..83d5071 100644 --- a/src/Codebelt.Extensions.Xunit/GlobalSuppressions.cs +++ b/src/Codebelt.Extensions.Xunit/GlobalSuppressions.cs @@ -7,3 +7,6 @@ [assembly: SuppressMessage("Major Code Smell", "S3881:\"IDisposable\" should be implemented correctly", Justification = "This is a base class implementation of the IDisposable interface tailored to avoid wrong implementations.", Scope = "type", Target = "~T:Codebelt.Extensions.Xunit.Test")] [assembly: SuppressMessage("Major Code Smell", "S3971:\"GC.SuppressFinalize\" should not be called", Justification = "False-Positive due to IAsyncDisposable living side-by-side with IDisposable.", Scope = "member", Target = "~M:Codebelt.Extensions.Xunit.Test.DisposeAsync~System.Threading.Tasks.ValueTask")] +[assembly: SuppressMessage("Maintainability", "CA1510:Use ArgumentNullException throw helper", Justification = "Wont fix. Multi-TFMs. Only supported with >= .NET 7.", Scope = "member", Target = "~M:Codebelt.Extensions.Xunit.DelimitedString.Create``1(System.Collections.Generic.IEnumerable{``0},System.Action{Codebelt.Extensions.Xunit.DelimitedStringOptions{``0}})~System.String")] +[assembly: SuppressMessage("Maintainability", "CA1510:Use ArgumentNullException throw helper", Justification = "Wont fix. Multi-TFMs. Only supported with >= .NET 7.", Scope = "member", Target = "~M:Codebelt.Extensions.Xunit.TestOutputHelperExtensions.WriteLines(Xunit.Abstractions.ITestOutputHelper,System.Object[])")] +[assembly: SuppressMessage("Maintainability", "CA1510:Use ArgumentNullException throw helper", Justification = "Wont fix. Multi-TFMs. Only supported with >= .NET 7.", Scope = "member", Target = "~M:Codebelt.Extensions.Xunit.TestOutputHelperExtensions.WriteLines``1(Xunit.Abstractions.ITestOutputHelper,System.Collections.Generic.IEnumerable{``0})")]