test(alarms): drivable-alarm discovery scan across candidate alarm tags
This commit is contained in:
@@ -335,6 +335,97 @@ public sealed class AlarmSubtagLiveSmokeTests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Discovery run: scans candidate alarm attributes for one whose value
|
||||||
|
/// actually responds to an external write (so it can drive a full
|
||||||
|
/// Raise/Clear lifecycle). Logs each candidate's before/after value and
|
||||||
|
/// InAlarm; does not assert. Runs only with
|
||||||
|
/// <c>MXGATEWAY_RUN_LIVE_MXACCESS_TESTS=1</c>. Side effect: flips any
|
||||||
|
/// writable candidate.
|
||||||
|
/// </summary>
|
||||||
|
[LiveMxAccessFact]
|
||||||
|
public void LiveProbe_FindDrivableAlarm()
|
||||||
|
{
|
||||||
|
Exception? threadException = null;
|
||||||
|
ManualResetEventSlim done = new ManualResetEventSlim(false);
|
||||||
|
Thread thread = new Thread(() =>
|
||||||
|
{
|
||||||
|
try { RunFindDrivable(); }
|
||||||
|
catch (Exception ex) { threadException = ex; }
|
||||||
|
finally { done.Set(); }
|
||||||
|
});
|
||||||
|
thread.IsBackground = false;
|
||||||
|
thread.SetApartmentState(ApartmentState.STA);
|
||||||
|
thread.Start();
|
||||||
|
done.Wait();
|
||||||
|
thread.Join();
|
||||||
|
|
||||||
|
List<string> lines = new List<string>();
|
||||||
|
string? line;
|
||||||
|
while (log.TryDequeue(out line)) { output.WriteLine(line); lines.Add(line); }
|
||||||
|
string logPath = Environment.GetEnvironmentVariable("PROBE_LOG")
|
||||||
|
?? System.IO.Path.Combine(System.IO.Path.GetTempPath(), "alarm-find-drivable.log");
|
||||||
|
try { System.IO.File.WriteAllLines(logPath, lines); } catch { /* best effort */ }
|
||||||
|
if (threadException != null) { throw threadException; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RunFindDrivable()
|
||||||
|
{
|
||||||
|
string[] candidates = new string[]
|
||||||
|
{
|
||||||
|
"TestMachine_001.TestAlarm002",
|
||||||
|
"TestMachine_001.TestAlarm003",
|
||||||
|
"TestMachine_002.TestAlarm001",
|
||||||
|
"TestMachine_003.TestAlarm001",
|
||||||
|
};
|
||||||
|
|
||||||
|
Log("=== Find a drivable alarm ===");
|
||||||
|
MxAccessComObjectFactory factory = new MxAccessComObjectFactory();
|
||||||
|
using LmxSubtagAlarmSource source = new LmxSubtagAlarmSource(factory, clientName: null);
|
||||||
|
|
||||||
|
Dictionary<string, object?> latest =
|
||||||
|
new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
source.ValueChanged += (_, c) =>
|
||||||
|
{
|
||||||
|
latest[c.ItemAddress] = c.Value;
|
||||||
|
Log(string.Format("raw: {0} = {1}", c.ItemAddress, c.Value ?? "<null>"));
|
||||||
|
};
|
||||||
|
|
||||||
|
List<string> toAdvise = new List<string>();
|
||||||
|
foreach (string cand in candidates)
|
||||||
|
{
|
||||||
|
toAdvise.Add(cand);
|
||||||
|
toAdvise.Add(cand + ".InAlarm");
|
||||||
|
}
|
||||||
|
source.Advise(toAdvise);
|
||||||
|
Log("Advised candidates. Pumping ...");
|
||||||
|
PumpFor(TimeSpan.FromSeconds(7));
|
||||||
|
|
||||||
|
foreach (string cand in candidates)
|
||||||
|
{
|
||||||
|
object? before;
|
||||||
|
latest.TryGetValue(cand, out before);
|
||||||
|
bool beforeBool = before is bool bb && bb;
|
||||||
|
Log(string.Format("[{0}] before: value={1} InAlarm={2}",
|
||||||
|
cand, before ?? "<none>", latest.ContainsKey(cand + ".InAlarm") ? latest[cand + ".InAlarm"] : "<none>"));
|
||||||
|
|
||||||
|
Log(string.Format("[{0}] writing {1} ...", cand, !beforeBool));
|
||||||
|
try { source.Write(cand, !beforeBool); }
|
||||||
|
catch (Exception ex) { Log(string.Format("[{0}] write threw: {1}", cand, ex.Message)); continue; }
|
||||||
|
|
||||||
|
PumpFor(TimeSpan.FromSeconds(5));
|
||||||
|
object? after;
|
||||||
|
latest.TryGetValue(cand, out after);
|
||||||
|
bool changed = !Equals(before, after);
|
||||||
|
Log(string.Format("[{0}] after: value={1} InAlarm={2} -> {3}",
|
||||||
|
cand, after ?? "<none>",
|
||||||
|
latest.ContainsKey(cand + ".InAlarm") ? latest[cand + ".InAlarm"] : "<none>",
|
||||||
|
changed ? "DRIVABLE (value changed)" : "not drivable (value held)"));
|
||||||
|
}
|
||||||
|
|
||||||
|
Log("=== Find-drivable scan complete ===");
|
||||||
|
}
|
||||||
|
|
||||||
private void RunSelfDriven()
|
private void RunSelfDriven()
|
||||||
{
|
{
|
||||||
// The discrete alarm's source attribute. Writing its boolean value
|
// The discrete alarm's source attribute. Writing its boolean value
|
||||||
|
|||||||
Reference in New Issue
Block a user