Merge #608/#602/#596: stale WaveC TODOs resolved, FOCAS/TwinCAT factory logging, Modbus health asymmetry documented, AbCip browsePageDelayMs field, Device1 by-design
Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
using ZB.MOM.WW.OtOpcUa.Core.Hosting;
|
||||
using ZB.MOM.WW.OtOpcUa.Driver.FOCAS;
|
||||
using ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Wire;
|
||||
|
||||
namespace ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Tests;
|
||||
|
||||
/// <summary>#602 CONV-3: the FOCAS factory hands the host logger factory to the driver and its wire client.</summary>
|
||||
[Trait("Category", "Unit")]
|
||||
public sealed class FocasFactoryLoggerTests
|
||||
{
|
||||
private sealed class RecordingLoggerFactory : ILoggerFactory
|
||||
{
|
||||
public List<string> Categories { get; } = [];
|
||||
public ILogger CreateLogger(string categoryName)
|
||||
{
|
||||
lock (Categories) Categories.Add(categoryName);
|
||||
return Microsoft.Extensions.Logging.Abstractions.NullLogger.Instance;
|
||||
}
|
||||
public void AddProvider(ILoggerProvider provider) { }
|
||||
public void Dispose() { }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Registered_factory_creates_driver_and_wire_client_loggers_from_the_host_factory()
|
||||
{
|
||||
var lf = new RecordingLoggerFactory();
|
||||
var registry = new DriverFactoryRegistry();
|
||||
FocasDriverFactoryExtensions.Register(registry, lf);
|
||||
|
||||
var drv = registry.TryGet(FocasDriverFactoryExtensions.DriverTypeName)!("drv-1", "{}");
|
||||
|
||||
drv.ShouldBeOfType<FocasDriver>();
|
||||
lf.Categories.ShouldContain(typeof(FocasDriver).FullName!);
|
||||
lf.Categories.ShouldContain(typeof(FocasWireClient).FullName!);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Registering_without_a_logger_factory_still_works()
|
||||
{
|
||||
var registry = new DriverFactoryRegistry();
|
||||
FocasDriverFactoryExtensions.Register(registry);
|
||||
registry.TryGet(FocasDriverFactoryExtensions.DriverTypeName)!("drv-1", "{}").ShouldBeOfType<FocasDriver>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
using ZB.MOM.WW.OtOpcUa.Core.Hosting;
|
||||
|
||||
namespace ZB.MOM.WW.OtOpcUa.Driver.TwinCAT.Tests;
|
||||
|
||||
/// <summary>#602 CONV-3: the TwinCAT factory hands the host logger factory to the driver.</summary>
|
||||
[Trait("Category", "Unit")]
|
||||
public sealed class TwinCATFactoryLoggerTests
|
||||
{
|
||||
private sealed class RecordingLoggerFactory : ILoggerFactory
|
||||
{
|
||||
public List<string> Categories { get; } = [];
|
||||
public ILogger CreateLogger(string categoryName)
|
||||
{
|
||||
lock (Categories) Categories.Add(categoryName);
|
||||
return Microsoft.Extensions.Logging.Abstractions.NullLogger.Instance;
|
||||
}
|
||||
public void AddProvider(ILoggerProvider provider) { }
|
||||
public void Dispose() { }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Registered_factory_creates_the_driver_logger_from_the_host_factory()
|
||||
{
|
||||
var lf = new RecordingLoggerFactory();
|
||||
var registry = new DriverFactoryRegistry();
|
||||
TwinCATDriverFactoryExtensions.Register(registry, lf);
|
||||
|
||||
var drv = registry.TryGet(TwinCATDriverFactoryExtensions.DriverTypeName)!("drv-1", "{}");
|
||||
|
||||
drv.ShouldBeOfType<TwinCATDriver>();
|
||||
lf.Categories.ShouldContain(typeof(TwinCATDriver).FullName!);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Registering_without_a_logger_factory_still_works()
|
||||
{
|
||||
var registry = new DriverFactoryRegistry();
|
||||
TwinCATDriverFactoryExtensions.Register(registry);
|
||||
registry.TryGet(TwinCATDriverFactoryExtensions.DriverTypeName)!("drv-1", "{}").ShouldBeOfType<TwinCATDriver>();
|
||||
}
|
||||
}
|
||||
@@ -306,4 +306,26 @@ public sealed class AbCipDriverPageFormSerializationTests
|
||||
opts.ShouldNotBeNull();
|
||||
opts.Devices[0].HostAddress.ShouldBe("ab://10.0.0.1/1,0");
|
||||
}
|
||||
|
||||
// ---- #596: browsePageDelayMs is form-authorable, reaches the factory, and unknown keys survive ----
|
||||
|
||||
[Fact]
|
||||
public void BrowsePageDelayMs_is_loaded_edited_and_bound_by_the_factory_without_dropping_unknown_keys()
|
||||
{
|
||||
var original = """{"browsePageDelayMs":40,"futureOption":"keep-me","devices":[{"hostAddress":"ab://10.0.0.1/1,0"}]}""";
|
||||
var loaded = AbCipDriverForm.TryDeserialize(original)!;
|
||||
var form = AbCipDriverForm.FormModel.FromJson(original, loaded);
|
||||
form.BrowsePageDelayMs.ShouldBe(40); // the form SEES the factory-keyed value
|
||||
|
||||
var untouched = AbCipDriverForm.Serialize(form.ToOptions(loaded.Devices), original);
|
||||
ZB.MOM.WW.OtOpcUa.Driver.AbCip.AbCipDriverFactoryExtensions.ParseOptions("t", untouched)
|
||||
.BrowsePageDelay.ShouldBe(TimeSpan.FromMilliseconds(40));
|
||||
|
||||
form.BrowsePageDelayMs = 125;
|
||||
var saved = AbCipDriverForm.Serialize(form.ToOptions(loaded.Devices), original);
|
||||
ZB.MOM.WW.OtOpcUa.Driver.AbCip.AbCipDriverFactoryExtensions.ParseOptions("t", saved)
|
||||
.BrowsePageDelay.ShouldBe(TimeSpan.FromMilliseconds(125));
|
||||
saved.ShouldContain("futureOption");
|
||||
System.Text.Json.Nodes.JsonNode.Parse(saved)!.AsObject().ContainsKey("browsePageDelay").ShouldBeFalse();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user