test: #871 fix two hosted-CI races that failed master runs 1218-1220

- MeshPskProviderRefreshTests: GatedResolver.Entered was set by the priming
  refresh and never reset, so Wait() returned before the held refresh reached
  the store and the mid-refresh call-count snapshot raced its increment
  (expected 1, was 2). Hold() now resets it.
- FailedCredentialLockoutTests all-bad burst: the 15 waiters could queue
  before a slot holder ran the increment after BeginAsync (authenticated 0
  vs 5). The wait now covers both conditions; the security assertions are
  unchanged.

Both looped 20x locally, 0 failures.

Claude-Session: https://claude.ai/code/session_01GT67AD99zQQqpLCVm3p7xk
This commit is contained in:
Joseph Doherty
2026-11-11 15:09:20 -05:00
parent 71b3b7f35f
commit 9aaab9ee42
2 changed files with 10 additions and 2 deletions
@@ -232,7 +232,13 @@ public sealed class MeshPskProviderRefreshTests
public int Calls => Volatile.Read(ref _calls);
public ManualResetEventSlim Entered { get; } = new();
public void Hold() => _gate = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
// Reset Entered too: the priming refresh already set it, so without the reset Wait() returned before the
// held call had even reached the store and the call-count snapshot raced its increment (hosted-CI flake).
public void Hold()
{
Entered.Reset();
_gate = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
}
public void Release() => _gate?.TrySetResult();
public async Task<string?> GetAsync(SecretName name, CancellationToken ct)
@@ -162,7 +162,9 @@ public sealed class FailedCredentialLockoutTests
lockout.Complete(Client, succeeded: false);
}, Ct)).ToArray();
await WaitUntilAsync(() => lockout.WaitingCount(Client) == 15);
// Wait for the slot holders' increments too: the 15 waiters can queue before a slot holder's thread has run
// the line after BeginAsync, which read authenticated == 0 on the 2-core hosted runner.
await WaitUntilAsync(() => lockout.WaitingCount(Client) == 15 && Volatile.Read(ref authenticated) == 5);
authenticated.ShouldBe(5);
release.SetResult();
await Task.WhenAll(attempts);