feat(ablegacy): resolve equipment-tag refs (read + write) via EquipmentTagRefResolver

This commit is contained in:
Joseph Doherty
2026-06-13 11:23:42 -04:00
parent 9d49cb7bbe
commit e2ea720c08
3 changed files with 125 additions and 2 deletions
@@ -0,0 +1,63 @@
using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
using ZB.MOM.WW.OtOpcUa.Driver.AbLegacy;
namespace ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests;
[Trait("Category", "Unit")]
public sealed class AbLegacyEquipmentTagTests
{
[Fact]
public void Parses_equipment_tagconfig_into_a_transient_definition()
{
var json = """{"deviceHostAddress":"ab://10.0.0.5/1,0","address":"N7:0","dataType":"Int"}""";
AbLegacyEquipmentTagParser.TryParse(json, out var def).ShouldBeTrue();
def!.Name.ShouldBe(json);
def.Address.ShouldBe("N7:0");
def.DataType.ShouldBe(AbLegacyDataType.Int);
def.DeviceHostAddress.ShouldBe("ab://10.0.0.5/1,0");
}
[Fact]
public void Rejects_a_non_address_blob()
=> AbLegacyEquipmentTagParser.TryParse("""{"FullName":"x"}""", out _).ShouldBeFalse();
[Fact]
public void Rejects_garbage()
=> AbLegacyEquipmentTagParser.TryParse("not json", out _).ShouldBeFalse();
[Fact]
public void Rejects_address_as_a_json_number()
=> AbLegacyEquipmentTagParser.TryParse(
"""{"address":7,"dataType":"Int"}""", out _).ShouldBeFalse();
[Fact]
public void Rejects_empty_address()
=> AbLegacyEquipmentTagParser.TryParse(
"""{"address":"","dataType":"Int"}""", out _).ShouldBeFalse();
/// <summary>
/// End-to-end driver-level proof: an AbLegacy driver with NO authored tags can still read an
/// equipment-tag ref (the raw TagConfig JSON) — the resolver parses it into a transient
/// definition and the read goes to the fake runtime instead of returning BadNodeIdUnknown.
/// </summary>
[Fact]
public async Task Driver_resolves_an_equipment_ref_and_reads_instead_of_BadNodeIdUnknown()
{
var json = """{"deviceHostAddress":"ab://10.0.0.5/1,0","address":"N7:0","dataType":"Int"}""";
var factory = new FakeAbLegacyTagFactory { Customise = p => new FakeAbLegacyTag(p) { Value = 4242 } };
var drv = new AbLegacyDriver(new AbLegacyDriverOptions
{
Devices = [new AbLegacyDeviceOptions("ab://10.0.0.5/1,0")],
Tags = [],
}, "ablegacy-eq", factory);
await drv.InitializeAsync("{}", CancellationToken.None);
var r = await drv.ReadAsync([json], CancellationToken.None);
r[0].StatusCode.ShouldBe(AbLegacyStatusMapper.Good);
r[0].StatusCode.ShouldNotBe(AbLegacyStatusMapper.BadNodeIdUnknown);
r[0].Value.ShouldBe(4242);
}
}