using SuiteLink.Client.Protocol; namespace SuiteLink.Client.Tests.Protocol; public sealed class SuiteLinkConnectCodecTests { [Fact] public void EncodeConnect_WritesConnectMessageTypeAndEndMarker() { var options = new SuiteLinkConnectionOptions( host: "127.0.0.1", application: "App", topic: "Topic", clientName: "Client", clientNode: "Node", userName: "User", serverNode: "Server", timezone: "UTC"); var bytes = SuiteLinkConnectCodec.Encode(options); Assert.Equal(0x80, bytes[2]); Assert.Equal(0x01, bytes[3]); Assert.Equal(0xA5, bytes[^1]); } [Fact] public void EncodeConnect_WritesExpectedFieldOrderReservedSegmentsAndTimezoneStrings() { var options = new SuiteLinkConnectionOptions( host: "127.0.0.1", application: "App", topic: "Topic", clientName: "Client", clientNode: "Node", userName: "User", serverNode: "Server", timezone: "UTC"); var bytes = SuiteLinkConnectCodec.Encode(options); var frame = SuiteLinkFrameReader.ParseFrame(bytes); var payload = frame.Payload.Span; var index = 0; var app = SuiteLinkEncoding.EncodeLengthPrefixedUtf16("App"); Assert.True(payload[index..].StartsWith(app)); index += app.Length; var topic = SuiteLinkEncoding.EncodeLengthPrefixedUtf16("Topic"); Assert.True(payload[index..].StartsWith(topic)); index += topic.Length; Assert.True(payload[index..(index + 3)].ToArray().All(static b => b == 0x00)); index += 3; var client = SuiteLinkEncoding.EncodeLengthPrefixedUtf16("Client"); Assert.True(payload[index..].StartsWith(client)); index += client.Length; var clientNode = SuiteLinkEncoding.EncodeLengthPrefixedUtf16("Node"); Assert.True(payload[index..].StartsWith(clientNode)); index += clientNode.Length; var user = SuiteLinkEncoding.EncodeLengthPrefixedUtf16("User"); Assert.True(payload[index..].StartsWith(user)); index += user.Length; var serverNode = SuiteLinkEncoding.EncodeLengthPrefixedUtf16("Server"); Assert.True(payload[index..].StartsWith(serverNode)); index += serverNode.Length; Assert.True(payload[index..(index + 20)].ToArray().All(static b => b == 0x00)); index += 20; var timezone1 = SuiteLinkEncoding.DecodeNullTerminatedUtf16(payload[index..], out var timezone1ConsumedBytes); index += timezone1ConsumedBytes; Assert.Equal("UTC", timezone1); Assert.True(payload[index..(index + 38)].ToArray().All(static b => b == 0x00)); index += 38; var timezone2 = SuiteLinkEncoding.DecodeNullTerminatedUtf16(payload[index..], out var timezone2ConsumedBytes); index += timezone2ConsumedBytes; Assert.Equal("UTC", timezone2); Assert.Equal(timezone1, timezone2); Assert.Equal(payload.Length, index); } [Fact] public void EncodeConnect_WhenTimezoneNotProvided_UsesUtcDefault() { var options = new SuiteLinkConnectionOptions( host: "127.0.0.1", application: "App", topic: "Topic", clientName: "Client", clientNode: "Node", userName: "User", serverNode: "Server"); var frame = SuiteLinkFrameReader.ParseFrame(SuiteLinkConnectCodec.Encode(options)); var payload = frame.Payload.Span; var index = 0; index += SuiteLinkEncoding.EncodeLengthPrefixedUtf16("App").Length; index += SuiteLinkEncoding.EncodeLengthPrefixedUtf16("Topic").Length; index += 3; index += SuiteLinkEncoding.EncodeLengthPrefixedUtf16("Client").Length; index += SuiteLinkEncoding.EncodeLengthPrefixedUtf16("Node").Length; index += SuiteLinkEncoding.EncodeLengthPrefixedUtf16("User").Length; index += SuiteLinkEncoding.EncodeLengthPrefixedUtf16("Server").Length; index += 20; var timezone1 = SuiteLinkEncoding.DecodeNullTerminatedUtf16(payload[index..], out var timezone1ConsumedBytes); index += timezone1ConsumedBytes + 38; var timezone2 = SuiteLinkEncoding.DecodeNullTerminatedUtf16(payload[index..], out _); Assert.Equal("UTC", timezone1); Assert.Equal("UTC", timezone2); } }