Files
lmxopcua/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests/AbLegacyBitRmwTests.cs
Joseph Doherty bd6c0b4d3d docs: complete XML doc comments via fixdocs (2757 to 131 findings)
Add missing <returns>/<param>/<summary>/<typeparam> tags and clean up
misused inheritdoc across 481 files so the documented API surface is
complete. Documentation-only (zero code lines changed). The 131 remaining
findings are inheritdoc-style warnings deliberately left to preserve
hand-written implementation rationale (plan-decision notes, race-condition
explanations).
2026-06-03 12:34:34 -04:00

113 lines
4.8 KiB
C#

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 AbLegacyBitRmwTests
{
/// <summary>Verifies that setting a bit reads the parent word, ORs the bit, and writes back.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task Bit_set_reads_parent_word_ORs_bit_writes_back()
{
var factory = new FakeAbLegacyTagFactory
{
Customise = p => new FakeAbLegacyTag(p) { Value = (short)0b0001 },
};
var drv = new AbLegacyDriver(new AbLegacyDriverOptions
{
Devices = [new AbLegacyDeviceOptions("ab://10.0.0.5/1,0")],
Tags = [new AbLegacyTagDefinition("Flag3", "ab://10.0.0.5/1,0", "N7:0/3", AbLegacyDataType.Bit)],
Probe = new AbLegacyProbeOptions { Enabled = false },
}, "drv-1", factory);
await drv.InitializeAsync("{}", CancellationToken.None);
var results = await drv.WriteAsync(
[new WriteRequest("Flag3", true)], CancellationToken.None);
results.Single().StatusCode.ShouldBe(AbLegacyStatusMapper.Good);
factory.Tags.ShouldContainKey("N7:0"); // parent word runtime created
Convert.ToInt32(factory.Tags["N7:0"].Value).ShouldBe(0b1001);
}
/// <summary>Verifies that clearing a bit preserves other bits in the word.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task Bit_clear_preserves_other_bits_in_N_file_word()
{
var factory = new FakeAbLegacyTagFactory
{
Customise = p => new FakeAbLegacyTag(p) { Value = unchecked((short)0xFFFF) },
};
var drv = new AbLegacyDriver(new AbLegacyDriverOptions
{
Devices = [new AbLegacyDeviceOptions("ab://10.0.0.5/1,0")],
Tags = [new AbLegacyTagDefinition("F", "ab://10.0.0.5/1,0", "N7:0/3", AbLegacyDataType.Bit)],
Probe = new AbLegacyProbeOptions { Enabled = false },
}, "drv-1", factory);
await drv.InitializeAsync("{}", CancellationToken.None);
await drv.WriteAsync([new WriteRequest("F", false)], CancellationToken.None);
Convert.ToInt32(factory.Tags["N7:0"].Value).ShouldBe(unchecked((short)0xFFF7));
}
/// <summary>Verifies that concurrent bit writes to the same word compose correctly.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task Concurrent_bit_writes_to_same_word_compose_correctly()
{
var factory = new FakeAbLegacyTagFactory
{
Customise = p => new FakeAbLegacyTag(p) { Value = (short)0 },
};
var tags = Enumerable.Range(0, 8)
.Select(b => new AbLegacyTagDefinition($"Bit{b}", "ab://10.0.0.5/1,0", $"N7:0/{b}", AbLegacyDataType.Bit))
.ToArray();
var drv = new AbLegacyDriver(new AbLegacyDriverOptions
{
Devices = [new AbLegacyDeviceOptions("ab://10.0.0.5/1,0")],
Tags = tags,
Probe = new AbLegacyProbeOptions { Enabled = false },
}, "drv-1", factory);
await drv.InitializeAsync("{}", CancellationToken.None);
await Task.WhenAll(Enumerable.Range(0, 8).Select(b =>
drv.WriteAsync([new WriteRequest($"Bit{b}", true)], CancellationToken.None)));
Convert.ToInt32(factory.Tags["N7:0"].Value).ShouldBe(0xFF);
}
/// <summary>Verifies that repeated bit writes reuse the parent word runtime.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task Repeat_bit_writes_reuse_parent_runtime()
{
var factory = new FakeAbLegacyTagFactory
{
Customise = p => new FakeAbLegacyTag(p) { Value = (short)0 },
};
var drv = new AbLegacyDriver(new AbLegacyDriverOptions
{
Devices = [new AbLegacyDeviceOptions("ab://10.0.0.5/1,0")],
Tags =
[
new AbLegacyTagDefinition("Bit0", "ab://10.0.0.5/1,0", "N7:0/0", AbLegacyDataType.Bit),
new AbLegacyTagDefinition("Bit5", "ab://10.0.0.5/1,0", "N7:0/5", AbLegacyDataType.Bit),
],
Probe = new AbLegacyProbeOptions { Enabled = false },
}, "drv-1", factory);
await drv.InitializeAsync("{}", CancellationToken.None);
await drv.WriteAsync([new WriteRequest("Bit0", true)], CancellationToken.None);
await drv.WriteAsync([new WriteRequest("Bit5", true)], CancellationToken.None);
factory.Tags["N7:0"].InitializeCount.ShouldBe(1);
factory.Tags["N7:0"].WriteCount.ShouldBe(2);
Convert.ToInt32(factory.Tags["N7:0"].Value).ShouldBe(0x21); // bits 0 + 5
}
}