fix(siteruntime): decode List value to typed array before DCL write (OPC UA array write path)
This commit is contained in:
+32
-8
@@ -1,20 +1,44 @@
|
||||
using System.Collections.Generic;
|
||||
using Opc.Ua;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.DataConnectionLayer.Tests.Adapters;
|
||||
|
||||
/// <summary>
|
||||
/// MV-8: the OPC UA WRITE path (<see cref="RealOpcUaClient.WriteValueAsync"/>)
|
||||
/// wraps the outgoing value in <c>new Variant(value)</c> and lets the OPC
|
||||
/// Foundation SDK serialize it. For a structured multi-value (List) attribute
|
||||
/// the value handed down is a CLR array. These tests assert that the load-bearing
|
||||
/// step — wrapping an array in a <see cref="Variant"/> — succeeds without
|
||||
/// throwing, which is what the write path relies on (no separate array handling
|
||||
/// is required in our code). A full device round-trip needs a live server and is
|
||||
/// covered by the live OPC UA browse/read smoke tests.
|
||||
/// SCOPE: these tests cover ONLY the SDK-level building block the write path
|
||||
/// relies on — that <c>new Variant(collection)</c> wraps a CLR array / list as a
|
||||
/// typed array <see cref="Variant"/> (ValueRank = OneDimension) without throwing.
|
||||
/// They are NOT an end-to-end test of the runtime write flow: they feed a
|
||||
/// hand-built collection straight into <see cref="Variant"/>, bypassing the
|
||||
/// InstanceActor decode step that produces that collection.
|
||||
///
|
||||
/// The END-TO-END flow — a script's canonical JSON list string being DECODED to a
|
||||
/// typed <c>List<T></c> before the <c>WriteTagRequest</c> reaches the DCL
|
||||
/// (so OPC UA writes an array node, not a String scalar) — is covered by
|
||||
/// <c>InstanceActorTests.InstanceActor_DataSourcedListWrite_SendsTypedArrayToDcl_NotJsonString</c>.
|
||||
/// The runtime hands <see cref="RealOpcUaClient.WriteValueAsync"/> a
|
||||
/// <c>List<T></c> (the codec's decode result), which the SDK wraps
|
||||
/// identically to a CLR array — see the <c>List<int></c> case below. A full
|
||||
/// device round-trip needs a live server and is covered by the live OPC UA smoke
|
||||
/// tests.
|
||||
/// </summary>
|
||||
[Trait("Category", "Unit")]
|
||||
public class RealOpcUaClientArrayWriteTests
|
||||
{
|
||||
[Fact]
|
||||
public void Variant_wraps_int_list_as_array_without_throwing()
|
||||
{
|
||||
// The runtime actually hands WriteValueAsync a List<T> (the decode result),
|
||||
// not a raw T[]; assert the SDK wraps it as a typed array all the same.
|
||||
var value = new List<int> { 10, 20, 30 };
|
||||
|
||||
var ex = Record.Exception(() => new Variant(value));
|
||||
|
||||
Assert.Null(ex);
|
||||
var variant = new Variant(value);
|
||||
Assert.Equal(BuiltInType.Int32, variant.TypeInfo.BuiltInType);
|
||||
Assert.Equal(ValueRanks.OneDimension, variant.TypeInfo.ValueRank);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Variant_wraps_int_array_without_throwing()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user