test(opcua-client): replace fixed delays in the ConditionRefresh wire test with ordering barriers (lmxopcua#764)
v2-ci / unit-tests (push) Has been cancelled
v2-ci / unit-tests (push) Has been cancelled
The 1500 ms pre-control and 500 ms trailing sleeps are gone. ConditionRefresh completes server-side before SubscribeAlarmsAsync returns, so refresh events queue ahead of the control Acknowledge; a trailing message-change barrier event is projected and awaited (bounded 10 s poll) so any stray event must arrive before it. The assertion is now the exact sequence [Acknowledge, Unspecified], no weaker than before. Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
This commit is contained in:
+12
-4
@@ -310,19 +310,27 @@ public sealed class OpcUaClientDriverWireTests
|
||||
var before = Seen().Length;
|
||||
await drv.UnsubscribeAlarmsAsync(first, ct);
|
||||
await drv.SubscribeAlarmsAsync([AlarmRef], ct);
|
||||
await Task.Delay(1500, ct); // let the second refresh's events land before the control transition
|
||||
// No sleep: ConditionRefresh has completed server-side when SubscribeAlarmsAsync returns, so its events
|
||||
// are already queued on the subscription AHEAD of anything projected below. A re-delivery would
|
||||
// therefore surface before the control events and be caught by the exact-sequence assertion.
|
||||
|
||||
// Positive control: an upstream acknowledge arrives as exactly one Acknowledge, after which nothing else.
|
||||
rig.Project(native: true, new AlarmConditionSnapshot(Active: true, Acknowledged: true, Confirmed: true,
|
||||
Enabled: true, AlarmShelvingKind.Unshelved, 800, "already hot"));
|
||||
await RecordedEvents.WaitUntilAsync(() => Seen().Any(e => e.Kind == AlarmTransitionKind.Acknowledge));
|
||||
await Task.Delay(500, ct);
|
||||
// Trailing barrier instead of a quiet period: a further, distinguishable upstream change (new message) is
|
||||
// projected after the Acknowledge and awaited. Events reach the driver in queue order, so anything stray
|
||||
// that was going to follow the Acknowledge must arrive before this marker and is caught below.
|
||||
rig.Project(native: true, new AlarmConditionSnapshot(Active: true, Acknowledged: true, Confirmed: true,
|
||||
Enabled: true, AlarmShelvingKind.Unshelved, 800, "barrier"));
|
||||
await RecordedEvents.WaitUntilAsync(() => Seen().Any(e => e.Message == "barrier"));
|
||||
// #728: record each event's full shape on failure, not only its Kind — the extra Unspecified that failed CI
|
||||
// could be a changed message/severity, a non-condition event or a quality-only annotation, and the Kind alone
|
||||
// cannot tell them apart.
|
||||
var after = Seen().Skip(before).ToArray();
|
||||
after.Select(e => e.Kind).ShouldBe([AlarmTransitionKind.Acknowledge],
|
||||
"the second refresh re-delivered an unchanged state and must have emitted nothing; events after the " +
|
||||
after.Select(e => e.Kind).ShouldBe([AlarmTransitionKind.Acknowledge, AlarmTransitionKind.Unspecified],
|
||||
"the second refresh re-delivered an unchanged state and must have emitted nothing (only the Acknowledge " +
|
||||
"and the trailing barrier's message change are expected); events after the " +
|
||||
"resubscribe: " + string.Join(" | ", after.Select(Describe)));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user