using System.Text.Json;
using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.Driver.Mqtt;
namespace ZB.MOM.WW.OtOpcUa.Driver.Mqtt.Tests;
public sealed class MqttDriverOptionsTests
{
///
/// The production instance, not a look-alike copy. A local clone would keep passing after
/// lost its JsonStringEnumConverter — testing the copy
/// instead of the thing every seam actually parses through.
///
private static readonly JsonSerializerOptions J = MqttJson.Options;
[Fact]
public void Deserialize_SparkplugConfig_ReadsModeAndSubObject()
{
const string json = """
{ "host":"10.100.0.35","port":8883,"useTls":true,"mode":"SparkplugB",
"sparkplug":{"groupId":"Plant1","hostId":"h1","requestRebirthOnGap":true} }
""";
var o = JsonSerializer.Deserialize(json, J)!;
o.Mode.ShouldBe(MqttMode.SparkplugB);
o.UseTls.ShouldBeTrue();
o.Sparkplug!.GroupId.ShouldBe("Plant1");
o.Plain.ShouldBeNull();
}
[Fact]
public void Serialize_WritesEnumsAsNames_NotOrdinals()
{
var s = JsonSerializer.Serialize(new MqttDriverOptions { Mode = MqttMode.Plain }, J);
s.ShouldContain("\"Plain\"");
s.ShouldNotContain("\"mode\":0");
}
// Pins the plan's cross-cutting rule ("never ship anonymous/public-broker defaults") as an
// executable assertion — nothing else in this suite fails if UseTls / AllowUntrustedServerCertificate
// (or the §5.1 numeric defaults) get flipped by an unrelated edit.
[Fact]
public void Defaults_SecurityCriticalKnobs_MatchPlan()
{
var o = new MqttDriverOptions();
o.UseTls.ShouldBeTrue();
o.AllowUntrustedServerCertificate.ShouldBeFalse();
o.ConnectTimeoutSeconds.ShouldBe(15);
o.ReconnectMinBackoffSeconds.ShouldBe(1);
o.ReconnectMaxBackoffSeconds.ShouldBe(30);
}
// The production case: an operator-authored config blob that simply doesn't mention TLS must
// never silently deserialize into an insecure instance.
[Fact]
public void Deserialize_PartialJsonOmittingTlsKnobs_KeepsSecureDefaults()
{
const string json = """{ "host":"10.100.0.35","port":8883 }""";
var o = JsonSerializer.Deserialize(json, J)!;
o.UseTls.ShouldBeTrue();
o.AllowUntrustedServerCertificate.ShouldBeFalse();
}
[Fact]
public void ToString_DoesNotLeakPassword()
{
var o = new MqttDriverOptions { Password = "hunter2-supersecret" };
var s = o.ToString();
s.ShouldNotContain("hunter2-supersecret");
s.ShouldContain("***");
}
}