diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Heidenhain.Tests/HeidenhainLiveIntegrationTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Heidenhain.Tests/HeidenhainLiveIntegrationTests.cs index b0a9c4522..020425a31 100644 --- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Heidenhain.Tests/HeidenhainLiveIntegrationTests.cs +++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Heidenhain.Tests/HeidenhainLiveIntegrationTests.cs @@ -85,4 +85,38 @@ public sealed class HeidenhainLiveIntegrationTests TestContext.Current.SendDiagnosticMessage($"{tags[i].RawPath} = {values[i].Value} (0x{values[i].StatusCode:X8})"); values[0].StatusCode.ShouldBe(HeidenhainStatus.Good); } + + /// #867: integer tool leaves must reach clients with their declared runtime type, not Double. + [Fact] + public async Task Real_control_tool_leaves_keep_integer_types() + { + Assert.SkipWhen(string.IsNullOrWhiteSpace(Host), "HEIDENHAIN_LSV2_HOST not set — real-controller gate skipped."); + var ct = TestContext.Current.CancellationToken; + var tags = new[] { TestTags.Raw("Tool/Number"), TestTags.Raw("Tool/Index"), TestTags.Raw("Tool/AxisCode") }; + var options = new HeidenhainDriverOptions + { + Devices = [new HeidenhainDeviceOptions { Host = Host!, Port = Port, DeviceName = "dev1" }], + RawTags = tags, + Access = new HeidenhainAccessOptions { InspectPassword = Environment.GetEnvironmentVariable("OTOPCUA_HEIDENHAIN_INSPECT_PASSWORD") is { Length: > 0 } ? "env:OTOPCUA_HEIDENHAIN_INSPECT_PASSWORD" : null }, + }; + await using var driver = new HeidenhainDriver(options, "live"); + await driver.InitializeAsync("{}", ct); + await driver.SubscribeAsync(tags.Select(t => t.RawPath).ToList(), TimeSpan.FromSeconds(1), ct); + var deadline = DateTime.UtcNow.AddSeconds(30); + IReadOnlyList values; + do + { + await Task.Delay(500, ct); + values = await driver.ReadAsync(tags.Select(t => t.RawPath).ToList(), ct); + } while (values.Any(v => v.StatusCode != HeidenhainStatus.Good) && DateTime.UtcNow < deadline); + + var expected = new[] { typeof(long), typeof(int), typeof(int) }; + for (var i = 0; i < tags.Length; i++) + { + TestContext.Current.SendDiagnosticMessage($"{tags[i].RawPath} = {values[i].Value} ({values[i].Value?.GetType().Name}) (0x{values[i].StatusCode:X8})"); + if (values[i].StatusCode == HeidenhainStatus.Good) + values[i].Value!.GetType().ShouldBe(expected[i]); + } + values.Count(v => v.StatusCode == HeidenhainStatus.Good).ShouldBeGreaterThan(0); + } }