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:
Joseph Doherty
2026-10-08 06:53:59 -04:00
17 changed files with 192 additions and 50 deletions
@@ -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>();
}
}