fix(tests): stabilize three flaky tests under parallel full-solution load
#1 EventPumpBoundedChannelTests.Tags_metrics_with_client_name_for_multi_driver_hosts: Replace fixed Task.Delay(100) with a poll-until-condition loop (5 s timeout, 25 ms poll) so the test waits until the galaxy.events.received measurement for galaxy.client=Driver-X actually lands in the listener. Also adds lock(captured) in the MeterListener callback and at all reads, since Counter.Add() fires the callback on the RunAsync background thread. #2 VirtualTagEngineTests.Upstream_change_triggers_cascade_through_two_levels: After waiting for B=15.0, also await WaitForConditionAsync for C=30.0 before asserting C. The cascade runs B then C sequentially under the _evalGate semaphore; the prior code could read C while its evaluation had not yet acquired the gate. #3 ThreeUserInteropMatrixTests.Admin_Resolves_All_Five_Groups_From_LDAP: Wrap the AuthenticateAsync call in a 15 s linked CancellationTokenSource with one retry so transient GLAuth latency spikes under parallel test load do not cause a CancellationToken expiry before the LDAP bind/search complete. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -207,9 +207,31 @@ public sealed class ThreeUserInteropMatrixTests
|
||||
// pins the resolution explicitly in strict mode.
|
||||
if (!GlauthReachable()) Assert.Skip("GLAuth unreachable at localhost:3893.");
|
||||
|
||||
var auth = await NewAuthenticator().AuthenticateAsync("admin", "admin123", TestContext.Current.CancellationToken);
|
||||
// Under parallel full-solution test load, GLAuth on localhost can be slow to
|
||||
// respond; use a generous per-call timeout independent of xUnit's test runner
|
||||
// deadline so we don't race against the runner's own CancellationToken, and
|
||||
// retry once on timeout to absorb transient latency spikes.
|
||||
const int LdapTimeoutSeconds = 15;
|
||||
UserAuthResult? auth = null;
|
||||
for (var attempt = 0; attempt < 2; attempt++)
|
||||
{
|
||||
using var cts = CancellationTokenSource.CreateLinkedTokenSource(
|
||||
TestContext.Current.CancellationToken);
|
||||
cts.CancelAfter(TimeSpan.FromSeconds(LdapTimeoutSeconds));
|
||||
try
|
||||
{
|
||||
auth = await NewAuthenticator().AuthenticateAsync("admin", "admin123", cts.Token);
|
||||
break; // success — no retry needed
|
||||
}
|
||||
catch (OperationCanceledException) when (!TestContext.Current.CancellationToken.IsCancellationRequested)
|
||||
{
|
||||
if (attempt == 1) throw; // second attempt also timed out — let it fail
|
||||
// First attempt timed out under load; retry once with a fresh token.
|
||||
}
|
||||
}
|
||||
|
||||
auth.Success.ShouldBeTrue();
|
||||
auth.ShouldNotBeNull();
|
||||
auth!.Success.ShouldBeTrue();
|
||||
auth.Groups.ShouldContain("ReadOnly");
|
||||
auth.Groups.ShouldContain("WriteOperate");
|
||||
auth.Groups.ShouldContain("WriteTune");
|
||||
|
||||
Reference in New Issue
Block a user