Files
lmxopcua/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/ScriptedAlarms/ScriptedAlarmEngineBudgetWiringTests.cs
T
Joseph Doherty d683b83156 fix(scripting): give scripted-alarm predicates the configured run budget, not 250 ms (lmxopcua#779)
DriverHostActor built ScriptedAlarmEngine without a scriptTimeout, so every
production alarm predicate fell back to TimedScriptEvaluator.DefaultTimeout
(250 ms) while virtual tags and Calculation tags ran on 2 s. History shows no
decision behind it: 250 ms is the generic Phase-7 A.4 default, the VT
evaluator moved to 2 s in F8b (219d10a2) and the alarm engine was simply never
given a value.

- New node-wide Scripting:RunTimeout (default 2 s, clamped to (0, 60 s],
  non-positive -> default, each clamp a startup Warning) on ScriptingOptions.
- The VT evaluator and the alarm engine default to it; DriverHostActor now
  builds the engine through CreateScriptedAlarmEngine, which passes it
  explicitly. Calculation keeps its per-driver runTimeoutMs.
- Docs: ScriptEditor (config table), ScriptedAlarms, VirtualTags.

Tests: ScriptedAlarmEngineBudgetTests (a 600 ms predicate now completes and
activates; default and configured budgets), ScriptedAlarmEngineBudgetWiringTests
(the host-built engine), ScriptingOptionsBindingTests (bind + clamps). The
engine and wiring tests fail with the old 250 ms default restored.

Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
2026-11-09 17:44:35 -05:00

39 lines
1.5 KiB
C#

using Serilog;
using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.Core.ScriptedAlarms;
using ZB.MOM.WW.OtOpcUa.Core.Scripting;
using ZB.MOM.WW.OtOpcUa.Runtime.Drivers;
using ZB.MOM.WW.OtOpcUa.Runtime.ScriptedAlarms;
namespace ZB.MOM.WW.OtOpcUa.Runtime.Tests.ScriptedAlarms;
/// <summary>
/// lmxopcua#779 — the engine the driver host builds for its scripted-alarm host runs predicates on the node's
/// <c>Scripting:RunTimeout</c>, not on the 250 ms Phase-7 default it used to fall back to.
/// </summary>
public sealed class ScriptedAlarmEngineBudgetWiringTests
{
private static readonly ILogger Logger = new LoggerConfiguration().CreateLogger();
[Fact]
public void The_host_built_engine_uses_the_configured_RunTimeout()
{
using var engine = DriverHostActor.CreateScriptedAlarmEngine(
new DependencyMuxTagUpstreamSource(), new InMemoryAlarmStateStore(), Logger,
new ScriptingOptions { RunTimeout = TimeSpan.FromSeconds(5) });
engine.ScriptTimeout.ShouldBe(TimeSpan.FromSeconds(5));
}
[Fact]
public void With_no_Scripting_options_the_host_built_engine_gets_the_2s_default_not_250ms()
{
using var engine = DriverHostActor.CreateScriptedAlarmEngine(
new DependencyMuxTagUpstreamSource(), new InMemoryAlarmStateStore(), Logger, scripting: null);
engine.ScriptTimeout.ShouldBe(TimeSpan.FromSeconds(2));
engine.ScriptTimeout.ShouldNotBe(TimedScriptEvaluator<AlarmPredicateContext, bool>.DefaultTimeout);
}
}