diff --git a/src/Particular.LicensingComponent.UnitTests/NUnitSettings.cs b/src/Particular.LicensingComponent.UnitTests/NUnitSettings.cs
new file mode 100644
index 0000000000..8b76b23ac7
--- /dev/null
+++ b/src/Particular.LicensingComponent.UnitTests/NUnitSettings.cs
@@ -0,0 +1,5 @@
+using NUnit.Framework;
+
+[assembly: FixtureLifeCycle(LifeCycle.InstancePerTestCase)]
+[assembly: Parallelizable(ParallelScope.All)]
+[assembly: LevelOfParallelism(4)]
diff --git a/src/ServiceControl.AcceptanceTesting/NServiceBusAcceptanceTest.cs b/src/ServiceControl.AcceptanceTesting/NServiceBusAcceptanceTest.cs
index 79cda757ca..b510e326ec 100644
--- a/src/ServiceControl.AcceptanceTesting/NServiceBusAcceptanceTest.cs
+++ b/src/ServiceControl.AcceptanceTesting/NServiceBusAcceptanceTest.cs
@@ -5,7 +5,6 @@
using System.Threading;
using NServiceBus.AcceptanceTesting;
using NServiceBus.AcceptanceTesting.Customization;
- using NServiceBus.Logging;
using NUnit.Framework;
using NUnit.Framework.Internal;
diff --git a/src/ServiceControl.AcceptanceTests.RavenDB/AcceptanceTestStorageConfiguration.cs b/src/ServiceControl.AcceptanceTests.RavenDB/AcceptanceTestStorageConfiguration.cs
index b95d834b29..e480fe43cc 100644
--- a/src/ServiceControl.AcceptanceTests.RavenDB/AcceptanceTestStorageConfiguration.cs
+++ b/src/ServiceControl.AcceptanceTests.RavenDB/AcceptanceTestStorageConfiguration.cs
@@ -1,38 +1,52 @@
-namespace ServiceControl.AcceptanceTests
+namespace ServiceControl.AcceptanceTests.RavenDB;
+
+using System;
+using System.Reactive.Disposables;
+using System.Threading;
+using System.Threading.Tasks;
+using ServiceBus.Management.Infrastructure.Settings;
+using ServiceControl.Persistence.Tests;
+using ServiceControl.RavenDB;
+
+public class AcceptanceTestStorageConfiguration
{
- using System;
- using System.Threading.Tasks;
- using Persistence.Tests;
- using ServiceBus.Management.Infrastructure.Settings;
- using ServiceControl.RavenDB;
+ public string PersistenceType { get; } = "RavenDB";
+
- public class AcceptanceTestStorageConfiguration
+ public async Task CustomizeSettings(Settings settings)
{
- public string PersistenceType { get; } = "RavenDB";
+ databaseName = Guid.NewGuid().ToString("n");
+ databaseInstance = await SharedEmbeddedServer.GetInstance();
- public async Task CustomizeSettings(Settings settings)
+ settings.PersisterSpecificSettings = new RavenPersisterSettings
{
- databaseName = Guid.NewGuid().ToString("n");
- databaseInstance = await SharedEmbeddedServer.GetInstance();
-
- settings.PersisterSpecificSettings = new RavenPersisterSettings
- {
- ErrorRetentionPeriod = TimeSpan.FromDays(10),
- ConnectionString = databaseInstance.ServerUrl,
- DatabaseName = databaseName
- };
- }
+ ErrorRetentionPeriod = TimeSpan.FromDays(10),
+ ConnectionString = databaseInstance.ServerUrl,
+ DatabaseName = databaseName
+ };
+ }
- public async Task Cleanup()
+ public async Task Cleanup()
+ {
+ if (databaseInstance == null)
{
- if (databaseInstance == null)
- {
- return;
- }
- await databaseInstance.DeleteDatabase(databaseName);
+ return;
}
+ using var _ = await UseDatabaseLifecycleLock();
+ await databaseInstance.DeleteDatabase(databaseName);
+ }
- EmbeddedDatabase databaseInstance;
- string databaseName;
+ ///
+ /// The shared server cannot perform database lifecycle operations in parallel, take this lock when you
+ /// need to do one of these operations in a test.
+ ///
+ public static async Task UseDatabaseLifecycleLock(CancellationToken cancellationToken = default)
+ {
+ await databaseLifecycleLock.WaitAsync(cancellationToken);
+ return Disposable.Create(() => databaseLifecycleLock.Release());
}
-}
+
+ static readonly SemaphoreSlim databaseLifecycleLock = new SemaphoreSlim(1, 1);
+ EmbeddedDatabase databaseInstance;
+ string databaseName;
+}
\ No newline at end of file
diff --git a/src/ServiceControl.AcceptanceTests.RavenDB/NUnitSettings.cs b/src/ServiceControl.AcceptanceTests.RavenDB/NUnitSettings.cs
new file mode 100644
index 0000000000..8b76b23ac7
--- /dev/null
+++ b/src/ServiceControl.AcceptanceTests.RavenDB/NUnitSettings.cs
@@ -0,0 +1,5 @@
+using NUnit.Framework;
+
+[assembly: FixtureLifeCycle(LifeCycle.InstancePerTestCase)]
+[assembly: Parallelizable(ParallelScope.All)]
+[assembly: LevelOfParallelism(4)]
diff --git a/src/ServiceControl.AcceptanceTests.RavenDB/Recoverability/MessageFailures/When_a_failed_message_is_retried.cs b/src/ServiceControl.AcceptanceTests.RavenDB/Recoverability/MessageFailures/When_a_failed_message_is_retried.cs
index 368e530ec3..95a133bd5b 100644
--- a/src/ServiceControl.AcceptanceTests.RavenDB/Recoverability/MessageFailures/When_a_failed_message_is_retried.cs
+++ b/src/ServiceControl.AcceptanceTests.RavenDB/Recoverability/MessageFailures/When_a_failed_message_is_retried.cs
@@ -17,7 +17,6 @@
using NUnit.Framework;
using ServiceControl.MessageFailures;
using ServiceControl.Recoverability;
- using TestSupport;
class When_a_failed_message_is_retried : AcceptanceTest
{
diff --git a/src/ServiceControl.AcceptanceTests.RavenDB/Recoverability/MessageFailures/When_a_message_fails_to_import.cs b/src/ServiceControl.AcceptanceTests.RavenDB/Recoverability/MessageFailures/When_a_message_fails_to_import.cs
index dbcae68e42..5780d4e716 100644
--- a/src/ServiceControl.AcceptanceTests.RavenDB/Recoverability/MessageFailures/When_a_message_fails_to_import.cs
+++ b/src/ServiceControl.AcceptanceTests.RavenDB/Recoverability/MessageFailures/When_a_message_fails_to_import.cs
@@ -18,6 +18,7 @@
using ServiceControl.MessageFailures;
using Conventions = NServiceBus.AcceptanceTesting.Customization.Conventions;
+ [NonParallelizable]
class When_a_message_fails_to_import : AcceptanceTest
{
[Test]
diff --git a/src/ServiceControl.AcceptanceTests.RavenDB/SetupFixture.cs b/src/ServiceControl.AcceptanceTests.RavenDB/SetupFixture.cs
new file mode 100644
index 0000000000..5a24a3417e
--- /dev/null
+++ b/src/ServiceControl.AcceptanceTests.RavenDB/SetupFixture.cs
@@ -0,0 +1,29 @@
+namespace ServiceControl.AcceptanceTests.RavenDB;
+
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Threading.Tasks;
+using NUnit.Framework;
+
+[SetUpFixture]
+public class SetupFixture
+{
+ [OneTimeSetUp]
+ public async Task Setup()
+ {
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ ServiceBus.Management.Infrastructure.Installers.EventSourceCreator.Create();
+
+ //There is a delay for this becoming true, tests will fall over if they interleave in the wrong way.
+ var cts = new CancellationTokenSource(TimeSpan.FromSeconds(60));
+ while (!EventLog.SourceExists(ServiceBus.Management.Infrastructure.Installers.EventSourceCreator.SourceName))
+ {
+ cts.Token.ThrowIfCancellationRequested();
+ await Task.Delay(500, CancellationToken.None);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ServiceControl.AcceptanceTests/Monitoring/InternalCustomChecks/When_a_critical_error_is_triggered.cs b/src/ServiceControl.AcceptanceTests/Monitoring/InternalCustomChecks/When_a_critical_error_is_triggered.cs
index 90e66ec00d..d9352118f9 100644
--- a/src/ServiceControl.AcceptanceTests/Monitoring/InternalCustomChecks/When_a_critical_error_is_triggered.cs
+++ b/src/ServiceControl.AcceptanceTests/Monitoring/InternalCustomChecks/When_a_critical_error_is_triggered.cs
@@ -12,6 +12,7 @@
using ServiceControl.Operations;
[TestFixture]
+ [NonParallelizable]
class When_a_critical_error_is_triggered : AcceptanceTest
{
[Test]
diff --git a/src/ServiceControl.AcceptanceTests/Security/Cors/When_cors_allows_any_origin.cs b/src/ServiceControl.AcceptanceTests/Security/Cors/When_cors_allows_any_origin.cs
index 1e06bafb7c..b6753128b2 100644
--- a/src/ServiceControl.AcceptanceTests/Security/Cors/When_cors_allows_any_origin.cs
+++ b/src/ServiceControl.AcceptanceTests/Security/Cors/When_cors_allows_any_origin.cs
@@ -12,6 +12,7 @@ namespace ServiceControl.AcceptanceTests.Security.Cors
/// When AllowAnyOrigin is true (default for backwards compatibility), requests from any origin should be allowed.
/// The Access-Control-Allow-Origin header should be "*".
///
+ [NonParallelizable]
class When_cors_allows_any_origin : AcceptanceTest
{
CorsTestConfiguration configuration;
diff --git a/src/ServiceControl.AcceptanceTests/Security/Cors/When_cors_is_disabled.cs b/src/ServiceControl.AcceptanceTests/Security/Cors/When_cors_is_disabled.cs
index c3d1f0cd9d..d8685bec1d 100644
--- a/src/ServiceControl.AcceptanceTests/Security/Cors/When_cors_is_disabled.cs
+++ b/src/ServiceControl.AcceptanceTests/Security/Cors/When_cors_is_disabled.cs
@@ -12,6 +12,7 @@ namespace ServiceControl.AcceptanceTests.Security.Cors
/// When AllowAnyOrigin is false and no AllowedOrigins are configured, CORS is effectively disabled.
/// No Access-Control-Allow-Origin header should be returned for any origin.
///
+ [NonParallelizable]
class When_cors_is_disabled : AcceptanceTest
{
CorsTestConfiguration configuration;
diff --git a/src/ServiceControl.AcceptanceTests/Security/Cors/When_request_from_allowed_origin.cs b/src/ServiceControl.AcceptanceTests/Security/Cors/When_request_from_allowed_origin.cs
index 6332d7db27..717d1a672a 100644
--- a/src/ServiceControl.AcceptanceTests/Security/Cors/When_request_from_allowed_origin.cs
+++ b/src/ServiceControl.AcceptanceTests/Security/Cors/When_request_from_allowed_origin.cs
@@ -12,6 +12,7 @@ namespace ServiceControl.AcceptanceTests.Security.Cors
/// When a request comes from an origin that is in the AllowedOrigins list,
/// the response should include the Access-Control-Allow-Origin header with that specific origin.
///
+ [NonParallelizable]
class When_request_from_allowed_origin : AcceptanceTest
{
CorsTestConfiguration configuration;
diff --git a/src/ServiceControl.AcceptanceTests/Security/Cors/When_request_from_disallowed_origin.cs b/src/ServiceControl.AcceptanceTests/Security/Cors/When_request_from_disallowed_origin.cs
index a5f9a99c65..f8d46dba92 100644
--- a/src/ServiceControl.AcceptanceTests/Security/Cors/When_request_from_disallowed_origin.cs
+++ b/src/ServiceControl.AcceptanceTests/Security/Cors/When_request_from_disallowed_origin.cs
@@ -12,6 +12,7 @@ namespace ServiceControl.AcceptanceTests.Security.Cors
/// When a request comes from an origin that is NOT in the AllowedOrigins list,
/// the response should NOT include an Access-Control-Allow-Origin header that matches the request origin.
///
+ [NonParallelizable]
class When_request_from_disallowed_origin : AcceptanceTest
{
CorsTestConfiguration configuration;
diff --git a/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_forwarded_headers_are_disabled.cs b/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_forwarded_headers_are_disabled.cs
index a407c1b591..2d80e9e3d6 100644
--- a/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_forwarded_headers_are_disabled.cs
+++ b/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_forwarded_headers_are_disabled.cs
@@ -10,6 +10,7 @@ namespace ServiceControl.AcceptanceTests.Security.ForwardedHeaders
/// Forwarded Headers Disabled
/// When forwarded headers processing is disabled, headers should be ignored regardless of trust.
///
+ [NonParallelizable]
class When_forwarded_headers_are_disabled : AcceptanceTest
{
ForwardedHeadersTestConfiguration configuration;
diff --git a/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_forwarded_headers_are_sent.cs b/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_forwarded_headers_are_sent.cs
index 665b5a8cbd..4c365e3934 100644
--- a/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_forwarded_headers_are_sent.cs
+++ b/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_forwarded_headers_are_sent.cs
@@ -10,6 +10,7 @@ namespace ServiceControl.AcceptanceTests.Security.ForwardedHeaders
/// Default Behavior with Headers
/// When forwarded headers are sent and TrustAllProxies is true (default), headers should be applied.
///
+ [NonParallelizable]
class When_forwarded_headers_are_sent : AcceptanceTest
{
[Test]
diff --git a/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_known_networks_are_configured.cs b/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_known_networks_are_configured.cs
index f88f46296b..cce32f64a6 100644
--- a/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_known_networks_are_configured.cs
+++ b/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_known_networks_are_configured.cs
@@ -10,6 +10,7 @@ namespace ServiceControl.AcceptanceTests.Security.ForwardedHeaders
/// Known Networks (CIDR)
/// When KnownNetworks are configured and the caller IP falls within, headers should be applied.
///
+ [NonParallelizable]
class When_known_networks_are_configured : AcceptanceTest
{
ForwardedHeadersTestConfiguration configuration;
diff --git a/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_known_proxies_are_configured.cs b/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_known_proxies_are_configured.cs
index 741e69459f..2ca9df7e52 100644
--- a/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_known_proxies_are_configured.cs
+++ b/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_known_proxies_are_configured.cs
@@ -10,6 +10,7 @@ namespace ServiceControl.AcceptanceTests.Security.ForwardedHeaders
/// Known Proxies Only
/// When KnownProxies are configured and the caller IP matches, headers should be applied.
///
+ [NonParallelizable]
class When_known_proxies_are_configured : AcceptanceTest
{
ForwardedHeadersTestConfiguration configuration;
diff --git a/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_multiple_header_values_are_sent.cs b/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_multiple_header_values_are_sent.cs
index b1deffd508..fc25eb780b 100644
--- a/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_multiple_header_values_are_sent.cs
+++ b/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_multiple_header_values_are_sent.cs
@@ -11,6 +11,7 @@ namespace ServiceControl.AcceptanceTests.Security.ForwardedHeaders
/// When TrustAllProxies is true and headers contain multiple values (proxy chain),
/// the original (leftmost) values should be returned.
///
+ [NonParallelizable]
class When_multiple_header_values_are_sent : AcceptanceTest
{
[Test]
diff --git a/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_multiple_header_values_are_sent_with_known_proxies.cs b/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_multiple_header_values_are_sent_with_known_proxies.cs
index c8a6917737..ed211e1537 100644
--- a/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_multiple_header_values_are_sent_with_known_proxies.cs
+++ b/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_multiple_header_values_are_sent_with_known_proxies.cs
@@ -11,6 +11,7 @@ namespace ServiceControl.AcceptanceTests.Security.ForwardedHeaders
/// When TrustAllProxies=false (known proxies configured), ForwardLimit=1,
/// so only the rightmost values are processed.
///
+ [NonParallelizable]
class When_multiple_header_values_are_sent_with_known_proxies : AcceptanceTest
{
ForwardedHeadersTestConfiguration configuration;
diff --git a/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_only_proto_header_is_sent.cs b/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_only_proto_header_is_sent.cs
index 83b79819f3..6ba393a7f2 100644
--- a/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_only_proto_header_is_sent.cs
+++ b/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_only_proto_header_is_sent.cs
@@ -10,6 +10,7 @@ namespace ServiceControl.AcceptanceTests.Security.ForwardedHeaders
/// Partial Headers (Proto Only)
/// When only X-Forwarded-Proto is sent, only scheme should change.
///
+ [NonParallelizable]
class When_only_proto_header_is_sent : AcceptanceTest
{
[Test]
diff --git a/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_proxy_chain_headers_are_sent.cs b/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_proxy_chain_headers_are_sent.cs
index dd3dd32dd1..57994013b9 100644
--- a/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_proxy_chain_headers_are_sent.cs
+++ b/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_proxy_chain_headers_are_sent.cs
@@ -11,6 +11,7 @@ namespace ServiceControl.AcceptanceTests.Security.ForwardedHeaders
/// When TrustAllProxies is true and X-Forwarded-For contains multiple IPs (proxy chain),
/// the original client IP (first in the chain) should be returned.
///
+ [NonParallelizable]
class When_proxy_chain_headers_are_sent : AcceptanceTest
{
[Test]
diff --git a/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_proxy_chain_headers_are_sent_with_known_proxies.cs b/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_proxy_chain_headers_are_sent_with_known_proxies.cs
index 81c7bc20c9..2b57ac5541 100644
--- a/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_proxy_chain_headers_are_sent_with_known_proxies.cs
+++ b/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_proxy_chain_headers_are_sent_with_known_proxies.cs
@@ -10,6 +10,7 @@ namespace ServiceControl.AcceptanceTests.Security.ForwardedHeaders
/// Proxy Chain with Known Proxies (ForwardLimit=1)
/// When TrustAllProxies=false (known proxies configured), ForwardLimit=1, so only the last proxy IP is processed.
///
+ [NonParallelizable]
class When_proxy_chain_headers_are_sent_with_known_proxies : AcceptanceTest
{
ForwardedHeadersTestConfiguration configuration;
diff --git a/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_request_has_no_forwarded_headers.cs b/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_request_has_no_forwarded_headers.cs
index 5c09add6cf..af6b387009 100644
--- a/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_request_has_no_forwarded_headers.cs
+++ b/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_request_has_no_forwarded_headers.cs
@@ -10,6 +10,7 @@ namespace ServiceControl.AcceptanceTests.Security.ForwardedHeaders
/// Direct Access (No Proxy)
/// When no forwarded headers are sent, the request values should remain unchanged.
///
+ [NonParallelizable]
class When_request_has_no_forwarded_headers : AcceptanceTest
{
[Test]
diff --git a/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_trust_all_proxies_is_explicitly_configured.cs b/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_trust_all_proxies_is_explicitly_configured.cs
index 25f4c3f31c..dfe220f9aa 100644
--- a/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_trust_all_proxies_is_explicitly_configured.cs
+++ b/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_trust_all_proxies_is_explicitly_configured.cs
@@ -11,6 +11,7 @@ namespace ServiceControl.AcceptanceTests.Security.ForwardedHeaders
/// When TrustAllProxies is explicitly configured via environment variable, headers should be applied.
/// This test verifies the WithTrustAllProxies() configuration method works correctly.
///
+ [NonParallelizable]
class When_trust_all_proxies_is_explicitly_configured : AcceptanceTest
{
ForwardedHeadersTestConfiguration configuration;
diff --git a/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_unknown_network_sends_headers.cs b/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_unknown_network_sends_headers.cs
index ba62f72a51..0fffa1cd84 100644
--- a/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_unknown_network_sends_headers.cs
+++ b/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_unknown_network_sends_headers.cs
@@ -10,6 +10,7 @@ namespace ServiceControl.AcceptanceTests.Security.ForwardedHeaders
/// Unknown Network Rejected
/// When KnownNetworks are configured but the caller IP does NOT fall within, headers should be ignored.
///
+ [NonParallelizable]
class When_unknown_network_sends_headers : AcceptanceTest
{
ForwardedHeadersTestConfiguration configuration;
diff --git a/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_unknown_proxy_sends_headers.cs b/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_unknown_proxy_sends_headers.cs
index 255d35ab18..d16e48fbcb 100644
--- a/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_unknown_proxy_sends_headers.cs
+++ b/src/ServiceControl.AcceptanceTests/Security/ForwardedHeaders/When_unknown_proxy_sends_headers.cs
@@ -10,6 +10,7 @@ namespace ServiceControl.AcceptanceTests.Security.ForwardedHeaders
/// Unknown Proxy Rejected
/// When KnownProxies are configured but the caller IP does NOT match, headers should be ignored.
///
+ [NonParallelizable]
class When_unknown_proxy_sends_headers : AcceptanceTest
{
ForwardedHeadersTestConfiguration configuration;
diff --git a/src/ServiceControl.AcceptanceTests/Security/Https/When_hsts_is_configured_in_development_mode.cs b/src/ServiceControl.AcceptanceTests/Security/Https/When_hsts_is_configured_in_development_mode.cs
index 692f431de4..10d4d36cab 100644
--- a/src/ServiceControl.AcceptanceTests/Security/Https/When_hsts_is_configured_in_development_mode.cs
+++ b/src/ServiceControl.AcceptanceTests/Security/Https/When_hsts_is_configured_in_development_mode.cs
@@ -13,6 +13,7 @@ namespace ServiceControl.AcceptanceTests.Security.Https
/// In acceptance tests (which run in Development mode), HSTS headers are not sent.
/// This test verifies that HSTS is correctly NOT applied in development mode.
///
+ [NonParallelizable]
class When_hsts_is_configured_in_development_mode : AcceptanceTest
{
HttpsTestConfiguration configuration;
diff --git a/src/ServiceControl.AcceptanceTests/Security/Https/When_https_redirect_is_disabled.cs b/src/ServiceControl.AcceptanceTests/Security/Https/When_https_redirect_is_disabled.cs
index 49af0e3879..f3f354d776 100644
--- a/src/ServiceControl.AcceptanceTests/Security/Https/When_https_redirect_is_disabled.cs
+++ b/src/ServiceControl.AcceptanceTests/Security/Https/When_https_redirect_is_disabled.cs
@@ -11,6 +11,7 @@ namespace ServiceControl.AcceptanceTests.Security.Https
/// HTTPS Redirect Disabled (Default)
/// When RedirectHttpToHttps is false (default), HTTP requests should not be redirected.
///
+ [NonParallelizable]
class When_https_redirect_is_disabled : AcceptanceTest
{
HttpsTestConfiguration configuration;
diff --git a/src/ServiceControl.AcceptanceTests/Security/Https/When_https_redirect_is_enabled.cs b/src/ServiceControl.AcceptanceTests/Security/Https/When_https_redirect_is_enabled.cs
index 81a0a81949..a314952797 100644
--- a/src/ServiceControl.AcceptanceTests/Security/Https/When_https_redirect_is_enabled.cs
+++ b/src/ServiceControl.AcceptanceTests/Security/Https/When_https_redirect_is_enabled.cs
@@ -11,6 +11,7 @@ namespace ServiceControl.AcceptanceTests.Security.Https
/// HTTPS Redirect Enabled
/// When RedirectHttpToHttps is true, HTTP requests should be redirected to HTTPS.
///
+ [NonParallelizable]
class When_https_redirect_is_enabled : AcceptanceTest
{
HttpsTestConfiguration configuration;
diff --git a/src/ServiceControl.AcceptanceTests/Security/OpenIdConnect/When_authentication_is_disabled.cs b/src/ServiceControl.AcceptanceTests/Security/OpenIdConnect/When_authentication_is_disabled.cs
index fcd8e90742..86a18eeb49 100644
--- a/src/ServiceControl.AcceptanceTests/Security/OpenIdConnect/When_authentication_is_disabled.cs
+++ b/src/ServiceControl.AcceptanceTests/Security/OpenIdConnect/When_authentication_is_disabled.cs
@@ -12,6 +12,7 @@ namespace ServiceControl.AcceptanceTests.Security.OpenIdConnect
/// When Authentication.Enabled is false (default), all API endpoints should be accessible
/// without authentication. Requests should not require Bearer tokens.
///
+ [NonParallelizable]
class When_authentication_is_disabled : AcceptanceTest
{
OpenIdConnectTestConfiguration configuration;
diff --git a/src/ServiceControl.AcceptanceTests/Security/OpenIdConnect/When_authentication_is_enabled.cs b/src/ServiceControl.AcceptanceTests/Security/OpenIdConnect/When_authentication_is_enabled.cs
index a52077657f..3795913478 100644
--- a/src/ServiceControl.AcceptanceTests/Security/OpenIdConnect/When_authentication_is_enabled.cs
+++ b/src/ServiceControl.AcceptanceTests/Security/OpenIdConnect/When_authentication_is_enabled.cs
@@ -17,6 +17,7 @@ namespace ServiceControl.AcceptanceTests.Security.OpenIdConnect
/// This test uses a mock OIDC server to provide discovery endpoints and signing keys,
/// allowing full testing of the JWT Bearer authentication flow.
///
+ [NonParallelizable]
class When_authentication_is_enabled : AcceptanceTest
{
OpenIdConnectTestConfiguration configuration;
diff --git a/src/ServiceControl.AcceptanceTests/Security/OpenIdConnect/When_my_routes_are_requested.cs b/src/ServiceControl.AcceptanceTests/Security/OpenIdConnect/When_my_routes_are_requested.cs
index d2fcb9ff6e..ef59c78693 100644
--- a/src/ServiceControl.AcceptanceTests/Security/OpenIdConnect/When_my_routes_are_requested.cs
+++ b/src/ServiceControl.AcceptanceTests/Security/OpenIdConnect/When_my_routes_are_requested.cs
@@ -17,6 +17,7 @@ namespace ServiceControl.AcceptanceTests.Security.OpenIdConnect;
/// It is the per-instance authorization contract ServicePulse consumes: it gates UI on routes it
/// already calls rather than on the server's internal permission vocabulary.
///
+[NonParallelizable]
class When_my_routes_are_requested : AcceptanceTest
{
OpenIdConnectTestConfiguration configuration;
diff --git a/src/ServiceControl.AcceptanceTests/Security/OpenIdConnect/When_service_pulse_authority_override_is_configured.cs b/src/ServiceControl.AcceptanceTests/Security/OpenIdConnect/When_service_pulse_authority_override_is_configured.cs
index 27d70d157f..4cf206372d 100644
--- a/src/ServiceControl.AcceptanceTests/Security/OpenIdConnect/When_service_pulse_authority_override_is_configured.cs
+++ b/src/ServiceControl.AcceptanceTests/Security/OpenIdConnect/When_service_pulse_authority_override_is_configured.cs
@@ -13,6 +13,7 @@ namespace ServiceControl.AcceptanceTests.Security.OpenIdConnect
/// endpoint should return the overridden authority for ServicePulse to use instead of the
/// main authority URL.
///
+ [NonParallelizable]
class When_service_pulse_authority_override_is_configured : AcceptanceTest
{
OpenIdConnectTestConfiguration configuration;
diff --git a/src/ServiceControl.AcceptanceTests/Security/OpenIdConnect/When_service_pulse_offline_access_scope_is_disabled.cs b/src/ServiceControl.AcceptanceTests/Security/OpenIdConnect/When_service_pulse_offline_access_scope_is_disabled.cs
index 60231ce655..610467e273 100644
--- a/src/ServiceControl.AcceptanceTests/Security/OpenIdConnect/When_service_pulse_offline_access_scope_is_disabled.cs
+++ b/src/ServiceControl.AcceptanceTests/Security/OpenIdConnect/When_service_pulse_offline_access_scope_is_disabled.cs
@@ -13,6 +13,7 @@ namespace ServiceControl.AcceptanceTests.Security.OpenIdConnect
/// string returned by the authentication configuration endpoint should omit offline_access,
/// so ServicePulse does not request a scope the identity provider disallows.
///
+ [NonParallelizable]
class When_service_pulse_offline_access_scope_is_disabled : AcceptanceTest
{
OpenIdConnectTestConfiguration configuration;
diff --git a/src/ServiceControl.AcceptanceTests/TestSupport/AcceptanceTest.cs b/src/ServiceControl.AcceptanceTests/TestSupport/AcceptanceTest.cs
index 8544456d11..30ad9075b1 100644
--- a/src/ServiceControl.AcceptanceTests/TestSupport/AcceptanceTest.cs
+++ b/src/ServiceControl.AcceptanceTests/TestSupport/AcceptanceTest.cs
@@ -14,6 +14,7 @@ namespace ServiceControl.AcceptanceTests
using NServiceBus.AcceptanceTesting;
using NServiceBus.AcceptanceTesting.Support;
using NUnit.Framework;
+ using RavenDB;
using ServiceBus.Management.Infrastructure.Settings;
using ServiceControl.AcceptanceTesting.InfrastructureConfig;
using TestSupport;
diff --git a/src/ServiceControl.AcceptanceTests/TestSupport/ServiceControlComponentBehavior.cs b/src/ServiceControl.AcceptanceTests/TestSupport/ServiceControlComponentBehavior.cs
index 5d4a8545d3..912db9e850 100644
--- a/src/ServiceControl.AcceptanceTests/TestSupport/ServiceControlComponentBehavior.cs
+++ b/src/ServiceControl.AcceptanceTests/TestSupport/ServiceControlComponentBehavior.cs
@@ -9,6 +9,7 @@ namespace ServiceControl.AcceptanceTests.TestSupport
using Microsoft.Extensions.Hosting;
using NServiceBus;
using NServiceBus.AcceptanceTesting.Support;
+ using RavenDB;
using ServiceBus.Management.Infrastructure.Settings;
class ServiceControlComponentBehavior : IComponentBehavior, IAcceptanceTestInfrastructureProvider
diff --git a/src/ServiceControl.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs b/src/ServiceControl.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs
index 736c842f2e..e3a5761b78 100644
--- a/src/ServiceControl.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs
+++ b/src/ServiceControl.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs
@@ -25,6 +25,8 @@
using NServiceBus.AcceptanceTesting.Support;
using Particular.ServiceControl;
using Particular.ServiceControl.Hosting;
+ using Persistence.Tests;
+ using RavenDB;
using RavenDB.Shared;
using ServiceBus.Management.Infrastructure.Settings;
using ServiceControl.Infrastructure;
@@ -47,9 +49,13 @@ public ServiceControlComponentRunner(ITransportIntegration transportToUse, Accep
public JsonSerializerOptions SerializerOptions => Infrastructure.WebApi.SerializerOptions.Default;
public IDomainEvents DomainEvents { get; private set; }
- public Task Initialize(RunDescriptor run) => InitializeServiceControl(run.ScenarioContext);
+ public async Task Initialize(RunDescriptor run)
+ {
+ using var _ = await AcceptanceTestStorageConfiguration.UseDatabaseLifecycleLock();
+ await InitializeServiceControlCore(run.ScenarioContext);
+ }
- async Task InitializeServiceControl(ScenarioContext context)
+ async Task InitializeServiceControlCore(ScenarioContext context)
{
var logPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
Directory.CreateDirectory(logPath);
diff --git a/src/ServiceControl.Audit.AcceptanceTests.RavenDB/AcceptanceTestStorageConfiguration.cs b/src/ServiceControl.Audit.AcceptanceTests.RavenDB/AcceptanceTestStorageConfiguration.cs
index de3882e6e8..f1aee9f300 100644
--- a/src/ServiceControl.Audit.AcceptanceTests.RavenDB/AcceptanceTestStorageConfiguration.cs
+++ b/src/ServiceControl.Audit.AcceptanceTests.RavenDB/AcceptanceTestStorageConfiguration.cs
@@ -2,7 +2,9 @@
{
using System;
using System.Collections.Generic;
+ using System.Threading;
using System.Threading.Tasks;
+ using Nito.Disposables;
using ServiceControl.Audit.Persistence.RavenDB;
using ServiceControl.Audit.Persistence.Tests;
using ServiceControl.RavenDB;
@@ -13,6 +15,7 @@ public class AcceptanceTestStorageConfiguration
EmbeddedDatabase databaseInstance;
string databaseName;
+ static readonly SemaphoreSlim databaseLifecycleLock = new SemaphoreSlim(1, 1);
public async Task> CustomizeSettings()
{
@@ -32,7 +35,18 @@ public async Task Cleanup()
{
return;
}
+ using var _ = await UseDatabaseLifecycleLock();
await databaseInstance.DeleteDatabase(databaseName);
}
+
+ ///
+ /// The shared server cannot perform database lifecycle operations in parallel, take this lock when you
+ /// need to do one of these operations in a test.
+ ///
+ public static async Task UseDatabaseLifecycleLock(CancellationToken cancellationToken = default)
+ {
+ await databaseLifecycleLock.WaitAsync(cancellationToken);
+ return Disposable.Create(() => databaseLifecycleLock.Release());
+ }
}
}
diff --git a/src/ServiceControl.Audit.AcceptanceTests.RavenDB/SetupFixture.cs b/src/ServiceControl.Audit.AcceptanceTests.RavenDB/SetupFixture.cs
new file mode 100644
index 0000000000..100af7975a
--- /dev/null
+++ b/src/ServiceControl.Audit.AcceptanceTests.RavenDB/SetupFixture.cs
@@ -0,0 +1,29 @@
+namespace ServiceControl.Audit.AcceptanceTests.RavenDB;
+
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Threading.Tasks;
+using NUnit.Framework;
+
+[SetUpFixture]
+public class SetupFixture
+{
+ [OneTimeSetUp]
+ public async Task Setup()
+ {
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ Infrastructure.EventSourceCreator.Create();
+
+ //There is a delay for this becoming true, tests will fall over if they interleave in the wrong way.
+ var cts = new CancellationTokenSource(TimeSpan.FromSeconds(60));
+ while (!EventLog.SourceExists(Infrastructure.EventSourceCreator.SourceName))
+ {
+ cts.Token.ThrowIfCancellationRequested();
+ await Task.Delay(500, CancellationToken.None);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ServiceControl.Audit.AcceptanceTests/AcceptanceTestStorageConfiguration.cs b/src/ServiceControl.Audit.AcceptanceTests/AcceptanceTestStorageConfiguration.cs
index 168a142f47..41f816339d 100644
--- a/src/ServiceControl.Audit.AcceptanceTests/AcceptanceTestStorageConfiguration.cs
+++ b/src/ServiceControl.Audit.AcceptanceTests/AcceptanceTestStorageConfiguration.cs
@@ -1,6 +1,8 @@
namespace ServiceControl.Audit.AcceptanceTests
{
+ using System;
using System.Collections.Generic;
+ using System.Threading;
using System.Threading.Tasks;
public class AcceptanceTestStorageConfiguration
@@ -10,5 +12,12 @@ public class AcceptanceTestStorageConfiguration
public Task> CustomizeSettings() => Task.FromResult>(new Dictionary());
public Task Cleanup() => Task.CompletedTask;
+
+ public static Task UseDatabaseLifecycleLock() => Task.FromResult(new EmptyDisposable());
+
+ class EmptyDisposable : IDisposable
+ {
+ public void Dispose() { }
+ }
}
-}
+}
\ No newline at end of file
diff --git a/src/ServiceControl.Audit.AcceptanceTests/NUnitSettings.cs b/src/ServiceControl.Audit.AcceptanceTests/NUnitSettings.cs
new file mode 100644
index 0000000000..8b76b23ac7
--- /dev/null
+++ b/src/ServiceControl.Audit.AcceptanceTests/NUnitSettings.cs
@@ -0,0 +1,5 @@
+using NUnit.Framework;
+
+[assembly: FixtureLifeCycle(LifeCycle.InstancePerTestCase)]
+[assembly: Parallelizable(ParallelScope.All)]
+[assembly: LevelOfParallelism(4)]
diff --git a/src/ServiceControl.Audit.AcceptanceTests/Security/Cors/When_cors_allows_any_origin.cs b/src/ServiceControl.Audit.AcceptanceTests/Security/Cors/When_cors_allows_any_origin.cs
index 3526c994aa..c936055f36 100644
--- a/src/ServiceControl.Audit.AcceptanceTests/Security/Cors/When_cors_allows_any_origin.cs
+++ b/src/ServiceControl.Audit.AcceptanceTests/Security/Cors/When_cors_allows_any_origin.cs
@@ -12,6 +12,7 @@ namespace ServiceControl.Audit.AcceptanceTests.Security.Cors
/// When AllowAnyOrigin is true (default for backwards compatibility), requests from any origin should be allowed.
/// The Access-Control-Allow-Origin header should be "*".
///
+ [NonParallelizable]
class When_cors_allows_any_origin : AcceptanceTest
{
CorsTestConfiguration configuration;
diff --git a/src/ServiceControl.Audit.AcceptanceTests/Security/Cors/When_cors_is_disabled.cs b/src/ServiceControl.Audit.AcceptanceTests/Security/Cors/When_cors_is_disabled.cs
index 0dbf96f7c2..4729678439 100644
--- a/src/ServiceControl.Audit.AcceptanceTests/Security/Cors/When_cors_is_disabled.cs
+++ b/src/ServiceControl.Audit.AcceptanceTests/Security/Cors/When_cors_is_disabled.cs
@@ -12,6 +12,7 @@ namespace ServiceControl.Audit.AcceptanceTests.Security.Cors
/// When AllowAnyOrigin is false and no AllowedOrigins are configured, CORS is effectively disabled.
/// No Access-Control-Allow-Origin header should be returned for any origin.
///
+ [NonParallelizable]
class When_cors_is_disabled : AcceptanceTest
{
CorsTestConfiguration configuration;
diff --git a/src/ServiceControl.Audit.AcceptanceTests/Security/Cors/When_request_from_allowed_origin.cs b/src/ServiceControl.Audit.AcceptanceTests/Security/Cors/When_request_from_allowed_origin.cs
index 4a14a8b801..9827da04a0 100644
--- a/src/ServiceControl.Audit.AcceptanceTests/Security/Cors/When_request_from_allowed_origin.cs
+++ b/src/ServiceControl.Audit.AcceptanceTests/Security/Cors/When_request_from_allowed_origin.cs
@@ -12,6 +12,7 @@ namespace ServiceControl.Audit.AcceptanceTests.Security.Cors
/// When a request comes from an origin that is in the AllowedOrigins list,
/// the response should include the Access-Control-Allow-Origin header with that specific origin.
///
+ [NonParallelizable]
class When_request_from_allowed_origin : AcceptanceTest
{
CorsTestConfiguration configuration;
diff --git a/src/ServiceControl.Audit.AcceptanceTests/Security/Cors/When_request_from_disallowed_origin.cs b/src/ServiceControl.Audit.AcceptanceTests/Security/Cors/When_request_from_disallowed_origin.cs
index d077ec88f6..b9f01b84ea 100644
--- a/src/ServiceControl.Audit.AcceptanceTests/Security/Cors/When_request_from_disallowed_origin.cs
+++ b/src/ServiceControl.Audit.AcceptanceTests/Security/Cors/When_request_from_disallowed_origin.cs
@@ -12,6 +12,7 @@ namespace ServiceControl.Audit.AcceptanceTests.Security.Cors
/// When a request comes from an origin that is NOT in the AllowedOrigins list,
/// the response should NOT include an Access-Control-Allow-Origin header that matches the request origin.
///
+ [NonParallelizable]
class When_request_from_disallowed_origin : AcceptanceTest
{
CorsTestConfiguration configuration;
diff --git a/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_forwarded_headers_are_disabled.cs b/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_forwarded_headers_are_disabled.cs
index 92a983e9de..76f3e22b95 100644
--- a/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_forwarded_headers_are_disabled.cs
+++ b/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_forwarded_headers_are_disabled.cs
@@ -10,6 +10,7 @@ namespace ServiceControl.Audit.AcceptanceTests.Security.ForwardedHeaders
/// Forwarded Headers Disabled
/// When forwarded headers processing is disabled, headers should be ignored regardless of trust.
///
+ [NonParallelizable]
class When_forwarded_headers_are_disabled : AcceptanceTest
{
ForwardedHeadersTestConfiguration configuration;
diff --git a/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_forwarded_headers_are_sent.cs b/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_forwarded_headers_are_sent.cs
index 34fa3de1c6..bd02d996a6 100644
--- a/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_forwarded_headers_are_sent.cs
+++ b/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_forwarded_headers_are_sent.cs
@@ -10,6 +10,7 @@ namespace ServiceControl.Audit.AcceptanceTests.Security.ForwardedHeaders
/// Default Behavior with Headers
/// When forwarded headers are sent and TrustAllProxies is true (default), headers should be applied.
///
+ [NonParallelizable]
class When_forwarded_headers_are_sent : AcceptanceTest
{
[Test]
diff --git a/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_known_networks_are_configured.cs b/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_known_networks_are_configured.cs
index 39a99b24de..00c2bdb1c5 100644
--- a/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_known_networks_are_configured.cs
+++ b/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_known_networks_are_configured.cs
@@ -10,6 +10,7 @@ namespace ServiceControl.Audit.AcceptanceTests.Security.ForwardedHeaders
/// Known Networks (CIDR)
/// When KnownNetworks are configured and the caller IP falls within, headers should be applied.
///
+ [NonParallelizable]
class When_known_networks_are_configured : AcceptanceTest
{
ForwardedHeadersTestConfiguration configuration;
diff --git a/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_known_proxies_are_configured.cs b/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_known_proxies_are_configured.cs
index fbf8a2a705..d6257717bd 100644
--- a/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_known_proxies_are_configured.cs
+++ b/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_known_proxies_are_configured.cs
@@ -10,6 +10,7 @@ namespace ServiceControl.Audit.AcceptanceTests.Security.ForwardedHeaders
/// Known Proxies Only
/// When KnownProxies are configured and the caller IP matches, headers should be applied.
///
+ [NonParallelizable]
class When_known_proxies_are_configured : AcceptanceTest
{
ForwardedHeadersTestConfiguration configuration;
diff --git a/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_multiple_header_values_are_sent.cs b/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_multiple_header_values_are_sent.cs
index ea29198632..0cd548fabd 100644
--- a/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_multiple_header_values_are_sent.cs
+++ b/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_multiple_header_values_are_sent.cs
@@ -11,6 +11,7 @@ namespace ServiceControl.Audit.AcceptanceTests.Security.ForwardedHeaders
/// When TrustAllProxies is true and headers contain multiple values (proxy chain),
/// the original (leftmost) values should be returned.
///
+ [NonParallelizable]
class When_multiple_header_values_are_sent : AcceptanceTest
{
[Test]
diff --git a/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_multiple_header_values_are_sent_with_known_proxies.cs b/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_multiple_header_values_are_sent_with_known_proxies.cs
index 901706f19f..4a10b83e52 100644
--- a/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_multiple_header_values_are_sent_with_known_proxies.cs
+++ b/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_multiple_header_values_are_sent_with_known_proxies.cs
@@ -11,6 +11,7 @@ namespace ServiceControl.Audit.AcceptanceTests.Security.ForwardedHeaders
/// When TrustAllProxies=false (known proxies configured), ForwardLimit=1,
/// so only the rightmost values are processed.
///
+ [NonParallelizable]
class When_multiple_header_values_are_sent_with_known_proxies : AcceptanceTest
{
ForwardedHeadersTestConfiguration configuration;
diff --git a/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_only_proto_header_is_sent.cs b/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_only_proto_header_is_sent.cs
index 6b0a38e081..66c7a36d08 100644
--- a/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_only_proto_header_is_sent.cs
+++ b/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_only_proto_header_is_sent.cs
@@ -10,6 +10,7 @@ namespace ServiceControl.Audit.AcceptanceTests.Security.ForwardedHeaders
/// Partial Headers (Proto Only)
/// When only X-Forwarded-Proto is sent, only scheme should change.
///
+ [NonParallelizable]
class When_only_proto_header_is_sent : AcceptanceTest
{
[Test]
diff --git a/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_proxy_chain_headers_are_sent.cs b/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_proxy_chain_headers_are_sent.cs
index fcf794ebea..d30b0a1031 100644
--- a/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_proxy_chain_headers_are_sent.cs
+++ b/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_proxy_chain_headers_are_sent.cs
@@ -11,6 +11,7 @@ namespace ServiceControl.Audit.AcceptanceTests.Security.ForwardedHeaders
/// When TrustAllProxies is true and X-Forwarded-For contains multiple IPs (proxy chain),
/// the original client IP (first in the chain) should be returned.
///
+ [NonParallelizable]
class When_proxy_chain_headers_are_sent : AcceptanceTest
{
[Test]
diff --git a/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_proxy_chain_headers_are_sent_with_known_proxies.cs b/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_proxy_chain_headers_are_sent_with_known_proxies.cs
index a2e9131bcd..6ea5c1a5ab 100644
--- a/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_proxy_chain_headers_are_sent_with_known_proxies.cs
+++ b/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_proxy_chain_headers_are_sent_with_known_proxies.cs
@@ -10,6 +10,7 @@ namespace ServiceControl.Audit.AcceptanceTests.Security.ForwardedHeaders
/// Proxy Chain with Known Proxies (ForwardLimit=1)
/// When TrustAllProxies=false (known proxies configured), ForwardLimit=1, so only the last proxy IP is processed.
///
+ [NonParallelizable]
class When_proxy_chain_headers_are_sent_with_known_proxies : AcceptanceTest
{
ForwardedHeadersTestConfiguration configuration;
diff --git a/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_request_has_no_forwarded_headers.cs b/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_request_has_no_forwarded_headers.cs
index c045909aca..5d2a21b651 100644
--- a/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_request_has_no_forwarded_headers.cs
+++ b/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_request_has_no_forwarded_headers.cs
@@ -10,6 +10,7 @@ namespace ServiceControl.Audit.AcceptanceTests.Security.ForwardedHeaders
/// Direct Access (No Proxy)
/// When no forwarded headers are sent, the request values should remain unchanged.
///
+ [NonParallelizable]
class When_request_has_no_forwarded_headers : AcceptanceTest
{
[Test]
diff --git a/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_trust_all_proxies_is_explicitly_configured.cs b/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_trust_all_proxies_is_explicitly_configured.cs
index c251cfe8d3..46d7ea883d 100644
--- a/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_trust_all_proxies_is_explicitly_configured.cs
+++ b/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_trust_all_proxies_is_explicitly_configured.cs
@@ -11,6 +11,7 @@ namespace ServiceControl.Audit.AcceptanceTests.Security.ForwardedHeaders
/// When TrustAllProxies is explicitly configured via environment variable, headers should be applied.
/// This test verifies the WithTrustAllProxies() configuration method works correctly.
///
+ [NonParallelizable]
class When_trust_all_proxies_is_explicitly_configured : AcceptanceTest
{
ForwardedHeadersTestConfiguration configuration;
diff --git a/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_unknown_network_sends_headers.cs b/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_unknown_network_sends_headers.cs
index 016bfbb706..e0ca6755c9 100644
--- a/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_unknown_network_sends_headers.cs
+++ b/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_unknown_network_sends_headers.cs
@@ -10,6 +10,7 @@ namespace ServiceControl.Audit.AcceptanceTests.Security.ForwardedHeaders
/// Unknown Network Rejected
/// When KnownNetworks are configured but the caller IP does NOT fall within, headers should be ignored.
///
+ [NonParallelizable]
class When_unknown_network_sends_headers : AcceptanceTest
{
ForwardedHeadersTestConfiguration configuration;
diff --git a/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_unknown_proxy_sends_headers.cs b/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_unknown_proxy_sends_headers.cs
index 84bcc88fb1..a9e63840a9 100644
--- a/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_unknown_proxy_sends_headers.cs
+++ b/src/ServiceControl.Audit.AcceptanceTests/Security/ForwardedHeaders/When_unknown_proxy_sends_headers.cs
@@ -10,6 +10,7 @@ namespace ServiceControl.Audit.AcceptanceTests.Security.ForwardedHeaders
/// Unknown Proxy Rejected
/// When KnownProxies are configured but the caller IP does NOT match, headers should be ignored.
///
+ [NonParallelizable]
class When_unknown_proxy_sends_headers : AcceptanceTest
{
ForwardedHeadersTestConfiguration configuration;
diff --git a/src/ServiceControl.Audit.AcceptanceTests/Security/Https/When_hsts_is_configured_in_development_mode.cs b/src/ServiceControl.Audit.AcceptanceTests/Security/Https/When_hsts_is_configured_in_development_mode.cs
index 3401c352cc..0f46bccd74 100644
--- a/src/ServiceControl.Audit.AcceptanceTests/Security/Https/When_hsts_is_configured_in_development_mode.cs
+++ b/src/ServiceControl.Audit.AcceptanceTests/Security/Https/When_hsts_is_configured_in_development_mode.cs
@@ -13,6 +13,7 @@ namespace ServiceControl.Audit.AcceptanceTests.Security.Https
/// In acceptance tests (which run in Development mode), HSTS headers are not sent.
/// This test verifies that HSTS is correctly NOT applied in development mode.
///
+ [NonParallelizable]
class When_hsts_is_configured_in_development_mode : AcceptanceTest
{
HttpsTestConfiguration configuration;
diff --git a/src/ServiceControl.Audit.AcceptanceTests/Security/Https/When_https_redirect_is_disabled.cs b/src/ServiceControl.Audit.AcceptanceTests/Security/Https/When_https_redirect_is_disabled.cs
index 30c7b8d61f..b49d7dd972 100644
--- a/src/ServiceControl.Audit.AcceptanceTests/Security/Https/When_https_redirect_is_disabled.cs
+++ b/src/ServiceControl.Audit.AcceptanceTests/Security/Https/When_https_redirect_is_disabled.cs
@@ -11,6 +11,7 @@ namespace ServiceControl.Audit.AcceptanceTests.Security.Https
/// HTTPS Redirect Disabled (Default)
/// When RedirectHttpToHttps is false (default), HTTP requests should not be redirected.
///
+ [NonParallelizable]
class When_https_redirect_is_disabled : AcceptanceTest
{
HttpsTestConfiguration configuration;
diff --git a/src/ServiceControl.Audit.AcceptanceTests/Security/Https/When_https_redirect_is_enabled.cs b/src/ServiceControl.Audit.AcceptanceTests/Security/Https/When_https_redirect_is_enabled.cs
index 47cac5511c..4bddc9efd9 100644
--- a/src/ServiceControl.Audit.AcceptanceTests/Security/Https/When_https_redirect_is_enabled.cs
+++ b/src/ServiceControl.Audit.AcceptanceTests/Security/Https/When_https_redirect_is_enabled.cs
@@ -11,6 +11,7 @@ namespace ServiceControl.Audit.AcceptanceTests.Security.Https
/// HTTPS Redirect Enabled
/// When RedirectHttpToHttps is true, HTTP requests should be redirected to HTTPS.
///
+ [NonParallelizable]
class When_https_redirect_is_enabled : AcceptanceTest
{
HttpsTestConfiguration configuration;
diff --git a/src/ServiceControl.Audit.AcceptanceTests/Security/OpenIdConnect/When_authentication_is_disabled.cs b/src/ServiceControl.Audit.AcceptanceTests/Security/OpenIdConnect/When_authentication_is_disabled.cs
index 03d36243f0..b32b7fb041 100644
--- a/src/ServiceControl.Audit.AcceptanceTests/Security/OpenIdConnect/When_authentication_is_disabled.cs
+++ b/src/ServiceControl.Audit.AcceptanceTests/Security/OpenIdConnect/When_authentication_is_disabled.cs
@@ -12,6 +12,7 @@ namespace ServiceControl.Audit.AcceptanceTests.Security.OpenIdConnect
/// When Authentication.Enabled is false (default), all API endpoints should be accessible
/// without authentication. Requests should not require Bearer tokens.
///
+ [NonParallelizable]
class When_authentication_is_disabled : AcceptanceTest
{
OpenIdConnectTestConfiguration configuration;
diff --git a/src/ServiceControl.Audit.AcceptanceTests/Security/OpenIdConnect/When_authentication_is_enabled.cs b/src/ServiceControl.Audit.AcceptanceTests/Security/OpenIdConnect/When_authentication_is_enabled.cs
index 5926e71c41..a1e177076d 100644
--- a/src/ServiceControl.Audit.AcceptanceTests/Security/OpenIdConnect/When_authentication_is_enabled.cs
+++ b/src/ServiceControl.Audit.AcceptanceTests/Security/OpenIdConnect/When_authentication_is_enabled.cs
@@ -16,6 +16,7 @@ namespace ServiceControl.Audit.AcceptanceTests.Security.OpenIdConnect
/// This test uses a mock OIDC server to provide discovery endpoints and signing keys,
/// allowing full testing of the JWT Bearer authentication flow.
///
+ [NonParallelizable]
class When_authentication_is_enabled : AcceptanceTest
{
OpenIdConnectTestConfiguration configuration;
diff --git a/src/ServiceControl.Audit.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs b/src/ServiceControl.Audit.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs
index 249e0f250e..2d873aaa9e 100644
--- a/src/ServiceControl.Audit.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs
+++ b/src/ServiceControl.Audit.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs
@@ -44,6 +44,16 @@ public class ServiceControlComponentRunner(
public Task Initialize(RunDescriptor run) => InitializeServiceControl(run.ScenarioContext);
async Task InitializeServiceControl(ScenarioContext context)
+ {
+ // Serialize initialization across parallel tests because:
+ // 1. ConfigurationManager.AppSettings is process-global and not thread-safe
+ // 2. The embedded RavenDB server does not support concurrent database create/delete/index operations
+ // The test scenario execution (after this method returns) still runs in parallel.
+ using var _ = await AcceptanceTestStorageConfiguration.UseDatabaseLifecycleLock();
+ await InitializeServiceControlCore(context);
+ }
+
+ async Task InitializeServiceControlCore(ScenarioContext context)
{
var logPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
Directory.CreateDirectory(logPath);
diff --git a/src/ServiceControl.Audit.Persistence.Tests.RavenDB/SharedEmbeddedServer.cs b/src/ServiceControl.Audit.Persistence.Tests.RavenDB/SharedEmbeddedServer.cs
index e5a9aa9639..8d8c613ca3 100644
--- a/src/ServiceControl.Audit.Persistence.Tests.RavenDB/SharedEmbeddedServer.cs
+++ b/src/ServiceControl.Audit.Persistence.Tests.RavenDB/SharedEmbeddedServer.cs
@@ -7,6 +7,7 @@
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting.Internal;
using Microsoft.Extensions.Logging.Abstractions;
+ using Nito.Disposables;
using NUnit.Framework;
using Persistence.RavenDB;
using Raven.Client.ServerWide.Operations;
diff --git a/src/ServiceControl.Audit.Persistence.Tests/NUnitSettings.cs b/src/ServiceControl.Audit.Persistence.Tests/NUnitSettings.cs
new file mode 100644
index 0000000000..8b76b23ac7
--- /dev/null
+++ b/src/ServiceControl.Audit.Persistence.Tests/NUnitSettings.cs
@@ -0,0 +1,5 @@
+using NUnit.Framework;
+
+[assembly: FixtureLifeCycle(LifeCycle.InstancePerTestCase)]
+[assembly: Parallelizable(ParallelScope.All)]
+[assembly: LevelOfParallelism(4)]
diff --git a/src/ServiceControl.Audit.UnitTests/NUnitSettings.cs b/src/ServiceControl.Audit.UnitTests/NUnitSettings.cs
new file mode 100644
index 0000000000..8b76b23ac7
--- /dev/null
+++ b/src/ServiceControl.Audit.UnitTests/NUnitSettings.cs
@@ -0,0 +1,5 @@
+using NUnit.Framework;
+
+[assembly: FixtureLifeCycle(LifeCycle.InstancePerTestCase)]
+[assembly: Parallelizable(ParallelScope.All)]
+[assembly: LevelOfParallelism(4)]
diff --git a/src/ServiceControl.Config.Tests/NUnitSettings.cs b/src/ServiceControl.Config.Tests/NUnitSettings.cs
new file mode 100644
index 0000000000..8b76b23ac7
--- /dev/null
+++ b/src/ServiceControl.Config.Tests/NUnitSettings.cs
@@ -0,0 +1,5 @@
+using NUnit.Framework;
+
+[assembly: FixtureLifeCycle(LifeCycle.InstancePerTestCase)]
+[assembly: Parallelizable(ParallelScope.All)]
+[assembly: LevelOfParallelism(4)]
diff --git a/src/ServiceControl.Infrastructure.Tests/NUnitSettings.cs b/src/ServiceControl.Infrastructure.Tests/NUnitSettings.cs
new file mode 100644
index 0000000000..8b76b23ac7
--- /dev/null
+++ b/src/ServiceControl.Infrastructure.Tests/NUnitSettings.cs
@@ -0,0 +1,5 @@
+using NUnit.Framework;
+
+[assembly: FixtureLifeCycle(LifeCycle.InstancePerTestCase)]
+[assembly: Parallelizable(ParallelScope.All)]
+[assembly: LevelOfParallelism(4)]
diff --git a/src/ServiceControl.Monitoring.AcceptanceTests/NUnitSettings.cs b/src/ServiceControl.Monitoring.AcceptanceTests/NUnitSettings.cs
new file mode 100644
index 0000000000..8b76b23ac7
--- /dev/null
+++ b/src/ServiceControl.Monitoring.AcceptanceTests/NUnitSettings.cs
@@ -0,0 +1,5 @@
+using NUnit.Framework;
+
+[assembly: FixtureLifeCycle(LifeCycle.InstancePerTestCase)]
+[assembly: Parallelizable(ParallelScope.All)]
+[assembly: LevelOfParallelism(4)]
diff --git a/src/ServiceControl.Monitoring.AcceptanceTests/Security/Cors/When_cors_allows_any_origin.cs b/src/ServiceControl.Monitoring.AcceptanceTests/Security/Cors/When_cors_allows_any_origin.cs
index 7b3ea434a6..40f1a6f6a8 100644
--- a/src/ServiceControl.Monitoring.AcceptanceTests/Security/Cors/When_cors_allows_any_origin.cs
+++ b/src/ServiceControl.Monitoring.AcceptanceTests/Security/Cors/When_cors_allows_any_origin.cs
@@ -12,6 +12,7 @@ namespace ServiceControl.Monitoring.AcceptanceTests.Security.Cors
/// When AllowAnyOrigin is true (default for backwards compatibility), requests from any origin should be allowed.
/// The Access-Control-Allow-Origin header should be "*".
///
+ [NonParallelizable]
class When_cors_allows_any_origin : AcceptanceTest
{
CorsTestConfiguration configuration;
diff --git a/src/ServiceControl.Monitoring.AcceptanceTests/Security/Cors/When_cors_is_disabled.cs b/src/ServiceControl.Monitoring.AcceptanceTests/Security/Cors/When_cors_is_disabled.cs
index f337d371ac..d7dbe61625 100644
--- a/src/ServiceControl.Monitoring.AcceptanceTests/Security/Cors/When_cors_is_disabled.cs
+++ b/src/ServiceControl.Monitoring.AcceptanceTests/Security/Cors/When_cors_is_disabled.cs
@@ -12,6 +12,7 @@ namespace ServiceControl.Monitoring.AcceptanceTests.Security.Cors
/// When AllowAnyOrigin is false and no AllowedOrigins are configured, CORS is effectively disabled.
/// No Access-Control-Allow-Origin header should be returned for any origin.
///
+ [NonParallelizable]
class When_cors_is_disabled : AcceptanceTest
{
CorsTestConfiguration configuration;
diff --git a/src/ServiceControl.Monitoring.AcceptanceTests/Security/Cors/When_request_from_allowed_origin.cs b/src/ServiceControl.Monitoring.AcceptanceTests/Security/Cors/When_request_from_allowed_origin.cs
index 7d4822f90e..71665ecbaf 100644
--- a/src/ServiceControl.Monitoring.AcceptanceTests/Security/Cors/When_request_from_allowed_origin.cs
+++ b/src/ServiceControl.Monitoring.AcceptanceTests/Security/Cors/When_request_from_allowed_origin.cs
@@ -12,6 +12,7 @@ namespace ServiceControl.Monitoring.AcceptanceTests.Security.Cors
/// When a request comes from an origin that is in the AllowedOrigins list,
/// the response should include the Access-Control-Allow-Origin header with that specific origin.
///
+ [NonParallelizable]
class When_request_from_allowed_origin : AcceptanceTest
{
CorsTestConfiguration configuration;
diff --git a/src/ServiceControl.Monitoring.AcceptanceTests/Security/Cors/When_request_from_disallowed_origin.cs b/src/ServiceControl.Monitoring.AcceptanceTests/Security/Cors/When_request_from_disallowed_origin.cs
index db1bffa20b..23513cd475 100644
--- a/src/ServiceControl.Monitoring.AcceptanceTests/Security/Cors/When_request_from_disallowed_origin.cs
+++ b/src/ServiceControl.Monitoring.AcceptanceTests/Security/Cors/When_request_from_disallowed_origin.cs
@@ -12,6 +12,7 @@ namespace ServiceControl.Monitoring.AcceptanceTests.Security.Cors
/// When a request comes from an origin that is NOT in the AllowedOrigins list,
/// the response should NOT include an Access-Control-Allow-Origin header that matches the request origin.
///
+ [NonParallelizable]
class When_request_from_disallowed_origin : AcceptanceTest
{
CorsTestConfiguration configuration;
diff --git a/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_forwarded_headers_are_disabled.cs b/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_forwarded_headers_are_disabled.cs
index 9c3bd719ec..ecebada948 100644
--- a/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_forwarded_headers_are_disabled.cs
+++ b/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_forwarded_headers_are_disabled.cs
@@ -9,6 +9,7 @@ namespace ServiceControl.Monitoring.AcceptanceTests.Security.ForwardedHeaders
///
/// When forwarded headers processing is disabled, headers should be ignored regardless of trust.
///
+ [NonParallelizable]
class When_forwarded_headers_are_disabled : AcceptanceTest
{
ForwardedHeadersTestConfiguration configuration;
diff --git a/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_forwarded_headers_are_sent.cs b/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_forwarded_headers_are_sent.cs
index 4fab083354..cda9411392 100644
--- a/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_forwarded_headers_are_sent.cs
+++ b/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_forwarded_headers_are_sent.cs
@@ -9,6 +9,7 @@ namespace ServiceControl.Monitoring.AcceptanceTests.Security.ForwardedHeaders
///
/// When forwarded headers are sent and TrustAllProxies is true (default), headers should be applied.
///
+ [NonParallelizable]
class When_forwarded_headers_are_sent : AcceptanceTest
{
[Test]
diff --git a/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_known_networks_are_configured.cs b/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_known_networks_are_configured.cs
index 2ab9a17781..e3a523001a 100644
--- a/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_known_networks_are_configured.cs
+++ b/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_known_networks_are_configured.cs
@@ -9,6 +9,7 @@ namespace ServiceControl.Monitoring.AcceptanceTests.Security.ForwardedHeaders
///
/// When KnownNetworks are configured and the caller IP falls within, headers should be applied.
///
+ [NonParallelizable]
class When_known_networks_are_configured : AcceptanceTest
{
ForwardedHeadersTestConfiguration configuration;
diff --git a/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_known_proxies_are_configured.cs b/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_known_proxies_are_configured.cs
index 487b26ba2a..e0f1611f55 100644
--- a/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_known_proxies_are_configured.cs
+++ b/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_known_proxies_are_configured.cs
@@ -9,6 +9,7 @@ namespace ServiceControl.Monitoring.AcceptanceTests.Security.ForwardedHeaders
///
/// When KnownProxies are configured and the caller IP matches, headers should be applied.
///
+ [NonParallelizable]
class When_known_proxies_are_configured : AcceptanceTest
{
ForwardedHeadersTestConfiguration configuration;
diff --git a/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_multiple_header_values_are_sent.cs b/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_multiple_header_values_are_sent.cs
index ce2732091c..88d11cef60 100644
--- a/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_multiple_header_values_are_sent.cs
+++ b/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_multiple_header_values_are_sent.cs
@@ -10,6 +10,7 @@ namespace ServiceControl.Monitoring.AcceptanceTests.Security.ForwardedHeaders
/// When TrustAllProxies is true and headers contain multiple values (proxy chain),
/// the original (leftmost) values should be returned.
///
+ [NonParallelizable]
class When_multiple_header_values_are_sent : AcceptanceTest
{
[Test]
diff --git a/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_multiple_header_values_are_sent_with_known_proxies.cs b/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_multiple_header_values_are_sent_with_known_proxies.cs
index c559bb79c0..1d674e850a 100644
--- a/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_multiple_header_values_are_sent_with_known_proxies.cs
+++ b/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_multiple_header_values_are_sent_with_known_proxies.cs
@@ -10,6 +10,7 @@ namespace ServiceControl.Monitoring.AcceptanceTests.Security.ForwardedHeaders
/// When TrustAllProxies=false (known proxies configured), ForwardLimit=1,
/// so only the rightmost values are processed.
///
+ [NonParallelizable]
class When_multiple_header_values_are_sent_with_known_proxies : AcceptanceTest
{
ForwardedHeadersTestConfiguration configuration;
diff --git a/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_only_proto_header_is_sent.cs b/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_only_proto_header_is_sent.cs
index efb8497eb6..90fc3b98e4 100644
--- a/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_only_proto_header_is_sent.cs
+++ b/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_only_proto_header_is_sent.cs
@@ -9,6 +9,7 @@ namespace ServiceControl.Monitoring.AcceptanceTests.Security.ForwardedHeaders
///
/// When only X-Forwarded-Proto is sent, only scheme should change.
///
+ [NonParallelizable]
class When_only_proto_header_is_sent : AcceptanceTest
{
[Test]
diff --git a/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_proxy_chain_headers_are_sent.cs b/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_proxy_chain_headers_are_sent.cs
index 0df4b812e3..adf89d5095 100644
--- a/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_proxy_chain_headers_are_sent.cs
+++ b/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_proxy_chain_headers_are_sent.cs
@@ -10,6 +10,7 @@ namespace ServiceControl.Monitoring.AcceptanceTests.Security.ForwardedHeaders
/// When TrustAllProxies is true and X-Forwarded-For contains multiple IPs (proxy chain),
/// the original client IP (first in the chain) should be returned.
///
+ [NonParallelizable]
class When_proxy_chain_headers_are_sent : AcceptanceTest
{
[Test]
diff --git a/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_proxy_chain_headers_are_sent_with_known_proxies.cs b/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_proxy_chain_headers_are_sent_with_known_proxies.cs
index ac863f6a3d..dcbbd77683 100644
--- a/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_proxy_chain_headers_are_sent_with_known_proxies.cs
+++ b/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_proxy_chain_headers_are_sent_with_known_proxies.cs
@@ -9,6 +9,7 @@ namespace ServiceControl.Monitoring.AcceptanceTests.Security.ForwardedHeaders
///
/// When TrustAllProxies=false (known proxies configured), ForwardLimit=1, so only the last proxy IP is processed.
///
+ [NonParallelizable]
class When_proxy_chain_headers_are_sent_with_known_proxies : AcceptanceTest
{
ForwardedHeadersTestConfiguration configuration;
diff --git a/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_request_has_no_forwarded_headers.cs b/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_request_has_no_forwarded_headers.cs
index 99773f82e1..888c8bbab4 100644
--- a/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_request_has_no_forwarded_headers.cs
+++ b/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_request_has_no_forwarded_headers.cs
@@ -9,6 +9,7 @@ namespace ServiceControl.Monitoring.AcceptanceTests.Security.ForwardedHeaders
///
/// When no forwarded headers are sent, the request values should remain unchanged.
///
+ [NonParallelizable]
class When_request_has_no_forwarded_headers : AcceptanceTest
{
[Test]
diff --git a/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_trust_all_proxies_is_explicitly_configured.cs b/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_trust_all_proxies_is_explicitly_configured.cs
index bc30673c51..6c642da9f8 100644
--- a/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_trust_all_proxies_is_explicitly_configured.cs
+++ b/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_trust_all_proxies_is_explicitly_configured.cs
@@ -11,6 +11,7 @@ namespace ServiceControl.Monitoring.AcceptanceTests.Security.ForwardedHeaders
/// When TrustAllProxies is explicitly configured via environment variable, headers should be applied.
/// This test verifies the WithTrustAllProxies() configuration method works correctly.
///
+ [NonParallelizable]
class When_trust_all_proxies_is_explicitly_configured : AcceptanceTest
{
ForwardedHeadersTestConfiguration configuration;
diff --git a/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_unknown_network_sends_headers.cs b/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_unknown_network_sends_headers.cs
index 39e4343a71..e5b20ab42c 100644
--- a/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_unknown_network_sends_headers.cs
+++ b/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_unknown_network_sends_headers.cs
@@ -9,6 +9,7 @@ namespace ServiceControl.Monitoring.AcceptanceTests.Security.ForwardedHeaders
///
/// When KnownNetworks are configured but the caller IP does NOT fall within, headers should be ignored.
///
+ [NonParallelizable]
class When_unknown_network_sends_headers : AcceptanceTest
{
ForwardedHeadersTestConfiguration configuration;
diff --git a/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_unknown_proxy_sends_headers.cs b/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_unknown_proxy_sends_headers.cs
index 6dc3aca1c1..1bc6ff49a0 100644
--- a/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_unknown_proxy_sends_headers.cs
+++ b/src/ServiceControl.Monitoring.AcceptanceTests/Security/ForwardedHeaders/When_unknown_proxy_sends_headers.cs
@@ -9,6 +9,7 @@ namespace ServiceControl.Monitoring.AcceptanceTests.Security.ForwardedHeaders
///
/// When KnownProxies are configured but the caller IP does NOT match, headers should be ignored.
///
+ [NonParallelizable]
class When_unknown_proxy_sends_headers : AcceptanceTest
{
ForwardedHeadersTestConfiguration configuration;
diff --git a/src/ServiceControl.Monitoring.AcceptanceTests/Security/Https/When_hsts_is_configured_in_development_mode.cs b/src/ServiceControl.Monitoring.AcceptanceTests/Security/Https/When_hsts_is_configured_in_development_mode.cs
index 4a799d92e1..875265903f 100644
--- a/src/ServiceControl.Monitoring.AcceptanceTests/Security/Https/When_hsts_is_configured_in_development_mode.cs
+++ b/src/ServiceControl.Monitoring.AcceptanceTests/Security/Https/When_hsts_is_configured_in_development_mode.cs
@@ -13,6 +13,7 @@ namespace ServiceControl.Monitoring.AcceptanceTests.Security.Https
/// In acceptance tests (which run in Development mode), HSTS headers are not sent.
/// This test verifies that HSTS is correctly NOT applied in development mode.
///
+ [NonParallelizable]
class When_hsts_is_configured_in_development_mode : AcceptanceTest
{
HttpsTestConfiguration configuration;
diff --git a/src/ServiceControl.Monitoring.AcceptanceTests/Security/Https/When_https_redirect_is_disabled.cs b/src/ServiceControl.Monitoring.AcceptanceTests/Security/Https/When_https_redirect_is_disabled.cs
index 1726e058f3..b33784dea2 100644
--- a/src/ServiceControl.Monitoring.AcceptanceTests/Security/Https/When_https_redirect_is_disabled.cs
+++ b/src/ServiceControl.Monitoring.AcceptanceTests/Security/Https/When_https_redirect_is_disabled.cs
@@ -11,6 +11,7 @@ namespace ServiceControl.Monitoring.AcceptanceTests.Security.Https
/// HTTPS Redirect Disabled (Default)
/// When RedirectHttpToHttps is false (default), HTTP requests should not be redirected.
///
+ [NonParallelizable]
class When_https_redirect_is_disabled : AcceptanceTest
{
HttpsTestConfiguration configuration;
diff --git a/src/ServiceControl.Monitoring.AcceptanceTests/Security/Https/When_https_redirect_is_enabled.cs b/src/ServiceControl.Monitoring.AcceptanceTests/Security/Https/When_https_redirect_is_enabled.cs
index d55baab276..999e0814cd 100644
--- a/src/ServiceControl.Monitoring.AcceptanceTests/Security/Https/When_https_redirect_is_enabled.cs
+++ b/src/ServiceControl.Monitoring.AcceptanceTests/Security/Https/When_https_redirect_is_enabled.cs
@@ -11,6 +11,7 @@ namespace ServiceControl.Monitoring.AcceptanceTests.Security.Https
/// HTTPS Redirect Enabled
/// When RedirectHttpToHttps is true, HTTP requests should be redirected to HTTPS.
///
+ [NonParallelizable]
class When_https_redirect_is_enabled : AcceptanceTest
{
HttpsTestConfiguration configuration;
diff --git a/src/ServiceControl.Monitoring.AcceptanceTests/Security/OpenIdConnect/When_authentication_is_disabled.cs b/src/ServiceControl.Monitoring.AcceptanceTests/Security/OpenIdConnect/When_authentication_is_disabled.cs
index 279976b831..c8cf0b1670 100644
--- a/src/ServiceControl.Monitoring.AcceptanceTests/Security/OpenIdConnect/When_authentication_is_disabled.cs
+++ b/src/ServiceControl.Monitoring.AcceptanceTests/Security/OpenIdConnect/When_authentication_is_disabled.cs
@@ -12,6 +12,7 @@ namespace ServiceControl.Monitoring.AcceptanceTests.Security.OpenIdConnect
/// When Authentication.Enabled is false (default), all API endpoints should be accessible
/// without authentication. Requests should not require Bearer tokens.
///
+ [NonParallelizable]
class When_authentication_is_disabled : AcceptanceTest
{
OpenIdConnectTestConfiguration configuration;
diff --git a/src/ServiceControl.Monitoring.AcceptanceTests/Security/OpenIdConnect/When_authentication_is_enabled.cs b/src/ServiceControl.Monitoring.AcceptanceTests/Security/OpenIdConnect/When_authentication_is_enabled.cs
index 963f727b86..9be7d0160f 100644
--- a/src/ServiceControl.Monitoring.AcceptanceTests/Security/OpenIdConnect/When_authentication_is_enabled.cs
+++ b/src/ServiceControl.Monitoring.AcceptanceTests/Security/OpenIdConnect/When_authentication_is_enabled.cs
@@ -16,6 +16,7 @@ namespace ServiceControl.Monitoring.AcceptanceTests.Security.OpenIdConnect
/// This test uses a mock OIDC server to provide discovery endpoints and signing keys,
/// allowing full testing of the JWT Bearer authentication flow.
///
+ [NonParallelizable]
class When_authentication_is_enabled : AcceptanceTest
{
OpenIdConnectTestConfiguration configuration;
diff --git a/src/ServiceControl.Monitoring.UnitTests/NUnitSettings.cs b/src/ServiceControl.Monitoring.UnitTests/NUnitSettings.cs
new file mode 100644
index 0000000000..8b76b23ac7
--- /dev/null
+++ b/src/ServiceControl.Monitoring.UnitTests/NUnitSettings.cs
@@ -0,0 +1,5 @@
+using NUnit.Framework;
+
+[assembly: FixtureLifeCycle(LifeCycle.InstancePerTestCase)]
+[assembly: Parallelizable(ParallelScope.All)]
+[assembly: LevelOfParallelism(4)]
diff --git a/src/ServiceControl.MultiInstance.AcceptanceTests/NUnitSettings.cs b/src/ServiceControl.MultiInstance.AcceptanceTests/NUnitSettings.cs
new file mode 100644
index 0000000000..8b76b23ac7
--- /dev/null
+++ b/src/ServiceControl.MultiInstance.AcceptanceTests/NUnitSettings.cs
@@ -0,0 +1,5 @@
+using NUnit.Framework;
+
+[assembly: FixtureLifeCycle(LifeCycle.InstancePerTestCase)]
+[assembly: Parallelizable(ParallelScope.All)]
+[assembly: LevelOfParallelism(4)]
diff --git a/src/ServiceControl.MultiInstance.AcceptanceTests/Recoverability/WhenRetryingSameMessageMultipleTimes.cs b/src/ServiceControl.MultiInstance.AcceptanceTests/Recoverability/WhenRetryingSameMessageMultipleTimes.cs
index 62683b9bbb..68b100316b 100644
--- a/src/ServiceControl.MultiInstance.AcceptanceTests/Recoverability/WhenRetryingSameMessageMultipleTimes.cs
+++ b/src/ServiceControl.MultiInstance.AcceptanceTests/Recoverability/WhenRetryingSameMessageMultipleTimes.cs
@@ -26,7 +26,7 @@ public enum RetryType
[TestCase(new[] { RetryType.Edit, RetryType.NoEdit, RetryType.Edit, RetryType.NoEdit })]
//[TestCase(new[] { RetryType.NoEdit, RetryType.Edit, RetryType.NoEdit, RetryType.Edit })]
[TestCase(new[] { RetryType.Edit, RetryType.Edit, RetryType.NoEdit })]
- [CancelAfter(15_000)]
+ [CancelAfter(30_000)]
public async Task WithMixOfRetryTypes(RetryType[] retryTypes, CancellationToken cancellationToken)
{
CustomServiceControlPrimarySettings = s => { s.AllowMessageEditing = true; };
diff --git a/src/ServiceControl.MultiInstance.AcceptanceTests/SetupFixture.cs b/src/ServiceControl.MultiInstance.AcceptanceTests/SetupFixture.cs
new file mode 100644
index 0000000000..4c74e8dcc9
--- /dev/null
+++ b/src/ServiceControl.MultiInstance.AcceptanceTests/SetupFixture.cs
@@ -0,0 +1,29 @@
+namespace ServiceControl.MultiInstance.AcceptanceTests;
+
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Threading.Tasks;
+using NUnit.Framework;
+
+[SetUpFixture]
+public class SetupFixture
+{
+ [OneTimeSetUp]
+ public async Task Setup()
+ {
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ ServiceBus.Management.Infrastructure.Installers.EventSourceCreator.Create();
+
+ //There is a delay for this becoming true, tests will fall over if they interleave in the wrong way.
+ var cts = new CancellationTokenSource(TimeSpan.FromSeconds(60));
+ while (!EventLog.SourceExists(ServiceBus.Management.Infrastructure.Installers.EventSourceCreator.SourceName))
+ {
+ cts.Token.ThrowIfCancellationRequested();
+ await Task.Delay(500, CancellationToken.None);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ServiceControl.MultiInstance.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs b/src/ServiceControl.MultiInstance.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs
index 5a57e0c874..4f3335216c 100644
--- a/src/ServiceControl.MultiInstance.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs
+++ b/src/ServiceControl.MultiInstance.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs
@@ -77,7 +77,7 @@ public async Task Initialize(RunDescriptor run)
primaryInstanceComponentRunner = new PrimaryInstanceTestsSupport.ServiceControlComponentRunner(
transportToUse,
- new ServiceControl.AcceptanceTests.AcceptanceTestStorageConfiguration(), primarySettings =>
+ new ServiceControl.AcceptanceTests.RavenDB.AcceptanceTestStorageConfiguration(), primarySettings =>
{
primarySettings.RemoteInstances = [auditInstance];
customServiceControlSettings(primarySettings);
diff --git a/src/ServiceControl.Persistence.Tests.InMemory/NUnitSettings.cs b/src/ServiceControl.Persistence.Tests.InMemory/NUnitSettings.cs
new file mode 100644
index 0000000000..8b76b23ac7
--- /dev/null
+++ b/src/ServiceControl.Persistence.Tests.InMemory/NUnitSettings.cs
@@ -0,0 +1,5 @@
+using NUnit.Framework;
+
+[assembly: FixtureLifeCycle(LifeCycle.InstancePerTestCase)]
+[assembly: Parallelizable(ParallelScope.All)]
+[assembly: LevelOfParallelism(4)]
diff --git a/src/ServiceControl.Persistence.Tests.PostgreSql/NUnitSettings.cs b/src/ServiceControl.Persistence.Tests.PostgreSql/NUnitSettings.cs
index 8478866bcd..ba80ffbc87 100644
--- a/src/ServiceControl.Persistence.Tests.PostgreSql/NUnitSettings.cs
+++ b/src/ServiceControl.Persistence.Tests.PostgreSql/NUnitSettings.cs
@@ -1,4 +1,4 @@
using NUnit.Framework;
[assembly: Parallelizable(ParallelScope.All)]
-[assembly: LevelOfParallelism(4)]
\ No newline at end of file
+[assembly: LevelOfParallelism(4)]
diff --git a/src/ServiceControl.Persistence.Tests.RavenDB/NUnitSettings.cs b/src/ServiceControl.Persistence.Tests.RavenDB/NUnitSettings.cs
index ba80ffbc87..8b76b23ac7 100644
--- a/src/ServiceControl.Persistence.Tests.RavenDB/NUnitSettings.cs
+++ b/src/ServiceControl.Persistence.Tests.RavenDB/NUnitSettings.cs
@@ -1,4 +1,5 @@
using NUnit.Framework;
+[assembly: FixtureLifeCycle(LifeCycle.InstancePerTestCase)]
[assembly: Parallelizable(ParallelScope.All)]
[assembly: LevelOfParallelism(4)]
diff --git a/src/ServiceControl.Persistence.Tests.RavenDB/SharedEmbeddedServer.cs b/src/ServiceControl.Persistence.Tests.RavenDB/SharedEmbeddedServer.cs
index ae6d389dcb..b35874bba5 100644
--- a/src/ServiceControl.Persistence.Tests.RavenDB/SharedEmbeddedServer.cs
+++ b/src/ServiceControl.Persistence.Tests.RavenDB/SharedEmbeddedServer.cs
@@ -1,7 +1,9 @@
namespace ServiceControl.Persistence.Tests
{
+ using System;
using System.IO;
using System.Linq;
+ using System.Reactive.Disposables;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting.Internal;
@@ -89,5 +91,6 @@ public static async Task Stop(CancellationToken cancellationToken = default)
static EmbeddedDatabase embeddedDatabase;
static readonly SemaphoreSlim semaphoreSlim = new(1, 1);
+
}
}
\ No newline at end of file
diff --git a/src/ServiceControl.Persistence.Tests.SqlServer/NUnitSettings.cs b/src/ServiceControl.Persistence.Tests.SqlServer/NUnitSettings.cs
index 8478866bcd..ba80ffbc87 100644
--- a/src/ServiceControl.Persistence.Tests.SqlServer/NUnitSettings.cs
+++ b/src/ServiceControl.Persistence.Tests.SqlServer/NUnitSettings.cs
@@ -1,4 +1,4 @@
using NUnit.Framework;
[assembly: Parallelizable(ParallelScope.All)]
-[assembly: LevelOfParallelism(4)]
\ No newline at end of file
+[assembly: LevelOfParallelism(4)]
diff --git a/src/ServiceControl.Transports.ASQ.Tests/NUnitSettings.cs b/src/ServiceControl.Transports.ASQ.Tests/NUnitSettings.cs
new file mode 100644
index 0000000000..ba80ffbc87
--- /dev/null
+++ b/src/ServiceControl.Transports.ASQ.Tests/NUnitSettings.cs
@@ -0,0 +1,4 @@
+using NUnit.Framework;
+
+[assembly: Parallelizable(ParallelScope.All)]
+[assembly: LevelOfParallelism(4)]
diff --git a/src/ServiceControl.Transports.IBMMQ.Tests/NUnitSettings.cs b/src/ServiceControl.Transports.IBMMQ.Tests/NUnitSettings.cs
new file mode 100644
index 0000000000..ba80ffbc87
--- /dev/null
+++ b/src/ServiceControl.Transports.IBMMQ.Tests/NUnitSettings.cs
@@ -0,0 +1,4 @@
+using NUnit.Framework;
+
+[assembly: Parallelizable(ParallelScope.All)]
+[assembly: LevelOfParallelism(4)]
diff --git a/src/ServiceControl.Transports.PostgreSql.Tests/NUnitSettings.cs b/src/ServiceControl.Transports.PostgreSql.Tests/NUnitSettings.cs
new file mode 100644
index 0000000000..ba80ffbc87
--- /dev/null
+++ b/src/ServiceControl.Transports.PostgreSql.Tests/NUnitSettings.cs
@@ -0,0 +1,4 @@
+using NUnit.Framework;
+
+[assembly: Parallelizable(ParallelScope.All)]
+[assembly: LevelOfParallelism(4)]
diff --git a/src/ServiceControl.Transports.Tests/FullEndpointTestFixture.cs b/src/ServiceControl.Transports.Tests/FullEndpointTestFixture.cs
index 0c0af7df1c..968d6467f6 100644
--- a/src/ServiceControl.Transports.Tests/FullEndpointTestFixture.cs
+++ b/src/ServiceControl.Transports.Tests/FullEndpointTestFixture.cs
@@ -7,7 +7,7 @@
using ServiceControl.Infrastructure;
[TestFixture]
-
+ [FixtureLifeCycle(LifeCycle.InstancePerTestCase)]
abstract class FullEndpointTestFixture
{
[SetUp]
diff --git a/src/ServiceControl.Transports.Tests/Learning/NUnitSettings.cs b/src/ServiceControl.Transports.Tests/Learning/NUnitSettings.cs
new file mode 100644
index 0000000000..ba80ffbc87
--- /dev/null
+++ b/src/ServiceControl.Transports.Tests/Learning/NUnitSettings.cs
@@ -0,0 +1,4 @@
+using NUnit.Framework;
+
+[assembly: Parallelizable(ParallelScope.All)]
+[assembly: LevelOfParallelism(4)]
diff --git a/src/ServiceControl.Transports.Tests/Learning/TransportTestsConfiguration.cs b/src/ServiceControl.Transports.Tests/Learning/TransportTestsConfiguration.cs
index 6a4a5b2c0f..0abad18c81 100644
--- a/src/ServiceControl.Transports.Tests/Learning/TransportTestsConfiguration.cs
+++ b/src/ServiceControl.Transports.Tests/Learning/TransportTestsConfiguration.cs
@@ -10,7 +10,7 @@ partial class TransportTestsConfiguration
{
public Task Configure()
{
- basePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ".transporttests");
+ basePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $".transporttests{Guid.NewGuid():N}");
if (Directory.Exists(basePath))
{
diff --git a/src/ServiceControl.Transports.Tests/QueueIngestionTests.cs b/src/ServiceControl.Transports.Tests/QueueIngestionTests.cs
index dc45c3ffb0..246e32b0c6 100644
--- a/src/ServiceControl.Transports.Tests/QueueIngestionTests.cs
+++ b/src/ServiceControl.Transports.Tests/QueueIngestionTests.cs
@@ -9,6 +9,7 @@
// The logging cannot be reinitialized, so subsequent test that utilize the Scenario.Define.Run will use a different log factory that depends on more statics :(
// The end result is a null reference exception :(
[TestFixture]
+ [NonParallelizable]
[Order(1)]
class QueueIngestionTests : TransportTestFixture
{
diff --git a/src/ServiceControl.UnitTests/Infrastructure/Settings/CorsSettingsTests.cs b/src/ServiceControl.UnitTests/Infrastructure/Settings/CorsSettingsTests.cs
index c0fab432be..7a1e791c60 100644
--- a/src/ServiceControl.UnitTests/Infrastructure/Settings/CorsSettingsTests.cs
+++ b/src/ServiceControl.UnitTests/Infrastructure/Settings/CorsSettingsTests.cs
@@ -13,6 +13,7 @@ namespace ServiceControl.UnitTests.Infrastructure.Settings;
/// The parsing logic is identical, so testing with one namespace is sufficient.
///
[TestFixture]
+[NonParallelizable]
public class CorsSettingsTests
{
static readonly SettingsRootNamespace TestNamespace = new("ServiceControl");
diff --git a/src/ServiceControl.UnitTests/Infrastructure/Settings/ForwardedHeadersSettingsTests.cs b/src/ServiceControl.UnitTests/Infrastructure/Settings/ForwardedHeadersSettingsTests.cs
index 0f51cb4b78..dd2c80bb97 100644
--- a/src/ServiceControl.UnitTests/Infrastructure/Settings/ForwardedHeadersSettingsTests.cs
+++ b/src/ServiceControl.UnitTests/Infrastructure/Settings/ForwardedHeadersSettingsTests.cs
@@ -14,6 +14,7 @@ namespace ServiceControl.UnitTests.Infrastructure.Settings;
/// The parsing logic is identical, so testing with one namespace is sufficient.
///
[TestFixture]
+[NonParallelizable]
public class ForwardedHeadersSettingsTests
{
static readonly SettingsRootNamespace TestNamespace = new("ServiceControl");
diff --git a/src/ServiceControl.UnitTests/Infrastructure/Settings/HttpsSettingsTests.cs b/src/ServiceControl.UnitTests/Infrastructure/Settings/HttpsSettingsTests.cs
index 71766b1c2d..8a0730e49b 100644
--- a/src/ServiceControl.UnitTests/Infrastructure/Settings/HttpsSettingsTests.cs
+++ b/src/ServiceControl.UnitTests/Infrastructure/Settings/HttpsSettingsTests.cs
@@ -14,6 +14,7 @@ namespace ServiceControl.UnitTests.Infrastructure.Settings;
/// The parsing logic is identical, so testing with one namespace is sufficient.
///
[TestFixture]
+[NonParallelizable]
public class HttpsSettingsTests
{
static readonly SettingsRootNamespace TestNamespace = new("ServiceControl");
diff --git a/src/ServiceControl.UnitTests/Infrastructure/Settings/OpenIdConnectSettingsTests.cs b/src/ServiceControl.UnitTests/Infrastructure/Settings/OpenIdConnectSettingsTests.cs
index a3e497415a..aeea90f1f3 100644
--- a/src/ServiceControl.UnitTests/Infrastructure/Settings/OpenIdConnectSettingsTests.cs
+++ b/src/ServiceControl.UnitTests/Infrastructure/Settings/OpenIdConnectSettingsTests.cs
@@ -13,6 +13,7 @@ namespace ServiceControl.UnitTests.Infrastructure.Settings;
/// The parsing logic is identical, so testing with one namespace is sufficient.
///
[TestFixture]
+[NonParallelizable]
public class OpenIdConnectSettingsTests
{
static readonly SettingsRootNamespace TestNamespace = new("ServiceControl");
diff --git a/src/ServiceControl.UnitTests/NUnitSettings.cs b/src/ServiceControl.UnitTests/NUnitSettings.cs
new file mode 100644
index 0000000000..8b76b23ac7
--- /dev/null
+++ b/src/ServiceControl.UnitTests/NUnitSettings.cs
@@ -0,0 +1,5 @@
+using NUnit.Framework;
+
+[assembly: FixtureLifeCycle(LifeCycle.InstancePerTestCase)]
+[assembly: Parallelizable(ParallelScope.All)]
+[assembly: LevelOfParallelism(4)]
diff --git a/src/ServiceControl.UnitTests/RepeatedFailuresOverTimeCircuitBreakerTests.cs b/src/ServiceControl.UnitTests/RepeatedFailuresOverTimeCircuitBreakerTests.cs
index e955646a88..a2abc171f4 100644
--- a/src/ServiceControl.UnitTests/RepeatedFailuresOverTimeCircuitBreakerTests.cs
+++ b/src/ServiceControl.UnitTests/RepeatedFailuresOverTimeCircuitBreakerTests.cs
@@ -11,6 +11,7 @@
// Ideally the circuit breaker would use a time provider to allow for easier testing but that would require a significant refactor
// and we want keep the changes to a minimum for now to allow backporting to older versions.
[TestFixture]
+ [NonParallelizable]
public class RepeatedFailuresOverTimeCircuitBreakerTests
{
[SetUp]
diff --git a/src/ServiceControlInstaller.Engine.UnitTests/NUnitSettings.cs b/src/ServiceControlInstaller.Engine.UnitTests/NUnitSettings.cs
new file mode 100644
index 0000000000..8b76b23ac7
--- /dev/null
+++ b/src/ServiceControlInstaller.Engine.UnitTests/NUnitSettings.cs
@@ -0,0 +1,5 @@
+using NUnit.Framework;
+
+[assembly: FixtureLifeCycle(LifeCycle.InstancePerTestCase)]
+[assembly: Parallelizable(ParallelScope.All)]
+[assembly: LevelOfParallelism(4)]
diff --git a/src/ServiceControlInstaller.Packaging.UnitTests/NUnitSettings.cs b/src/ServiceControlInstaller.Packaging.UnitTests/NUnitSettings.cs
new file mode 100644
index 0000000000..8b76b23ac7
--- /dev/null
+++ b/src/ServiceControlInstaller.Packaging.UnitTests/NUnitSettings.cs
@@ -0,0 +1,5 @@
+using NUnit.Framework;
+
+[assembly: FixtureLifeCycle(LifeCycle.InstancePerTestCase)]
+[assembly: Parallelizable(ParallelScope.All)]
+[assembly: LevelOfParallelism(4)]