feat(sphistorianclient): port SDK source + tests, rebrand namespace to ZB.MOM.WW.SPHistorianClient
This commit is contained in:
+283
@@ -0,0 +1,283 @@
|
||||
using System.Text;
|
||||
using ZB.MOM.WW.SPHistorianClient.Wcf;
|
||||
|
||||
namespace ZB.MOM.WW.SPHistorianClient.Tests;
|
||||
|
||||
public sealed class WcfOpen2ProtocolTests
|
||||
{
|
||||
[Fact]
|
||||
public void LegacyVersion1SerializerMatchesDecompiledSaveOpenConnectionParamsLayout()
|
||||
{
|
||||
byte[] actual = HistorianOpen2Protocol.SerializeLegacyVersion1(new HistorianOpen2Request(
|
||||
HostName: "H",
|
||||
ProcessName: "P",
|
||||
ProcessId: 0x01020304,
|
||||
UserName: "U",
|
||||
Password: Encoding.Unicode.GetBytes("pw"),
|
||||
ClientType: 4,
|
||||
ClientVersion: 11,
|
||||
ConnectionMode: 2,
|
||||
MetadataNamespace: HistorianMetadataNamespace.Empty));
|
||||
|
||||
byte[] expected =
|
||||
[
|
||||
0x01, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x48, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x50, 0x00,
|
||||
0x04, 0x03, 0x02, 0x01,
|
||||
0x01, 0x00, 0x00, 0x00, 0x55, 0x00,
|
||||
0x04, 0x00, 0x00, 0x00, 0x70, 0x00, 0x77, 0x00,
|
||||
0x04,
|
||||
0x0B, 0x00,
|
||||
0x02, 0x00, 0x00, 0x00,
|
||||
0x01,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00
|
||||
];
|
||||
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LegacyVersion1SerializerUsesUtf16CodeUnitStringLengths()
|
||||
{
|
||||
byte[] actual = HistorianOpen2Protocol.SerializeLegacyVersion1(new HistorianOpen2Request(
|
||||
HostName: "A\ud83d\ude00",
|
||||
ProcessName: string.Empty,
|
||||
ProcessId: 0,
|
||||
UserName: string.Empty,
|
||||
Password: [],
|
||||
ClientType: 4,
|
||||
ClientVersion: 0,
|
||||
ConnectionMode: 2,
|
||||
MetadataNamespace: HistorianMetadataNamespace.Empty));
|
||||
|
||||
Assert.Equal([0x03, 0x00, 0x00, 0x00], actual[2..6]);
|
||||
Assert.Equal(Encoding.Unicode.GetBytes("A\ud83d\ude00"), actual[6..12]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NativeErrorParserReadsObservedFiveByteBuffers()
|
||||
{
|
||||
HistorianNativeError? error = HistorianOpen2Protocol.TryReadNativeError([0x04, 0xAB, 0x00, 0x00, 0x00]);
|
||||
|
||||
Assert.NotNull(error);
|
||||
Assert.Equal(4, error.Type);
|
||||
Assert.Equal<uint>(171, error.Code);
|
||||
Assert.Equal("AuthenticationFailed", error.Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NativeErrorParserRejectsShortBuffers()
|
||||
{
|
||||
Assert.Null(HistorianOpen2Protocol.TryReadNativeError([0x04, 0xAB, 0x00, 0x00]));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LegacyOpen2OutputParserReadsObservedWcfLayout()
|
||||
{
|
||||
byte[] buffer =
|
||||
[
|
||||
0x78, 0x56, 0x34, 0x12,
|
||||
0x33, 0x22, 0x11, 0x00,
|
||||
0x55, 0x44,
|
||||
0x77, 0x66,
|
||||
0x88, 0x99, 0xAA, 0xBB,
|
||||
0xCC, 0xDD, 0xEE, 0xFF,
|
||||
0x08, 0x07, 0x06, 0x05,
|
||||
0x04, 0x03, 0x02, 0x01,
|
||||
0x44, 0x33, 0x22, 0x11
|
||||
];
|
||||
|
||||
HistorianLegacyOpen2Output? output = HistorianOpen2Protocol.TryReadLegacyOpen2Output(buffer);
|
||||
|
||||
Assert.NotNull(output);
|
||||
Assert.Equal<uint>(0x12345678, output.Handle);
|
||||
Assert.Equal(new Guid("00112233-4455-6677-8899-aabbccddeeff"), output.StorageSessionId);
|
||||
Assert.Equal(0x0102030405060708, output.ConnectTimeFileTimeUtc);
|
||||
Assert.Equal<uint>(0x11223344, output.ServerStatus);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LegacyOpen2OutputParserRejectsNonLegacyLength()
|
||||
{
|
||||
Assert.Null(HistorianOpen2Protocol.TryReadLegacyOpen2Output([0x00]));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NativeOpen3OutputParserReadsObservedDeserializerLayout()
|
||||
{
|
||||
byte[] buffer =
|
||||
[
|
||||
0x03,
|
||||
0x78, 0x56, 0x34, 0x12,
|
||||
0x33, 0x22, 0x11, 0x00,
|
||||
0x55, 0x44,
|
||||
0x77, 0x66,
|
||||
0x88, 0x99, 0xAA, 0xBB,
|
||||
0xCC, 0xDD, 0xEE, 0xFF,
|
||||
0x08, 0x07, 0x06, 0x05,
|
||||
0x04, 0x03, 0x02, 0x01,
|
||||
0x18, 0x17, 0x16, 0x15,
|
||||
0x14, 0x13, 0x12, 0x11,
|
||||
0x44, 0x33, 0x22, 0x11,
|
||||
0x00
|
||||
];
|
||||
|
||||
HistorianNativeOpen3Output? output = HistorianOpen2Protocol.TryReadNativeOpen3Output(buffer);
|
||||
|
||||
Assert.NotNull(output);
|
||||
Assert.Equal(3, output.ProtocolVersion);
|
||||
Assert.Equal<uint>(0x12345678, output.Handle);
|
||||
Assert.Equal(new Guid("00112233-4455-6677-8899-aabbccddeeff"), output.StorageSessionId);
|
||||
Assert.Equal(0x0102030405060708, output.ConnectTimeFileTimeUtc);
|
||||
Assert.Equal(0x1112131415161718, output.ServerTimeFileTimeUtc);
|
||||
Assert.Equal([0x44, 0x33, 0x22, 0x11, 0x00], output.TrailingBytes);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NativeOpen3OutputParserRejectsUnsupportedVersion()
|
||||
{
|
||||
Assert.Null(HistorianOpen2Protocol.TryReadNativeOpen3Output([0x01, 0x00, 0x00, 0x00]));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NativeVersion3SerializerMatchesDecompiledFieldOrder()
|
||||
{
|
||||
byte[] actual = HistorianOpen2Protocol.SerializeNativeVersion3(
|
||||
new HistorianOpen2Request(
|
||||
HostName: "H",
|
||||
ProcessName: "P",
|
||||
ProcessId: 0x01020304,
|
||||
UserName: string.Empty,
|
||||
Password: [0xAA, 0xBB],
|
||||
ClientType: 4,
|
||||
ClientVersion: 11,
|
||||
ConnectionMode: 1026,
|
||||
MetadataNamespace: HistorianMetadataNamespace.Empty),
|
||||
new HistorianClientCommonInfo(
|
||||
FormatVersion: 3,
|
||||
ServerNodeName: "S",
|
||||
ClientNodeName: "C",
|
||||
ProcessId: 0x11223344,
|
||||
HcalVersion: 17,
|
||||
ProcessName: "Proc",
|
||||
Proxy: string.Empty,
|
||||
DataSourceId: string.Empty,
|
||||
ShardId: new Guid("00112233-4455-6677-8899-aabbccddeeff"),
|
||||
ClientVersion: 0x55667788,
|
||||
ClientTimestamp: 0x0102030405060708,
|
||||
ClientDllVersion: string.Empty));
|
||||
|
||||
byte[] expectedPrefix =
|
||||
[
|
||||
0x03,
|
||||
0x01, 0x00, 0x00, 0x00, 0x48, 0x00,
|
||||
0x02, 0x00, 0xAA, 0xBB,
|
||||
0x04,
|
||||
0x02, 0x04, 0x00, 0x00
|
||||
];
|
||||
Assert.Equal(expectedPrefix, actual[..expectedPrefix.Length]);
|
||||
|
||||
Assert.Contains<byte>(0x03, actual);
|
||||
byte[] expectedSuffix = [0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01];
|
||||
Assert.Equal(expectedSuffix, actual[^expectedSuffix.Length..]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NativeOpenConnection3Version6SerializerAddsObservedPrefixBeforeContent()
|
||||
{
|
||||
HistorianOpen2Request request = new(
|
||||
HostName: "H",
|
||||
ProcessName: "P",
|
||||
ProcessId: 0x01020304,
|
||||
UserName: string.Empty,
|
||||
Password: [0xAA, 0xBB],
|
||||
ClientType: 4,
|
||||
ClientVersion: 11,
|
||||
ConnectionMode: 1026,
|
||||
MetadataNamespace: HistorianMetadataNamespace.Empty);
|
||||
HistorianClientCommonInfo commonInfo = new(
|
||||
FormatVersion: 3,
|
||||
ServerNodeName: "S",
|
||||
ClientNodeName: "C",
|
||||
ProcessId: 0x11223344,
|
||||
HcalVersion: 17,
|
||||
ProcessName: "Proc",
|
||||
Proxy: string.Empty,
|
||||
DataSourceId: string.Empty,
|
||||
ShardId: new Guid("00112233-4455-6677-8899-aabbccddeeff"),
|
||||
ClientVersion: 0x55667788,
|
||||
ClientTimestamp: 0x0102030405060708,
|
||||
ClientDllVersion: string.Empty);
|
||||
|
||||
byte[] actual = HistorianOpen2Protocol.SerializeNativeOpenConnection3Version6(
|
||||
request,
|
||||
commonInfo,
|
||||
new Guid("00112233-4455-6677-8899-aabbccddeeff"));
|
||||
|
||||
byte[] expectedPrefix =
|
||||
[
|
||||
0x06,
|
||||
0x33, 0x22, 0x11, 0x00,
|
||||
0x55, 0x44,
|
||||
0x77, 0x66,
|
||||
0x88, 0x99, 0xAA, 0xBB,
|
||||
0xCC, 0xDD, 0xEE, 0xFF,
|
||||
0x00
|
||||
];
|
||||
Assert.Equal(expectedPrefix, actual[..expectedPrefix.Length]);
|
||||
byte[] expectedContentPrefix =
|
||||
[
|
||||
0x01, 0x00, 0x00, 0x00, 0x48, 0x00,
|
||||
0x02, 0x00, 0xAA, 0xBB,
|
||||
0x04,
|
||||
0x02, 0x04, 0x00, 0x00,
|
||||
0x01,
|
||||
0x01, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00
|
||||
];
|
||||
Assert.Equal(expectedContentPrefix, actual[expectedPrefix.Length..(expectedPrefix.Length + expectedContentPrefix.Length)]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NativeOpenConnection3Version6SerializerCanUseSeparateCredentialBlock()
|
||||
{
|
||||
HistorianOpen2Request request = new(
|
||||
HostName: "H",
|
||||
ProcessName: "P",
|
||||
ProcessId: 0x01020304,
|
||||
UserName: string.Empty,
|
||||
Password: [0xAA, 0xBB],
|
||||
ClientType: 4,
|
||||
ClientVersion: 11,
|
||||
ConnectionMode: 1026,
|
||||
MetadataNamespace: HistorianMetadataNamespace.Empty);
|
||||
HistorianClientCommonInfo commonInfo = new(
|
||||
FormatVersion: 2,
|
||||
ServerNodeName: string.Empty,
|
||||
ClientNodeName: string.Empty,
|
||||
ProcessId: 0,
|
||||
HcalVersion: 17,
|
||||
ProcessName: string.Empty,
|
||||
Proxy: string.Empty,
|
||||
DataSourceId: string.Empty,
|
||||
ShardId: Guid.Empty,
|
||||
ClientVersion: 0,
|
||||
ClientTimestamp: 0,
|
||||
ClientDllVersion: string.Empty);
|
||||
|
||||
byte[] actual = HistorianOpen2Protocol.SerializeNativeOpenConnection3Version6(
|
||||
request,
|
||||
commonInfo,
|
||||
Guid.Empty,
|
||||
[0x00, 0x00, 0x00, 0x00]);
|
||||
|
||||
int hostLengthOffset = 18;
|
||||
int credentialLengthOffset = hostLengthOffset + 4 + Encoding.Unicode.GetByteCount("H");
|
||||
Assert.Equal([0x04, 0x00], actual[credentialLengthOffset..(credentialLengthOffset + 2)]);
|
||||
Assert.Equal([0x00, 0x00, 0x00, 0x00], actual[(credentialLengthOffset + 2)..(credentialLengthOffset + 6)]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user