feat: bootstrap suitelink tag client codecs

This commit is contained in:
Joseph Doherty
2026-03-16 14:43:31 -04:00
commit 731bfe2237
30 changed files with 3429 additions and 0 deletions

View File

@@ -0,0 +1,122 @@
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);
}
}