test(commons): failing tests for OpcUaEndpointConfigSerializer

This commit is contained in:
Joseph Doherty
2026-05-12 00:38:56 -04:00
parent b16606d97e
commit 2220bfcf58

View File

@@ -0,0 +1,163 @@
using ScadaLink.Commons.Serialization;
using ScadaLink.Commons.Types.DataConnections;
namespace ScadaLink.Commons.Tests.Types.DataConnections;
public class OpcUaEndpointConfigSerializerTests
{
[Fact]
public void Serialize_TypedRoundtrip_PreservesAllFields()
{
var original = new OpcUaEndpointConfig
{
EndpointUrl = "opc.tcp://plant-a:4840",
SecurityMode = OpcUaSecurityMode.SignAndEncrypt,
AutoAcceptUntrustedCerts = false,
SessionTimeoutMs = 90000,
OperationTimeoutMs = 20000,
PublishingIntervalMs = 500,
SamplingIntervalMs = 250,
QueueSize = 50,
KeepAliveCount = 5,
LifetimeCount = 15,
MaxNotificationsPerPublish = 200,
Heartbeat = new OpcUaHeartbeatConfig { TagPath = "Sensors.HB", MaxSilenceSeconds = 60 }
};
var json = OpcUaEndpointConfigSerializer.Serialize(original);
var (round, isLegacy) = OpcUaEndpointConfigSerializer.Deserialize(json);
Assert.False(isLegacy);
Assert.Equal(original.EndpointUrl, round.EndpointUrl);
Assert.Equal(original.SecurityMode, round.SecurityMode);
Assert.Equal(original.AutoAcceptUntrustedCerts, round.AutoAcceptUntrustedCerts);
Assert.Equal(original.SessionTimeoutMs, round.SessionTimeoutMs);
Assert.Equal(original.OperationTimeoutMs, round.OperationTimeoutMs);
Assert.Equal(original.PublishingIntervalMs, round.PublishingIntervalMs);
Assert.Equal(original.SamplingIntervalMs, round.SamplingIntervalMs);
Assert.Equal(original.QueueSize, round.QueueSize);
Assert.Equal(original.KeepAliveCount, round.KeepAliveCount);
Assert.Equal(original.LifetimeCount, round.LifetimeCount);
Assert.Equal(original.MaxNotificationsPerPublish, round.MaxNotificationsPerPublish);
Assert.NotNull(round.Heartbeat);
Assert.Equal("Sensors.HB", round.Heartbeat!.TagPath);
Assert.Equal(60, round.Heartbeat.MaxSilenceSeconds);
}
[Fact]
public void Serialize_UsesCamelCase()
{
var config = new OpcUaEndpointConfig { EndpointUrl = "opc.tcp://x:4840" };
var json = OpcUaEndpointConfigSerializer.Serialize(config);
Assert.Contains("\"endpointUrl\"", json);
Assert.DoesNotContain("\"EndpointUrl\"", json);
}
[Fact]
public void Serialize_SecurityModeAsCamelCaseString()
{
var config = new OpcUaEndpointConfig { SecurityMode = OpcUaSecurityMode.SignAndEncrypt };
var json = OpcUaEndpointConfigSerializer.Serialize(config);
Assert.Contains("\"securityMode\":\"signAndEncrypt\"", json);
}
[Fact]
public void Deserialize_NullOrEmpty_ReturnsDefaults()
{
var (config1, legacy1) = OpcUaEndpointConfigSerializer.Deserialize(null);
var (config2, legacy2) = OpcUaEndpointConfigSerializer.Deserialize("");
var (config3, legacy3) = OpcUaEndpointConfigSerializer.Deserialize(" ");
Assert.False(legacy1);
Assert.False(legacy2);
Assert.False(legacy3);
Assert.Equal("", config1.EndpointUrl);
Assert.Equal(60000, config1.SessionTimeoutMs);
Assert.Null(config1.Heartbeat);
}
[Fact]
public void Deserialize_LegacyFlatDict_IsLegacyTrue_PopulatesFields()
{
var legacyJson = """
{
"endpoint": "opc.tcp://legacy:4840",
"SessionTimeoutMs": "45000",
"SamplingIntervalMs": "500",
"SecurityMode": "Sign",
"AutoAcceptUntrustedCerts": "false",
"HeartbeatTagPath": "Old.Heartbeat",
"HeartbeatMaxSilence": "20"
}
""";
var (config, isLegacy) = OpcUaEndpointConfigSerializer.Deserialize(legacyJson);
Assert.True(isLegacy);
Assert.Equal("opc.tcp://legacy:4840", config.EndpointUrl);
Assert.Equal(45000, config.SessionTimeoutMs);
Assert.Equal(500, config.SamplingIntervalMs);
Assert.Equal(OpcUaSecurityMode.Sign, config.SecurityMode);
Assert.False(config.AutoAcceptUntrustedCerts);
Assert.NotNull(config.Heartbeat);
Assert.Equal("Old.Heartbeat", config.Heartbeat!.TagPath);
Assert.Equal(20, config.Heartbeat.MaxSilenceSeconds);
}
[Fact]
public void Deserialize_LegacyWithEndpointUrlPascalKey_Works()
{
var legacyJson = """{"EndpointUrl":"opc.tcp://x:4840"}""";
var (config, isLegacy) = OpcUaEndpointConfigSerializer.Deserialize(legacyJson);
Assert.True(isLegacy);
Assert.Equal("opc.tcp://x:4840", config.EndpointUrl);
}
[Fact]
public void ToFlatDict_OmitsNullHeartbeat()
{
var config = new OpcUaEndpointConfig { EndpointUrl = "opc.tcp://x:4840" };
var dict = OpcUaEndpointConfigSerializer.ToFlatDict(config);
Assert.Equal("opc.tcp://x:4840", dict["endpoint"]);
Assert.Equal("60000", dict["SessionTimeoutMs"]);
Assert.Equal("None", dict["SecurityMode"]);
Assert.Equal("True", dict["AutoAcceptUntrustedCerts"]);
Assert.False(dict.ContainsKey("HeartbeatTagPath"));
Assert.False(dict.ContainsKey("HeartbeatMaxSilence"));
}
[Fact]
public void ToFlatDict_IncludesHeartbeat_WhenSet()
{
var config = new OpcUaEndpointConfig
{
EndpointUrl = "opc.tcp://x:4840",
Heartbeat = new OpcUaHeartbeatConfig { TagPath = "HB.Tag", MaxSilenceSeconds = 45 }
};
var dict = OpcUaEndpointConfigSerializer.ToFlatDict(config);
Assert.Equal("HB.Tag", dict["HeartbeatTagPath"]);
Assert.Equal("45", dict["HeartbeatMaxSilence"]);
}
[Fact]
public void FromFlatDict_RoundTripsAllKeys()
{
var dict = new Dictionary<string, string>
{
["endpoint"] = "opc.tcp://x:4840",
["SessionTimeoutMs"] = "30000",
["SecurityMode"] = "Sign",
["HeartbeatTagPath"] = "Hb",
["HeartbeatMaxSilence"] = "15"
};
var config = OpcUaEndpointConfigSerializer.FromFlatDict(dict);
Assert.Equal("opc.tcp://x:4840", config.EndpointUrl);
Assert.Equal(30000, config.SessionTimeoutMs);
Assert.Equal(OpcUaSecurityMode.Sign, config.SecurityMode);
Assert.NotNull(config.Heartbeat);
Assert.Equal("Hb", config.Heartbeat!.TagPath);
}
}