Files
histsdk/tests/AVEVA.Historian.Client.Tests/WcfHistoricalWriteProtocolTests.cs
T
Joseph Doherty 79bb1d9e06 test(write): golden-pin UInt1/Int8/UInt8 tag-create + value buffers
New InlineData rows derived from the captured Double baselines (type-code /
value bytes swapped). Negative-gate tests retained for still-gated types.

Claude-Session: https://claude.ai/code/session_012SDSQ3AcaXqPcBtDESBRii
2026-06-25 14:49:21 -04:00

71 lines
4.1 KiB
C#

using System.Buffers.Binary;
using AVEVA.Historian.Client.Models;
using AVEVA.Historian.Client.Wcf;
namespace AVEVA.Historian.Client.Tests;
public sealed class WcfHistoricalWriteProtocolTests
{
// Exact HistoryService.AddStreamValues "values" buffers captured live from the native 2023 R2
// client writing one historical sample to a sandbox tag of each analog type — see
// docs/plans/revision-write-path.md §"R3.1 CAPTURED". The value descriptor (C0 10 01 00) is
// constant across types; only the value width differs.
[Theory]
[InlineData(HistorianDataType.Float, 124.5,
"4f4e0100380000002e00d51d3107e9f8664793b155d3d1aef54470df38b1d101dd01c000c0100100e64bcb74e201dd01000000000000f942")]
[InlineData(HistorianDataType.Double, 124.5,
"4f4e01003c0000003200" + "7f970bb0b5a7344bb7bf6899ff06d027" + "c07d5f23d701dd01" + "c000" + "c0100100" + "08eff1e6e701dd01" + "000000000000000000205f40")]
[InlineData(HistorianDataType.Int2, 1234d,
"4f4e0100360000002c00" + "35bb0ca5865a7f4498f06bf4e4d9ab23" + "f012f356d701dd01" + "c000" + "c0100100" + "9546841ae801dd01" + "00000000d204")]
[InlineData(HistorianDataType.Int4, 12345d,
"4f4e0100380000002e00" + "ca9735f7f841b244b56f9c14ccfeac32" + "b09bc72fd701dd01" + "c000" + "c0100100" + "104b59f3e701dd01" + "0000000039300000")]
[InlineData(HistorianDataType.UInt4, 305419896d,
"4f4e0100380000002e00" + "e7ae22d8e4cc65439ebd8bcb09402974" + "602d6663d701dd01" + "c000" + "c0100100" + "498af726e801dd01" + "0000000078563412")]
// UInt1/Int8/UInt8 (H1 un-gate): prefix is the captured Double buffer; only the data-type code / value bytes differ. Live round-trip confirms (gateway HistorianTypeRoundTripTests).
[InlineData(HistorianDataType.Int8, 100000d,
"4f4e01003c0000003200" + "7f970bb0b5a7344bb7bf6899ff06d027" + "c07d5f23d701dd01" + "c000" + "c0100100" + "08eff1e6e701dd01" + "00000000a086010000000000")]
[InlineData(HistorianDataType.UInt8, 100001d,
"4f4e01003c0000003200" + "7f970bb0b5a7344bb7bf6899ff06d027" + "c07d5f23d701dd01" + "c000" + "c0100100" + "08eff1e6e701dd01" + "00000000a186010000000000")]
[InlineData(HistorianDataType.UInt1, 7d,
"4f4e0100" + "35000000" + "2b00" + "7f970bb0b5a7344bb7bf6899ff06d027" + "c07d5f23d701dd01" + "c000" + "c0100100" + "08eff1e6e701dd01" + "00000000" + "07")]
public void SerializeAddStreamValuesBuffer_MatchesCapturedNativeBuffer(HistorianDataType dataType, double value, string capturedHex)
{
byte[] captured = Convert.FromHexString(capturedHex);
// The GUID + both FILETIMEs sit at fixed offsets (the value width varies after them).
var tagGuid = new Guid(captured.AsSpan(10, 16).ToArray());
long sampleFt = BinaryPrimitives.ReadInt64LittleEndian(captured.AsSpan(26, 8));
long receivedFt = BinaryPrimitives.ReadInt64LittleEndian(captured.AsSpan(40, 8));
byte[] actual = HistorianHistoricalWriteProtocol.SerializeAddStreamValuesBuffer(
tagGuid,
dataType,
DateTime.FromFileTimeUtc(sampleFt),
value,
DateTime.FromFileTimeUtc(receivedFt),
quality: 192);
Assert.Equal(captured, actual);
}
[Fact]
public void SerializeAddStreamValuesBuffer_UnsupportedType_Throws()
{
Assert.Throws<ProtocolEvidenceMissingException>(() =>
HistorianHistoricalWriteProtocol.SerializeAddStreamValuesBuffer(
Guid.NewGuid(), HistorianDataType.SingleByteString, DateTime.UtcNow, 1.0, DateTime.UtcNow));
}
[Fact]
public void SerializeAddStreamValuesBuffer_HeaderDeclaresLengths()
{
byte[] buffer = HistorianHistoricalWriteProtocol.SerializeAddStreamValuesBuffer(
Guid.NewGuid(), HistorianDataType.Float, DateTime.UtcNow, value: 1.0, DateTime.UtcNow);
Assert.Equal(0x4E4F, BitConverter.ToUInt16(buffer, 0)); // "ON"
Assert.Equal(1, BitConverter.ToUInt16(buffer, 2)); // sampleCount
Assert.Equal((uint)buffer.Length, BitConverter.ToUInt32(buffer, 4));
Assert.Equal(buffer.Length - 10, BitConverter.ToUInt16(buffer, 8));
}
}