Files
suitelinkclient/tests/SuiteLink.Client.Tests/Protocol/SuiteLinkEncodingTests.cs
2026-03-16 14:43:31 -04:00

112 lines
3.4 KiB
C#

using SuiteLink.Client.Protocol;
namespace SuiteLink.Client.Tests.Protocol;
public sealed class SuiteLinkEncodingTests
{
[Fact]
public void EncodeLengthPrefixedUtf16_WithAsciiText_WritesCharacterCountAndUtf16Bytes()
{
var bytes = SuiteLinkEncoding.EncodeLengthPrefixedUtf16("AB");
Assert.Equal(new byte[] { 0x02, 0x41, 0x00, 0x42, 0x00 }, bytes);
}
[Fact]
public void DecodeNullTerminatedUtf16_ReadsStringAndConsumedBytes()
{
var buffer = new byte[] { 0x48, 0x00, 0x69, 0x00, 0x00, 0x00, 0x20, 0x00 };
var text = SuiteLinkEncoding.DecodeNullTerminatedUtf16(buffer, out var consumed);
Assert.Equal("Hi", text);
Assert.Equal(6, consumed);
}
[Fact]
public void WriteAndReadUInt32LittleEndian_RoundTripsValue()
{
Span<byte> bytes = stackalloc byte[4];
SuiteLinkEncoding.WriteUInt32LittleEndian(bytes, 0x11223344);
var value = SuiteLinkEncoding.ReadUInt32LittleEndian(bytes);
Assert.Equal((uint)0x11223344, value);
Assert.Equal(new byte[] { 0x44, 0x33, 0x22, 0x11 }, bytes.ToArray());
}
[Fact]
public void FileTimeToUtcDateTime_ConvertsKnownEpochValue()
{
const long unixEpochFileTime = 116444736000000000L;
var value = SuiteLinkEncoding.FileTimeToUtcDateTime(unixEpochFileTime);
Assert.Equal(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc), value);
}
[Fact]
public void DecodeNullTerminatedUtf16_WithOddLength_ThrowsFormatException()
{
var buffer = new byte[] { 0x41, 0x00, 0x00 };
Assert.Throws<FormatException>(() => SuiteLinkEncoding.DecodeNullTerminatedUtf16(buffer, out _));
}
[Fact]
public void DecodeNullTerminatedUtf16_WithoutNullTerminator_ThrowsFormatException()
{
var buffer = new byte[] { 0x41, 0x00, 0x42, 0x00 };
Assert.Throws<FormatException>(() => SuiteLinkEncoding.DecodeNullTerminatedUtf16(buffer, out _));
}
[Fact]
public void EncodeLengthPrefixedUtf16_WhenInputIsTooLong_ThrowsArgumentOutOfRangeException()
{
var value = new string('A', 256);
Assert.Throws<ArgumentOutOfRangeException>(() => SuiteLinkEncoding.EncodeLengthPrefixedUtf16(value));
}
[Fact]
public void EncodeLengthPrefixedUtf16_WithSurrogatePair_PrefixUsesUtf16CodeUnits()
{
var bytes = SuiteLinkEncoding.EncodeLengthPrefixedUtf16("A\U0001F600");
Assert.Equal(3, bytes[0]);
}
[Fact]
public void ReadUInt32LittleEndian_WhenInputIsTooShort_ThrowsFormatException()
{
var buffer = new byte[] { 0x01, 0x02, 0x03 };
Assert.Throws<FormatException>(() => SuiteLinkEncoding.ReadUInt32LittleEndian(buffer));
}
[Fact]
public void WriteAndReadSingleLittleEndian_RoundTripsNonTrivialValue()
{
Span<byte> bytes = stackalloc byte[4];
const float expected = 123.4567f;
SuiteLinkEncoding.WriteSingleLittleEndian(bytes, expected);
var value = SuiteLinkEncoding.ReadSingleLittleEndian(bytes);
Assert.Equal(expected, value);
}
[Fact]
public void WriteAndReadSingleLittleEndian_RoundTripsNaN()
{
Span<byte> bytes = stackalloc byte[4];
var expected = float.NaN;
SuiteLinkEncoding.WriteSingleLittleEndian(bytes, expected);
var value = SuiteLinkEncoding.ReadSingleLittleEndian(bytes);
Assert.True(float.IsNaN(value));
}
}