fix(worker): resilient failover switch; FIPS-safe synthetic GUID; dup-reference guard + tests (Worker-026..028, Worker.Tests-031..033)

This commit is contained in:
Joseph Doherty
2026-06-15 02:56:15 -04:00
parent ddf2d84fbc
commit cebe67e9bd
8 changed files with 584 additions and 20 deletions
@@ -24,4 +24,43 @@ public sealed class SyntheticAlarmGuidTests
[Fact]
public void Reference_ProducesNonEmptyGuid() =>
Assert.NotEqual(Guid.Empty, SyntheticAlarmGuid.ForReference("A.B.C"));
/// <summary>
/// Verifies the empty string still derives a non-empty GUID. The length
/// fold in the derivation prevents a degenerate all-zero (Guid.Empty)
/// result, which would collide with the unset-record default downstream.
/// </summary>
[Fact]
public void EmptyReference_ProducesNonEmptyGuid() =>
Assert.NotEqual(Guid.Empty, SyntheticAlarmGuid.ForReference(string.Empty));
/// <summary>
/// Worker-027 regression: <see cref="SyntheticAlarmGuid.ForReference"/>
/// must derive its GUID without routing through
/// <see cref="System.Security.Cryptography"/>, because on net48
/// <c>MD5.Create()</c> throws under the Windows FIPS-compliance policy.
/// This test enables the per-AppContext FIPS-enforcement switch (which the
/// managed crypto factories honour) and asserts the derivation still
/// succeeds deterministically — a regression that reintroduced a FIPS-gated
/// provider would throw here instead of returning a stable GUID.
/// </summary>
[Fact]
public void ForReference_UnderFipsEnforcement_DoesNotThrowAndStaysDeterministic()
{
const string switchName = "Switch.System.Security.Cryptography.UseLegacyFipsThrow";
bool original = AppContext.TryGetSwitch(switchName, out bool value) && value;
AppContext.SetSwitch(switchName, true);
try
{
Guid first = SyntheticAlarmGuid.ForReference("Galaxy!Area.Tank01.Level.HiHi");
Guid second = SyntheticAlarmGuid.ForReference("Galaxy!Area.Tank01.Level.HiHi");
Assert.NotEqual(Guid.Empty, first);
Assert.Equal(first, second);
}
finally
{
AppContext.SetSwitch(switchName, original);
}
}
}