91 lines
3.5 KiB
C#
91 lines
3.5 KiB
C#
// Copyright (c) .NET Foundation. All rights reserved.
|
||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Text;
|
||
using Microsoft.AspNetCore.SignalR.Internal.Encoders;
|
||
using Xunit;
|
||
|
||
namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Encoders
|
||
{
|
||
public class LengthPrefixedTextMessageParserTests
|
||
{
|
||
[Theory]
|
||
[InlineData("0:;", "")]
|
||
[InlineData("3:ABC;", "ABC")]
|
||
[InlineData("11:A\nR\rC\r\n;DEF;", "A\nR\rC\r\n;DEF")]
|
||
[InlineData("12:Hello, World;", "Hello, World")]
|
||
public void ReadTextMessage(string encoded, string payload)
|
||
{
|
||
ReadOnlySpan<byte> buffer = Encoding.UTF8.GetBytes(encoded);
|
||
|
||
Assert.True(LengthPrefixedTextMessageParser.TryParseMessage(ref buffer, out var message));
|
||
Assert.Equal(0, buffer.Length);
|
||
Assert.Equal(Encoding.UTF8.GetBytes(payload), message.ToArray());
|
||
}
|
||
|
||
[Fact]
|
||
public void ReadMultipleMessages()
|
||
{
|
||
const string encoded = "0:;14:Hello,\r\nWorld!;";
|
||
ReadOnlySpan<byte> buffer = Encoding.UTF8.GetBytes(encoded);
|
||
|
||
var messages = new List<byte[]>();
|
||
while (LengthPrefixedTextMessageParser.TryParseMessage(ref buffer, out var message))
|
||
{
|
||
messages.Add(message.ToArray());
|
||
}
|
||
|
||
Assert.Equal(0, buffer.Length);
|
||
|
||
Assert.Equal(2, messages.Count);
|
||
Assert.Equal(new byte[0], messages[0]);
|
||
Assert.Equal(Encoding.UTF8.GetBytes("Hello,\r\nWorld!"), messages[1]);
|
||
}
|
||
|
||
[Theory]
|
||
[InlineData("")]
|
||
[InlineData("ABC")]
|
||
[InlineData("1230450945")]
|
||
[InlineData("1:")]
|
||
[InlineData("10")]
|
||
[InlineData("5:A")]
|
||
[InlineData("5:ABCDE")]
|
||
public void ReadIncompleteMessages(string encoded)
|
||
{
|
||
ReadOnlySpan<byte> buffer = Encoding.UTF8.GetBytes(encoded);
|
||
Assert.False(LengthPrefixedTextMessageParser.TryParseMessage(ref buffer, out _));
|
||
}
|
||
|
||
[Theory]
|
||
[InlineData("X:", "Invalid length: 'X'")]
|
||
[InlineData("1:asdf", "Missing delimiter ';' after payload")]
|
||
[InlineData("1029348109238412903849023841290834901283409128349018239048102394:ABCDEF", "Invalid length: '1029348109238412903849023841290834901283409128349018239048102394'")]
|
||
[InlineData("12ab34:", "Invalid length: '12ab34'")]
|
||
[InlineData("5:ABCDEF", "Missing delimiter ';' after payload")]
|
||
public void ReadInvalidMessages(string encoded, string expectedMessage)
|
||
{
|
||
var ex = Assert.Throws<FormatException>(() =>
|
||
{
|
||
ReadOnlySpan<byte> buffer = Encoding.UTF8.GetBytes(encoded);
|
||
LengthPrefixedTextMessageParser.TryParseMessage(ref buffer, out _);
|
||
});
|
||
Assert.Equal(expectedMessage, ex.Message);
|
||
}
|
||
|
||
[Fact]
|
||
public void ReadInvalidEncodedMessage()
|
||
{
|
||
var ex = Assert.Throws<FormatException>(() =>
|
||
{
|
||
// Invalid because first character is a UTF-8 "continuation" character
|
||
// We need to include the ':' so that
|
||
ReadOnlySpan<byte> buffer = new byte[] { 0x48, 0x65, 0x80, 0x6C, 0x6F, (byte)':' };
|
||
LengthPrefixedTextMessageParser.TryParseMessage(ref buffer, out _);
|
||
});
|
||
Assert.Equal("Invalid length: 'He<48>lo'", ex.Message);
|
||
}
|
||
}
|
||
}
|