using Shouldly;
using Xunit;
namespace ZB.MOM.WW.OtOpcUa.Driver.S7.Tests;
///
/// Unit tests for 's IReadable/IWritable surface
/// that don't require a live PLC — covers error paths (not-initialized, unknown tag,
/// read-only write rejection, unsupported data types). Wire-level round-trip tests
/// against a live S7 or a mock-server land in a follow-up PR since S7.Net doesn't ship
/// an in-process fake and an adequate mock is non-trivial.
///
[Trait("Category", "Unit")]
public sealed class S7DriverReadWriteTests
{
/// Verifies that initialization rejects invalid tag addresses and fails fast.
[Fact]
public async Task Initialize_rejects_invalid_tag_address_and_fails_fast()
{
// A bad address is refused PER TAG at every gate (mapper/editor, deploy gate, driver init):
// it reads BadNodeIdUnknown while its neighbours keep working. It used to throw at init and
// fault every tag on the PLC, with the actor retrying the same init every 10 s forever.
await S7TagSkipAssert.RefusedPerTagAsync(
new S7TagDefinition("BadTag", "NOT-AN-S7-ADDRESS", S7DataType.Int16), "does not parse");
}
/// Verifies that ReadAsync without initialize throws InvalidOperationException.
[Fact]
public async Task ReadAsync_without_initialize_throws_InvalidOperationException()
{
using var drv = new S7Driver(new S7DriverOptions { Host = "192.0.2.1" }, "s7-uninit");
await Should.ThrowAsync(async () =>
await drv.ReadAsync(["Any"], TestContext.Current.CancellationToken));
}
/// Verifies that WriteAsync without initialize throws InvalidOperationException.
[Fact]
public async Task WriteAsync_without_initialize_throws_InvalidOperationException()
{
using var drv = new S7Driver(new S7DriverOptions { Host = "192.0.2.1" }, "s7-uninit");
await Should.ThrowAsync(async () =>
await drv.WriteAsync(
[new(FullReference: "Any", Value: (short)0)],
TestContext.Current.CancellationToken));
}
}