|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Buffers;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.AspNetCore.Internal;
using Microsoft.AspNetCore.SignalR.Internal;
using Xunit;
namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Formatters;
public partial class BinaryMessageFormatterTests
{
[Fact]
public void WriteMultipleMessages()
{
var expectedEncoding = new byte[]
{
/* length: */ 0x00,
/* body: <empty> */
/* length: */ 0x0E,
/* body: */ 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x2C, 0x0D, 0x0A, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21,
};
var messages = new[]
{
new byte[0],
Encoding.UTF8.GetBytes("Hello,\r\nWorld!")
};
var writer = MemoryBufferWriter.Get(); // Use small chunks to test Advance/Enlarge and partial payload writing
try
{
foreach (var message in messages)
{
BinaryMessageFormatter.WriteLengthPrefix(message.Length, writer);
writer.Write(message);
}
Assert.Equal(expectedEncoding, writer.ToArray());
}
finally
{
MemoryBufferWriter.Return(writer);
}
}
[Theory]
[InlineData(new byte[] { 0x00 }, new byte[0])]
[InlineData(new byte[]
{
0x80, 0x01, // Size - 128
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f
},
new byte[]
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f
})]
[InlineData(new byte[] { 0x04, 0xAB, 0xCD, 0xEF, 0x12 }, new byte[] { 0xAB, 0xCD, 0xEF, 0x12 })]
public void WriteBinaryMessage(byte[] encoded, byte[] payload)
{
var writer = MemoryBufferWriter.Get();
try
{
BinaryMessageFormatter.WriteLengthPrefix(payload.Length, writer);
writer.Write(payload);
Assert.Equal(encoded, writer.ToArray());
}
finally
{
MemoryBufferWriter.Return(writer);
}
}
[Theory]
[InlineData(new byte[] { 0x00 }, "")]
[InlineData(new byte[] { 0x03, 0x41, 0x42, 0x43 }, "ABC")]
[InlineData(new byte[] { 0x0B, 0x41, 0x0A, 0x52, 0x0D, 0x43, 0x0D, 0x0A, 0x3B, 0x44, 0x45, 0x46 }, "A\nR\rC\r\n;DEF")]
public void WriteTextMessage(byte[] encoded, string payload)
{
var message = Encoding.UTF8.GetBytes(payload);
var writer = MemoryBufferWriter.Get();
try
{
BinaryMessageFormatter.WriteLengthPrefix(message.Length, writer);
writer.Write(message);
Assert.Equal(encoded, writer.ToArray());
}
finally
{
MemoryBufferWriter.Return(writer);
}
}
[Theory]
[MemberData(nameof(RandomPayloads))]
public void RoundTrippingTest(byte[] payload)
{
var writer = MemoryBufferWriter.Get();
try
{
BinaryMessageFormatter.WriteLengthPrefix(payload.Length, writer);
writer.Write(payload);
var buffer = new ReadOnlySequence<byte>(writer.ToArray());
Assert.True(BinaryMessageParser.TryParseMessage(ref buffer, out var roundtripped));
Assert.Equal(payload, roundtripped.ToArray());
}
finally
{
MemoryBufferWriter.Return(writer);
}
}
public static IEnumerable<object[]> RandomPayloads()
{
// boundaries
yield return new[] { CreatePayload(0) };
yield return new[] { CreatePayload(1) };
yield return new[] { CreatePayload(0x7f) };
yield return new[] { CreatePayload(0x80) };
yield return new[] { CreatePayload(0x3fff) };
yield return new[] { CreatePayload(0x4000) };
// random
yield return new[] { CreatePayload(0xc0de) };
}
private static byte[] CreatePayload(int size) =>
Enumerable.Range(0, size).Select(n => (byte)(n & 0xff)).ToArray();
}
|