docs: backfill XML documentation across 756 files
v2-ci / build (push) Failing after 1m43s
v2-ci / unit-tests (tests/Core/ZB.MOM.WW.OtOpcUa.Cluster.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Security.Tests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests) (push) Has been skipped
v2-ci / build (push) Failing after 1m43s
v2-ci / unit-tests (tests/Core/ZB.MOM.WW.OtOpcUa.Cluster.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Security.Tests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests) (push) Has been skipped
Adds <summary>, <param>, <typeparam>, and <inheritdoc/> tags to public members surfaced by commentchecker — resolves 5,847 of 5,869 issues (99.6%) across three /fixdocs passes.
This commit is contained in:
@@ -8,6 +8,12 @@ public sealed class S7AddressParserTests
|
||||
{
|
||||
// --- Data blocks ---
|
||||
|
||||
/// <summary>Verifies that data block addresses are parsed correctly.</summary>
|
||||
/// <param name="input">The address string to parse.</param>
|
||||
/// <param name="db">The expected data block number.</param>
|
||||
/// <param name="size">The expected data size.</param>
|
||||
/// <param name="byteOff">The expected byte offset.</param>
|
||||
/// <param name="bitOff">The expected bit offset.</param>
|
||||
[Theory]
|
||||
[InlineData("DB1.DBX0.0", 1, S7Size.Bit, 0, 0)]
|
||||
[InlineData("DB1.DBX0.7", 1, S7Size.Bit, 0, 7)]
|
||||
@@ -26,6 +32,11 @@ public sealed class S7AddressParserTests
|
||||
r.BitOffset.ShouldBe(bitOff);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that parsing is case-insensitive and trims whitespace.</summary>
|
||||
/// <param name="input">The address string to parse.</param>
|
||||
/// <param name="db">The expected data block number.</param>
|
||||
/// <param name="size">The expected data size.</param>
|
||||
/// <param name="off">The expected byte offset.</param>
|
||||
[Theory]
|
||||
[InlineData("db1.dbw0", 1, S7Size.Word, 0)]
|
||||
[InlineData(" DB1.DBW0 ", 1, S7Size.Word, 0)] // trim whitespace
|
||||
@@ -40,6 +51,12 @@ public sealed class S7AddressParserTests
|
||||
|
||||
// --- M / I / Q ---
|
||||
|
||||
/// <summary>Verifies that Memory (M), Input (I), and Output (Q) addresses are parsed correctly.</summary>
|
||||
/// <param name="input">The address string to parse.</param>
|
||||
/// <param name="area">The expected address area.</param>
|
||||
/// <param name="size">The expected data size.</param>
|
||||
/// <param name="byteOff">The expected byte offset.</param>
|
||||
/// <param name="bitOff">The expected bit offset.</param>
|
||||
[Theory]
|
||||
[InlineData("MB0", S7Area.Memory, S7Size.Byte, 0, 0)]
|
||||
[InlineData("MW10", S7Area.Memory, S7Size.Word, 10, 0)]
|
||||
@@ -65,6 +82,10 @@ public sealed class S7AddressParserTests
|
||||
|
||||
// --- Timers / counters ---
|
||||
|
||||
/// <summary>Verifies that timer and counter addresses are parsed correctly.</summary>
|
||||
/// <param name="input">The address string to parse.</param>
|
||||
/// <param name="area">The expected address area.</param>
|
||||
/// <param name="number">The expected timer or counter number.</param>
|
||||
[Theory]
|
||||
[InlineData("T0", S7Area.Timer, 0)]
|
||||
[InlineData("T15", S7Area.Timer, 15)]
|
||||
@@ -80,6 +101,8 @@ public sealed class S7AddressParserTests
|
||||
|
||||
// --- Reject garbage ---
|
||||
|
||||
/// <summary>Verifies that invalid addresses are rejected with FormatException.</summary>
|
||||
/// <param name="bad">The invalid address string to test.</param>
|
||||
[Theory]
|
||||
[InlineData("")]
|
||||
[InlineData(" ")]
|
||||
@@ -102,6 +125,7 @@ public sealed class S7AddressParserTests
|
||||
public void Parse_rejects_invalid(string bad)
|
||||
=> Should.Throw<FormatException>(() => S7AddressParser.Parse(bad));
|
||||
|
||||
/// <summary>Verifies that TryParse returns false for invalid input without throwing.</summary>
|
||||
[Fact]
|
||||
public void TryParse_returns_false_for_garbage_without_throwing()
|
||||
{
|
||||
@@ -109,6 +133,7 @@ public sealed class S7AddressParserTests
|
||||
r.ShouldBe(default);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that TryParse returns true for a valid address.</summary>
|
||||
[Fact]
|
||||
public void TryParse_returns_true_for_valid_address()
|
||||
{
|
||||
|
||||
@@ -18,27 +18,53 @@ public sealed class S7DiscoveryAndSubscribeTests
|
||||
public readonly List<string> Folders = new();
|
||||
public readonly List<(string Name, DriverAttributeInfo Attr)> Variables = new();
|
||||
|
||||
/// <summary>Adds a folder to the address space.</summary>
|
||||
/// <param name="browseName">The browse name of the folder.</param>
|
||||
/// <param name="displayName">The display name of the folder.</param>
|
||||
/// <returns>This builder instance for method chaining.</returns>
|
||||
public IAddressSpaceBuilder Folder(string browseName, string displayName)
|
||||
{
|
||||
Folders.Add(browseName);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>Adds a variable to the address space.</summary>
|
||||
/// <param name="browseName">The browse name of the variable.</param>
|
||||
/// <param name="displayName">The display name of the variable.</param>
|
||||
/// <param name="attributeInfo">The attribute information for the variable.</param>
|
||||
/// <returns>A handle to the created variable.</returns>
|
||||
public IVariableHandle Variable(string browseName, string displayName, DriverAttributeInfo attributeInfo)
|
||||
{
|
||||
Variables.Add((browseName, attributeInfo));
|
||||
return new StubHandle();
|
||||
}
|
||||
|
||||
/// <summary>Adds a property to a variable.</summary>
|
||||
/// <param name="browseName">The browse name of the property.</param>
|
||||
/// <param name="dataType">The data type of the property.</param>
|
||||
/// <param name="value">The initial value of the property.</param>
|
||||
public void AddProperty(string browseName, DriverDataType dataType, object? value) { }
|
||||
|
||||
/// <summary>Attaches an alarm condition to a variable.</summary>
|
||||
/// <param name="sourceVariable">The variable to attach the alarm to.</param>
|
||||
/// <param name="alarmName">The name of the alarm.</param>
|
||||
/// <param name="alarmInfo">The alarm information.</param>
|
||||
public void AttachAlarmCondition(IVariableHandle sourceVariable, string alarmName, DriverAttributeInfo alarmInfo) { }
|
||||
|
||||
private sealed class StubHandle : IVariableHandle
|
||||
{
|
||||
/// <summary>Gets the full reference of the variable.</summary>
|
||||
public string FullReference => "stub";
|
||||
|
||||
/// <summary>Marks this variable as an alarm condition.</summary>
|
||||
/// <param name="info">The alarm condition information.</param>
|
||||
/// <returns>An alarm condition sink.</returns>
|
||||
public IAlarmConditionSink MarkAsAlarmCondition(AlarmConditionInfo info)
|
||||
=> throw new NotImplementedException("S7 driver never calls this — no alarm surfacing");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verifies that DiscoverAsync projects every configured tag into the address space.</summary>
|
||||
[Fact]
|
||||
public async Task DiscoverAsync_projects_every_tag_into_the_address_space()
|
||||
{
|
||||
@@ -65,6 +91,7 @@ public sealed class S7DiscoveryAndSubscribeTests
|
||||
builder.Variables[2].Attr.DriverDataType.ShouldBe(DriverDataType.Float32);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that DiscoverAsync propagates the WriteIdempotent flag from tag configuration to attribute info.</summary>
|
||||
[Fact]
|
||||
public async Task DiscoverAsync_propagates_WriteIdempotent_from_tag_to_attribute_info()
|
||||
{
|
||||
@@ -86,6 +113,7 @@ public sealed class S7DiscoveryAndSubscribeTests
|
||||
builder.Variables.Single(v => v.Name == "StartBit").Attr.WriteIdempotent.ShouldBeFalse("default is opt-in per decision #44");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that GetHostStatuses returns one row with the host:port identity in pre-init state.</summary>
|
||||
[Fact]
|
||||
public void GetHostStatuses_returns_one_row_with_host_port_identity_pre_init()
|
||||
{
|
||||
@@ -98,6 +126,7 @@ public sealed class S7DiscoveryAndSubscribeTests
|
||||
rows[0].State.ShouldBe(HostState.Unknown, "pre-init / pre-probe state is Unknown");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that SubscribeAsync returns unique handles and UnsubscribeAsync correctly accepts them.</summary>
|
||||
[Fact]
|
||||
public async Task SubscribeAsync_returns_unique_handles_and_UnsubscribeAsync_accepts_them()
|
||||
{
|
||||
@@ -121,6 +150,7 @@ public sealed class S7DiscoveryAndSubscribeTests
|
||||
await drv.UnsubscribeAsync(h1, TestContext.Current.CancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that Subscribe floors the publishing interval at 100ms.</summary>
|
||||
[Fact]
|
||||
public async Task Subscribe_publishing_interval_is_floored_at_100ms()
|
||||
{
|
||||
|
||||
@@ -16,6 +16,8 @@ public sealed class S7DriverCodeReviewFixTests
|
||||
{
|
||||
// ---- Driver.S7-001 — Timer/Counter tags must be rejected at init ----
|
||||
|
||||
/// <summary>Verifies that initialize rejects timer or counter tags with NotSupportedException.</summary>
|
||||
/// <param name="address">The S7 Timer or Counter address to test.</param>
|
||||
[Theory]
|
||||
[InlineData("T0")]
|
||||
[InlineData("T15")]
|
||||
@@ -45,6 +47,7 @@ public sealed class S7DriverCodeReviewFixTests
|
||||
health.LastError.ShouldNotBeNull();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that initialize accepts DB and MIQ addresses without triggering the unsupported guard.</summary>
|
||||
[Fact]
|
||||
public async Task Initialize_accepts_DB_and_MIQ_addresses_without_the_unsupported_guard_tripping()
|
||||
{
|
||||
@@ -71,6 +74,7 @@ public sealed class S7DriverCodeReviewFixTests
|
||||
|
||||
// ---- Driver.S7-011 — driverConfigJson must be applied on Initialize ----
|
||||
|
||||
/// <summary>Verifies that initialize applies the supplied driverConfigJson over constructor options.</summary>
|
||||
[Fact]
|
||||
public async Task Initialize_applies_the_supplied_driverConfigJson_over_the_constructor_options()
|
||||
{
|
||||
@@ -96,6 +100,7 @@ public sealed class S7DriverCodeReviewFixTests
|
||||
"InitializeAsync must apply the driverConfigJson timeout, not the constructor's");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that initialize rejects a timer tag supplied only through driverConfigJson.</summary>
|
||||
[Fact]
|
||||
public async Task Initialize_rejects_a_timer_tag_supplied_only_through_driverConfigJson()
|
||||
{
|
||||
@@ -114,6 +119,7 @@ public sealed class S7DriverCodeReviewFixTests
|
||||
ex.Message.ShouldContain("T5");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that reinitialize applies a changed driverConfigJson.</summary>
|
||||
[Fact]
|
||||
public async Task Reinitialize_applies_a_changed_driverConfigJson()
|
||||
{
|
||||
@@ -135,6 +141,7 @@ public sealed class S7DriverCodeReviewFixTests
|
||||
|
||||
// ---- Driver.S7-006 — Shutdown drains probe/poll loops before disposing the gate ----
|
||||
|
||||
/// <summary>Verifies that shutdown completes cleanly with active subscriptions and no disposal race.</summary>
|
||||
[Fact]
|
||||
public async Task Shutdown_completes_cleanly_with_active_subscriptions_and_no_disposal_race()
|
||||
{
|
||||
@@ -159,6 +166,7 @@ public sealed class S7DriverCodeReviewFixTests
|
||||
await Should.NotThrowAsync(async () => await drv.DisposeAsync());
|
||||
}
|
||||
|
||||
/// <summary>Verifies that dispose after subscribe does not throw ObjectDisposedException.</summary>
|
||||
[Fact]
|
||||
public async Task Dispose_after_subscribe_does_not_throw_ObjectDisposedException()
|
||||
{
|
||||
|
||||
@@ -15,6 +15,7 @@ public sealed class S7DriverCodeReviewFixTests2
|
||||
{
|
||||
// ── Driver.S7-003 — Read/WriteAsync must throw ArgumentNullException, not NRE ─────────
|
||||
|
||||
/// <summary>Verifies that ReadAsync throws ArgumentNullException for null references.</summary>
|
||||
[Fact]
|
||||
public async Task ReadAsync_with_null_fullReferences_throws_ArgumentNullException()
|
||||
{
|
||||
@@ -26,6 +27,7 @@ public sealed class S7DriverCodeReviewFixTests2
|
||||
await drv.ReadAsync(null!, TestContext.Current.CancellationToken));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that WriteAsync throws ArgumentNullException for null writes.</summary>
|
||||
[Fact]
|
||||
public async Task WriteAsync_with_null_writes_throws_ArgumentNullException()
|
||||
{
|
||||
@@ -36,6 +38,7 @@ public sealed class S7DriverCodeReviewFixTests2
|
||||
|
||||
// ── Driver.S7-009 — Poll loop must update health on sustained failure ────────────────
|
||||
|
||||
/// <summary>Verifies that the poll loop degrades health when the driver is uninitialized.</summary>
|
||||
[Fact]
|
||||
public async Task PollLoop_against_uninitialized_driver_degrades_health()
|
||||
{
|
||||
@@ -64,6 +67,7 @@ public sealed class S7DriverCodeReviewFixTests2
|
||||
await drv.DisposeAsync();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the poll loop applies capped backoff after consecutive failures.</summary>
|
||||
[Fact]
|
||||
public async Task PollLoop_applies_capped_backoff_after_consecutive_failures()
|
||||
{
|
||||
@@ -103,6 +107,7 @@ public sealed class S7DriverCodeReviewFixTests2
|
||||
|
||||
// ── Driver.S7-010 — Dispose() must not deadlock via sync-over-async ──────────────────
|
||||
|
||||
/// <summary>Verifies that Dispose completes synchronously without sync-over-async.</summary>
|
||||
[Fact]
|
||||
public void Dispose_completes_synchronously_without_sync_over_async_round_trip()
|
||||
{
|
||||
@@ -120,6 +125,7 @@ public sealed class S7DriverCodeReviewFixTests2
|
||||
"Dispose() must teardown directly — see Driver.S7-010");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that Dispose is idempotent.</summary>
|
||||
[Fact]
|
||||
public void Dispose_is_idempotent()
|
||||
{
|
||||
@@ -132,6 +138,8 @@ public sealed class S7DriverCodeReviewFixTests2
|
||||
|
||||
// ── Driver.S7-013 — Reject not-yet-implemented S7DataType values at init ─────────────
|
||||
|
||||
/// <summary>Verifies that Initialize rejects not-yet-implemented data types with NotSupportedException.</summary>
|
||||
/// <param name="dt">The S7 data type that is not yet implemented.</param>
|
||||
[Theory]
|
||||
[InlineData(S7DataType.Int64)]
|
||||
[InlineData(S7DataType.UInt64)]
|
||||
@@ -162,6 +170,9 @@ public sealed class S7DriverCodeReviewFixTests2
|
||||
health.State.ShouldBe(DriverState.Faulted);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that Initialize accepts implemented data types.</summary>
|
||||
/// <param name="dt">The S7 data type to test.</param>
|
||||
/// <param name="addr">The S7 address string corresponding to the data type.</param>
|
||||
[Theory]
|
||||
[InlineData(S7DataType.Bool, "DB1.DBX0.0")]
|
||||
[InlineData(S7DataType.Byte, "DB1.DBB0")]
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.S7.Tests;
|
||||
[Trait("Category", "Unit")]
|
||||
public sealed class S7DriverReadWriteTests
|
||||
{
|
||||
/// <summary>Verifies that initialization rejects invalid tag addresses and fails fast.</summary>
|
||||
[Fact]
|
||||
public async Task Initialize_rejects_invalid_tag_address_and_fails_fast()
|
||||
{
|
||||
@@ -34,6 +35,7 @@ public sealed class S7DriverReadWriteTests
|
||||
await drv.InitializeAsync("{}", TestContext.Current.CancellationToken));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that ReadAsync without initialize throws InvalidOperationException.</summary>
|
||||
[Fact]
|
||||
public async Task ReadAsync_without_initialize_throws_InvalidOperationException()
|
||||
{
|
||||
@@ -42,6 +44,7 @@ public sealed class S7DriverReadWriteTests
|
||||
await drv.ReadAsync(["Any"], TestContext.Current.CancellationToken));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that WriteAsync without initialize throws InvalidOperationException.</summary>
|
||||
[Fact]
|
||||
public async Task WriteAsync_without_initialize_throws_InvalidOperationException()
|
||||
{
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.S7.Tests;
|
||||
[Trait("Category", "Unit")]
|
||||
public sealed class S7DriverScaffoldTests
|
||||
{
|
||||
/// <summary>Verifies that default options target S7-1500 slot 0 on port 102.</summary>
|
||||
[Fact]
|
||||
public void Default_options_target_S7_1500_slot_0_on_port_102()
|
||||
{
|
||||
@@ -22,6 +23,7 @@ public sealed class S7DriverScaffoldTests
|
||||
opts.Slot.ShouldBe((short)0, "S7-1200/1500 onboard PN ports are slot 0 by convention");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the default probe interval is reasonable for S7 scan cycles.</summary>
|
||||
[Fact]
|
||||
public void Default_probe_interval_is_reasonable_for_S7_scan_cycle()
|
||||
{
|
||||
@@ -30,6 +32,7 @@ public sealed class S7DriverScaffoldTests
|
||||
new S7ProbeOptions().Interval.ShouldBe(TimeSpan.FromSeconds(5));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that tag definition defaults to writable with S7 max string length.</summary>
|
||||
[Fact]
|
||||
public void Tag_definition_defaults_to_writable_with_S7_max_string_length()
|
||||
{
|
||||
@@ -38,6 +41,7 @@ public sealed class S7DriverScaffoldTests
|
||||
tag.StringLength.ShouldBe(254, "S7 STRING type max length is 254 chars");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the driver instance reports type and ID before connect.</summary>
|
||||
[Fact]
|
||||
public void Driver_instance_reports_type_and_id_before_connect()
|
||||
{
|
||||
@@ -48,6 +52,7 @@ public sealed class S7DriverScaffoldTests
|
||||
drv.GetHealth().State.ShouldBe(DriverState.Unknown, "health starts Unknown until InitializeAsync runs");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that Initialize against unreachable host transitions to Faulted and throws.</summary>
|
||||
[Fact]
|
||||
public async Task Initialize_against_unreachable_host_transitions_to_Faulted_and_throws()
|
||||
{
|
||||
|
||||
@@ -22,6 +22,7 @@ public sealed class S7TypeMappingTests
|
||||
|
||||
// ── ReinterpretRawValue — implemented types ───────────────────────────────────────────
|
||||
|
||||
/// <summary>Verifies that bool values are returned unchanged.</summary>
|
||||
[Fact]
|
||||
public void ReinterpretRawValue_Bool_returns_bool()
|
||||
{
|
||||
@@ -31,6 +32,7 @@ public sealed class S7TypeMappingTests
|
||||
S7Driver.ReinterpretRawValue(tag, addr, false).ShouldBe(false);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that byte values are returned unchanged.</summary>
|
||||
[Fact]
|
||||
public void ReinterpretRawValue_Byte_returns_byte()
|
||||
{
|
||||
@@ -39,6 +41,7 @@ public sealed class S7TypeMappingTests
|
||||
S7Driver.ReinterpretRawValue(tag, addr, (byte)42).ShouldBe((byte)42);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that UInt16 values are returned as unsigned short.</summary>
|
||||
[Fact]
|
||||
public void ReinterpretRawValue_UInt16_returns_ushort()
|
||||
{
|
||||
@@ -46,6 +49,7 @@ public sealed class S7TypeMappingTests
|
||||
.ShouldBe((ushort)1000);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that unsigned short bits are reinterpreted as signed short.</summary>
|
||||
[Fact]
|
||||
public void ReinterpretRawValue_Int16_reinterprets_ushort_as_signed()
|
||||
{
|
||||
@@ -54,6 +58,7 @@ public sealed class S7TypeMappingTests
|
||||
result.ShouldBe((short)-1);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that UInt32 values are returned as unsigned integer.</summary>
|
||||
[Fact]
|
||||
public void ReinterpretRawValue_UInt32_returns_uint()
|
||||
{
|
||||
@@ -61,6 +66,7 @@ public sealed class S7TypeMappingTests
|
||||
.ShouldBe(70_000u);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that unsigned integer bits are reinterpreted as signed integer.</summary>
|
||||
[Fact]
|
||||
public void ReinterpretRawValue_Int32_reinterprets_uint_as_signed()
|
||||
{
|
||||
@@ -69,6 +75,7 @@ public sealed class S7TypeMappingTests
|
||||
result.ShouldBe(-1);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that unsigned integer bits are converted to IEEE 754 float.</summary>
|
||||
[Fact]
|
||||
public void ReinterpretRawValue_Float32_converts_uint_bits_to_float()
|
||||
{
|
||||
@@ -80,6 +87,8 @@ public sealed class S7TypeMappingTests
|
||||
|
||||
// ── ReinterpretRawValue — unsupported types throw NotSupportedException ───────────────
|
||||
|
||||
/// <summary>Verifies that unsupported data types throw NotSupportedException.</summary>
|
||||
/// <param name="dt">The unsupported S7 data type.</param>
|
||||
[Theory]
|
||||
[InlineData(S7DataType.Int64)]
|
||||
[InlineData(S7DataType.UInt64)]
|
||||
@@ -94,6 +103,7 @@ public sealed class S7TypeMappingTests
|
||||
|
||||
// ── BoxValueForWrite — implemented types ─────────────────────────────────────────────
|
||||
|
||||
/// <summary>Verifies that values are converted to bool for write.</summary>
|
||||
[Fact]
|
||||
public void BoxValueForWrite_Bool_converts_value_to_bool()
|
||||
{
|
||||
@@ -102,18 +112,21 @@ public sealed class S7TypeMappingTests
|
||||
S7Driver.BoxValueForWrite(S7DataType.Bool, 1).ShouldBe(true);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that values are converted to byte for write.</summary>
|
||||
[Fact]
|
||||
public void BoxValueForWrite_Byte_converts_to_byte()
|
||||
{
|
||||
S7Driver.BoxValueForWrite(S7DataType.Byte, (byte)200).ShouldBe((byte)200);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that values are converted to unsigned short for write.</summary>
|
||||
[Fact]
|
||||
public void BoxValueForWrite_UInt16_converts_to_ushort()
|
||||
{
|
||||
S7Driver.BoxValueForWrite(S7DataType.UInt16, (ushort)1234).ShouldBe((ushort)1234);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that signed short is reinterpreted as unsigned short using two's complement.</summary>
|
||||
[Fact]
|
||||
public void BoxValueForWrite_Int16_reinterprets_as_ushort_two_complement()
|
||||
{
|
||||
@@ -121,12 +134,14 @@ public sealed class S7TypeMappingTests
|
||||
S7Driver.BoxValueForWrite(S7DataType.Int16, (short)-1).ShouldBe((ushort)0xFFFF);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that values are converted to unsigned integer for write.</summary>
|
||||
[Fact]
|
||||
public void BoxValueForWrite_UInt32_converts_to_uint()
|
||||
{
|
||||
S7Driver.BoxValueForWrite(S7DataType.UInt32, 70_000u).ShouldBe(70_000u);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that signed integer is reinterpreted as unsigned integer using two's complement.</summary>
|
||||
[Fact]
|
||||
public void BoxValueForWrite_Int32_reinterprets_as_uint_two_complement()
|
||||
{
|
||||
@@ -134,6 +149,7 @@ public sealed class S7TypeMappingTests
|
||||
S7Driver.BoxValueForWrite(S7DataType.Int32, -1).ShouldBe(0xFFFF_FFFFu);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that float is encoded as IEEE 754 unsigned integer for write.</summary>
|
||||
[Fact]
|
||||
public void BoxValueForWrite_Float32_encodes_as_ieee754_uint()
|
||||
{
|
||||
@@ -144,6 +160,8 @@ public sealed class S7TypeMappingTests
|
||||
|
||||
// ── BoxValueForWrite — unsupported types throw NotSupportedException ─────────────────
|
||||
|
||||
/// <summary>Verifies that unsupported data types throw NotSupportedException on write.</summary>
|
||||
/// <param name="dt">The unsupported S7 data type.</param>
|
||||
[Theory]
|
||||
[InlineData(S7DataType.Int64)]
|
||||
[InlineData(S7DataType.UInt64)]
|
||||
@@ -158,6 +176,7 @@ public sealed class S7TypeMappingTests
|
||||
|
||||
// ── BoxValueForWrite — overflow paths ────────────────────────────────────────────────
|
||||
|
||||
/// <summary>Verifies that out-of-range values throw OverflowException for byte write.</summary>
|
||||
[Fact]
|
||||
public void BoxValueForWrite_Byte_overflows_for_out_of_range_value()
|
||||
{
|
||||
@@ -165,6 +184,7 @@ public sealed class S7TypeMappingTests
|
||||
Should.Throw<OverflowException>(() => S7Driver.BoxValueForWrite(S7DataType.Byte, 256));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that out-of-range values throw OverflowException for unsigned short write.</summary>
|
||||
[Fact]
|
||||
public void BoxValueForWrite_UInt16_overflows_for_out_of_range_value()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user