test(secrets): serialize env-var-mutating test classes into one xunit collection
Environment.SetEnvironmentVariable/GetEnvironmentVariable mutate the process-wide environ; concurrent setenv/getenv across parallel xunit test classes is a documented crash/flake source on glibc even with unique variable names. Group the six classes that touch process env vars into a DisableParallelization=true collection so they run serially against each other while everything else keeps running in parallel.
This commit is contained in:
+1
@@ -13,6 +13,7 @@ namespace ZB.MOM.WW.Secrets.Tests.Cli.Interactive;
|
|||||||
/// KEK-upgrade prompt, and the error-containment panel. The shell is the only UI-owning class, so these
|
/// KEK-upgrade prompt, and the error-containment panel. The shell is the only UI-owning class, so these
|
||||||
/// tests assert on rendered <see cref="TestConsole.Output"/> and on what a fake flow observed.
|
/// tests assert on rendered <see cref="TestConsole.Output"/> and on what a fake flow observed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Collection("Process environment")]
|
||||||
public sealed class InteractiveShellTests : IDisposable
|
public sealed class InteractiveShellTests : IDisposable
|
||||||
{
|
{
|
||||||
private readonly string _dir =
|
private readonly string _dir =
|
||||||
|
|||||||
+1
@@ -11,6 +11,7 @@ namespace ZB.MOM.WW.Secrets.Tests.Cli.Interactive;
|
|||||||
/// <see cref="IMasterKeyProvider.KekId"/> derived identically to the configured providers so a key
|
/// <see cref="IMasterKeyProvider.KekId"/> derived identically to the configured providers so a key
|
||||||
/// entered by hand can decrypt (and re-wrap) rows another provider kind sealed.
|
/// entered by hand can decrypt (and re-wrap) rows another provider kind sealed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Collection("Process environment")]
|
||||||
public sealed class LiteralMasterKeyProviderTests
|
public sealed class LiteralMasterKeyProviderTests
|
||||||
{
|
{
|
||||||
private static string NewKeyBase64()
|
private static string NewKeyBase64()
|
||||||
|
|||||||
+1
@@ -13,6 +13,7 @@ namespace ZB.MOM.WW.Secrets.Tests.Cli.Interactive;
|
|||||||
/// (present/decryptable → Ok, absent → Missing, tombstoned → Tombstoned, wrong-KEK → Undecryptable),
|
/// (present/decryptable → Ok, absent → Missing, tombstoned → Tombstoned, wrong-KEK → Undecryptable),
|
||||||
/// and the degraded-session presence-only downgrade (present → PresentUnverified).
|
/// and the degraded-session presence-only downgrade (present → PresentUnverified).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Collection("Process environment")]
|
||||||
public sealed class ReferenceAuditorTests : IDisposable
|
public sealed class ReferenceAuditorTests : IDisposable
|
||||||
{
|
{
|
||||||
private readonly string _dir =
|
private readonly string _dir =
|
||||||
|
|||||||
+1
@@ -13,6 +13,7 @@ namespace ZB.MOM.WW.Secrets.Tests.Cli.Interactive;
|
|||||||
/// (KEK unresolvable → degraded session that still lists metadata), the operator-override upgrade, and
|
/// (KEK unresolvable → degraded session that still lists metadata), the operator-override upgrade, and
|
||||||
/// the SQL-Server-with-unresolved-secret-ref fall-back to the local store.
|
/// the SQL-Server-with-unresolved-secret-ref fall-back to the local store.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Collection("Process environment")]
|
||||||
public sealed class SecretsSessionFactoryTests : IDisposable
|
public sealed class SecretsSessionFactoryTests : IDisposable
|
||||||
{
|
{
|
||||||
private readonly string _dir =
|
private readonly string _dir =
|
||||||
|
|||||||
+1
@@ -12,6 +12,7 @@ namespace ZB.MOM.WW.Secrets.Tests.DependencyInjection;
|
|||||||
/// core: every seam resolves, a real secret round-trips through the composed graph, and a missing
|
/// core: every seam resolves, a real secret round-trips through the composed graph, and a missing
|
||||||
/// master key fails closed.
|
/// master key fails closed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Collection("Process environment")]
|
||||||
public sealed class AddZbSecretsTests
|
public sealed class AddZbSecretsTests
|
||||||
{
|
{
|
||||||
private static string NewTempDbPath() =>
|
private static string NewTempDbPath() =>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using ZB.MOM.WW.Secrets.MasterKey;
|
|||||||
|
|
||||||
namespace ZB.MOM.WW.Secrets.Tests.MasterKey;
|
namespace ZB.MOM.WW.Secrets.Tests.MasterKey;
|
||||||
|
|
||||||
|
[Collection("Process environment")]
|
||||||
public class MasterKeyProviderTests
|
public class MasterKeyProviderTests
|
||||||
{
|
{
|
||||||
// ---- Environment ----------------------------------------------------------------------
|
// ---- Environment ----------------------------------------------------------------------
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
namespace ZB.MOM.WW.Secrets.Tests;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Serializes every test class that mutates process environment variables. setenv/getenv operate
|
||||||
|
/// on the single process-wide environ, which is not safe under concurrent mutation on glibc —
|
||||||
|
/// unique variable names do not remove the race, only serialization does. Classes that never
|
||||||
|
/// touch the environment stay fully parallel.
|
||||||
|
/// </summary>
|
||||||
|
[CollectionDefinition("Process environment", DisableParallelization = true)]
|
||||||
|
public sealed class ProcessEnvironmentCollection;
|
||||||
Reference in New Issue
Block a user