Files
lmxopcua/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Ab.Transport.Tests/Logix/SymbolObjectServicesTests.cs
T

75 lines
3.2 KiB
C#

using System.Buffers.Binary;
using System.Text;
using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.Driver.Ab.Transport.Cip;
using ZB.MOM.WW.OtOpcUa.Driver.Ab.Transport.Logix;
using ZB.MOM.WW.OtOpcUa.Driver.Ab.Transport.Tests.Captures;
namespace ZB.MOM.WW.OtOpcUa.Driver.Ab.Transport.Tests.Logix;
public sealed class SymbolObjectServicesTests
{
private static readonly string[] ExpectedNames =
["Motor_Run", "Line1_Count", "Pump_1_Speed", "TestArray", "TestString", "TestSINT", "TestBOOL", "TestREAL", "TestDINT"];
[Fact]
public void Request_matches_capture()
{
// libplctag requests attributes 2,7,8,1 in that order -- same as the brief; no change needed.
var cap = CaptureFile.CipPayload(CaptureFile.Load("logix-tags-listing.hex").First(f => f.FromClient));
SymbolObjectServices.GetInstanceAttributeList(null, 0).ShouldBe(cap);
}
[Fact]
public void Request_with_program_scope_and_start_instance() =>
Convert.ToHexString(SymbolObjectServices.GetInstanceAttributeList("Main", 0x0102)).ShouldBe(
"550A" + "910C" + Convert.ToHexString(Encoding.ASCII.GetBytes("Program:Main"))
+ "206B2500" + "0201" + "0400" + "0200" + "0700" + "0800" + "0100");
[Fact]
public void Captured_reply_entries_have_the_decoder_layout()
{
var reply = CipReply.Parse(CaptureFile.CipPayload(CaptureFile.Load("logix-tags-listing.hex").First(f => !f.FromClient)));
var (entries, last, more) = SymbolObjectServices.ParseListingReply(reply);
more.ShouldBeFalse();
last.ShouldBe(9u);
var names = new List<string>();
var pos = 0;
uint expectedInstance = 1;
while (pos < entries.Length)
{
BinaryPrimitives.ReadUInt32LittleEndian(entries.AsSpan(pos)).ShouldBe(expectedInstance++);
var nameLen = BinaryPrimitives.ReadUInt16LittleEndian(entries.AsSpan(pos + 20));
names.Add(Encoding.ASCII.GetString(entries, pos + 22, nameLen));
pos += 22 + nameLen;
}
names.ShouldBe(ExpectedNames);
}
[Fact]
public void More_flag_follows_status_0x06()
{
var entry = Convert.FromHexString("05000000" + "C400" + "0400" + "00000000" + "00000000" + "00000000" + "0100" + "41");
var reply = new CipReply(0x55, 0x06, [], entry);
var (entries, last, more) = SymbolObjectServices.ParseListingReply(reply);
more.ShouldBeTrue(); last.ShouldBe(5u); entries.ShouldBe(entry);
}
[Fact]
public void Failure_status_throws() =>
Should.Throw<AbTransportException>(() =>
SymbolObjectServices.ParseListingReply(new CipReply(0x55, 0x04, [], ReadOnlyMemory<byte>.Empty)));
[Fact]
public void Start_instance_above_16_bits_uses_32_bit_segment() =>
Convert.ToHexString(SymbolObjectServices.GetInstanceAttributeList(null, 0x12345)).ShouldBe(
"5504" + "206B" + "2600" + "45230100" + "0400" + "0200" + "0700" + "0800" + "0100");
[Fact]
public void More_with_no_entries_throws() =>
Should.Throw<AbTransportException>(() =>
SymbolObjectServices.ParseListingReply(new CipReply(0x55, 0x06, [], ReadOnlyMemory<byte>.Empty)))
.Status.ShouldBe(AbStatus.BadReply);
}