test: preserve server SDK 2.0 value security and history contracts
This commit is contained in:
+15
-15
@@ -62,16 +62,16 @@ public sealed class NodeManagerAlarmSourceFieldsTests : IDisposable
|
||||
// EventType — the concrete condition type, so a client reading the FIELD (not just an OfType
|
||||
// where-clause) can resolve the type.
|
||||
condition.EventType.ShouldNotBeNull();
|
||||
condition.EventType.Value.ShouldBe(ObjectTypeIds.OffNormalAlarmType);
|
||||
condition.EventType!.Value.ShouldBe(ObjectTypeIds.OffNormalAlarmType);
|
||||
|
||||
// SourceNode — the condition's own NodeId (it IS the source: no separate value variable exists
|
||||
// for an alarm-bearing raw tag). Equal to ConditionId.
|
||||
condition.SourceNode.ShouldNotBeNull();
|
||||
condition.SourceNode.Value.ShouldBe(new NodeId(RawAlarmPath, rawNs));
|
||||
condition.SourceNode!.Value.ShouldBe(new NodeId(RawAlarmPath, rawNs));
|
||||
|
||||
// SourceName — the RawPath: unique across devices, matching ConditionId/SourceNode.
|
||||
condition.SourceName.ShouldNotBeNull();
|
||||
condition.SourceName.Value.ShouldBe(RawAlarmPath);
|
||||
condition.SourceName!.Value.ShouldBe(RawAlarmPath);
|
||||
|
||||
// The leaf name is NOT lost — it stays on ConditionName.
|
||||
condition.ConditionName!.Value.ShouldBe("HR200");
|
||||
@@ -169,11 +169,11 @@ public sealed class NodeManagerAlarmSourceFieldsTests : IDisposable
|
||||
condition.ShouldNotBeNull();
|
||||
|
||||
condition.ConditionClassId.ShouldNotBeNull();
|
||||
condition.ConditionClassId.Value.ShouldBe(ObjectTypeIds.BaseConditionClassType);
|
||||
condition.ConditionClassId!.Value.ShouldBe(ObjectTypeIds.BaseConditionClassType);
|
||||
|
||||
condition.ConditionClassName.ShouldNotBeNull();
|
||||
condition.ConditionClassName.Value.ShouldNotBeNull();
|
||||
condition.ConditionClassName.Value.Text.ShouldBe("BaseConditionClass");
|
||||
condition.ConditionClassName!.Value.IsNull.ShouldBeFalse();
|
||||
condition.ConditionClassName!.Value.Text.ShouldBe("BaseConditionClass");
|
||||
}
|
||||
|
||||
/// <summary>#475 — a SCRIPTED condition (UNS realm) carries the SAME classification fields: native and scripted
|
||||
@@ -213,8 +213,8 @@ public sealed class NodeManagerAlarmSourceFieldsTests : IDisposable
|
||||
var condition = nm.TryGetAlarmCondition(RawAlarmPath, AddressSpaceRealm.Raw);
|
||||
condition.ShouldNotBeNull();
|
||||
condition.Quality.ShouldNotBeNull();
|
||||
condition.Quality.Value.ShouldBe((StatusCode)StatusCodes.BadWaitingForInitialData);
|
||||
StatusCode.IsGood(condition.Quality.Value).ShouldBeFalse();
|
||||
condition.Quality!.Value.ShouldBe((StatusCode)StatusCodes.BadWaitingForInitialData);
|
||||
StatusCode.IsGood(condition.Quality!.Value).ShouldBeFalse();
|
||||
}
|
||||
|
||||
/// <summary>#477 — a SCRIPTED condition is script-computed and always "live" in v1, so it materialises Good.
|
||||
@@ -233,7 +233,7 @@ public sealed class NodeManagerAlarmSourceFieldsTests : IDisposable
|
||||
var condition = nm.TryGetAlarmCondition("scripted-q", AddressSpaceRealm.Uns);
|
||||
condition.ShouldNotBeNull();
|
||||
condition.Quality.ShouldNotBeNull();
|
||||
StatusCode.IsGood(condition.Quality.Value).ShouldBeTrue();
|
||||
StatusCode.IsGood(condition.Quality!.Value).ShouldBeTrue();
|
||||
}
|
||||
|
||||
/// <summary>#477 — WriteAlarmCondition projects the snapshot's Quality onto the live condition node, so a
|
||||
@@ -258,12 +258,12 @@ public sealed class NodeManagerAlarmSourceFieldsTests : IDisposable
|
||||
|
||||
var condition = nm.TryGetAlarmCondition(RawAlarmPath, AddressSpaceRealm.Raw);
|
||||
condition.ShouldNotBeNull();
|
||||
StatusCode.IsBad(condition.Quality.Value).ShouldBeTrue();
|
||||
StatusCode.IsBad(condition.Quality!.Value).ShouldBeTrue();
|
||||
|
||||
// Recover: a Good snapshot restores Good quality.
|
||||
var goodSnapshot = badSnapshot with { StatusCode = OpcUaStatus.Good };
|
||||
nm.WriteAlarmCondition(RawAlarmPath, goodSnapshot, DateTime.UtcNow, AddressSpaceRealm.Raw);
|
||||
StatusCode.IsGood(condition.Quality.Value).ShouldBeTrue();
|
||||
StatusCode.IsGood(condition.Quality!.Value).ShouldBeTrue();
|
||||
}
|
||||
|
||||
/// <summary>#477 Layer 2 — the dedicated connectivity-quality path sets ONLY the condition's Quality
|
||||
@@ -283,7 +283,7 @@ public sealed class NodeManagerAlarmSourceFieldsTests : IDisposable
|
||||
var condition = nm.TryGetAlarmCondition(RawAlarmPath, AddressSpaceRealm.Raw);
|
||||
condition.ShouldNotBeNull();
|
||||
var severityBefore = condition.Severity!.Value;
|
||||
var messageBefore = condition.Message!.Value?.Text;
|
||||
var messageBefore = condition.Message!.Value.Text;
|
||||
|
||||
// Device comes online → Good.
|
||||
nm.WriteAlarmQuality(RawAlarmPath, OpcUaStatus.Good, DateTime.UtcNow, AddressSpaceRealm.Raw);
|
||||
@@ -291,9 +291,9 @@ public sealed class NodeManagerAlarmSourceFieldsTests : IDisposable
|
||||
|
||||
// Device goes comms-lost → Bad, but severity / message / active-ack state are untouched.
|
||||
nm.WriteAlarmQuality(RawAlarmPath, OpcUaStatus.Bad, DateTime.UtcNow, AddressSpaceRealm.Raw);
|
||||
StatusCode.IsBad(condition.Quality.Value).ShouldBeTrue();
|
||||
condition.Severity.Value.ShouldBe(severityBefore);
|
||||
condition.Message.Value?.Text.ShouldBe(messageBefore);
|
||||
StatusCode.IsBad(condition.Quality!.Value).ShouldBeTrue();
|
||||
condition.Severity!.Value.ShouldBe(severityBefore);
|
||||
condition.Message!.Value.Text.ShouldBe(messageBefore);
|
||||
condition.ActiveState!.Id!.Value.ShouldBeFalse(); // unchanged: annotation only
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user