fix: Fixes SpanWriter/SpanReader tests (#2263)
This commit is contained in:
parent
68caaab92c
commit
6f5b7f7a6b
3 changed files with 1171 additions and 46 deletions
597
Projects/Server.Tests/Tests/Buffers/SpanReaderTests.cs
Normal file
597
Projects/Server.Tests/Tests/Buffers/SpanReaderTests.cs
Normal file
|
|
@ -0,0 +1,597 @@
|
|||
using System;
|
||||
using System.Buffers;
|
||||
using System.IO;
|
||||
using Xunit;
|
||||
|
||||
namespace Server.Tests;
|
||||
|
||||
public class SpanReaderTests
|
||||
{
|
||||
[Fact]
|
||||
public void TestReadByte()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = [0x12, 0x34];
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
Assert.Equal(0x12, reader.ReadByte());
|
||||
Assert.Equal(0x34, reader.ReadByte());
|
||||
Assert.Equal(2, reader.Position);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadByteAtEnd()
|
||||
{
|
||||
Assert.Throws<EndOfStreamException>(
|
||||
() =>
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = [0x12];
|
||||
var reader = new SpanReader(buffer);
|
||||
reader.ReadByte();
|
||||
reader.ReadByte();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadBoolean()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = [0, 1, 2, 255];
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
Assert.False(reader.ReadBoolean());
|
||||
Assert.True(reader.ReadBoolean());
|
||||
Assert.True(reader.ReadBoolean());
|
||||
Assert.True(reader.ReadBoolean());
|
||||
Assert.Equal(4, reader.Position);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadSByte()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = [0xFF, 0x7F];
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
Assert.Equal(-1, reader.ReadSByte());
|
||||
Assert.Equal(127, reader.ReadSByte());
|
||||
Assert.Equal(2, reader.Position);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadInt16BigEndian()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = [0x12, 0x34];
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
Assert.Equal(0x1234, reader.ReadInt16());
|
||||
Assert.Equal(2, reader.Position);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadInt16LittleEndian()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = [0x34, 0x12];
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
Assert.Equal(0x1234, reader.ReadInt16LE());
|
||||
Assert.Equal(2, reader.Position);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadInt16AtEnd()
|
||||
{
|
||||
Assert.Throws<EndOfStreamException>(
|
||||
() =>
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = [0x12];
|
||||
var reader = new SpanReader(buffer);
|
||||
reader.ReadInt16();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadUInt16BigEndian()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = [0x12, 0x34];
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
Assert.Equal((ushort)0x1234, reader.ReadUInt16());
|
||||
Assert.Equal(2, reader.Position);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadUInt16LittleEndian()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = [0x34, 0x12];
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
Assert.Equal((ushort)0x1234, reader.ReadUInt16LE());
|
||||
Assert.Equal(2, reader.Position);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadInt32BigEndian()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = [0x12, 0x34, 0x56, 0x78];
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
Assert.Equal(0x12345678, reader.ReadInt32());
|
||||
Assert.Equal(4, reader.Position);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadInt32AtEnd()
|
||||
{
|
||||
Assert.Throws<EndOfStreamException>(
|
||||
() =>
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = [0x12, 0x34, 0x56];
|
||||
var reader = new SpanReader(buffer);
|
||||
reader.ReadInt32();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadUInt32BigEndian()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = [0x12, 0x34, 0x56, 0x78];
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
Assert.Equal(0x12345678u, reader.ReadUInt32());
|
||||
Assert.Equal(4, reader.Position);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadUInt32LittleEndian()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = [0x78, 0x56, 0x34, 0x12];
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
Assert.Equal(0x12345678u, reader.ReadUInt32LE());
|
||||
Assert.Equal(4, reader.Position);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadInt64BigEndian()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = [0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0];
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
Assert.Equal(0x123456789ABCDEF0L, reader.ReadInt64());
|
||||
Assert.Equal(8, reader.Position);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadInt64AtEnd()
|
||||
{
|
||||
Assert.Throws<EndOfStreamException>(
|
||||
() =>
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = [0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE];
|
||||
var reader = new SpanReader(buffer);
|
||||
reader.ReadInt64();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadUInt64BigEndian()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = [0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0];
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
Assert.Equal(0x123456789ABCDEF0UL, reader.ReadUInt64());
|
||||
Assert.Equal(8, reader.Position);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadAsciiString()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = "Hello"u8;
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
var result = reader.ReadAscii();
|
||||
|
||||
Assert.Equal("Hello", result);
|
||||
Assert.Equal(5, reader.Position);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadAsciiStringWithNull()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = "Hel\0o"u8;
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
var result = reader.ReadAscii();
|
||||
|
||||
Assert.Equal("Hel", result);
|
||||
Assert.Equal(4, reader.Position);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadAsciiStringFixedLength()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = "Hello\0\0\0\0\0"u8;
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
var result = reader.ReadAscii(10);
|
||||
|
||||
Assert.Equal("Hello", result);
|
||||
Assert.Equal(10, reader.Position);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadAsciiStringFixedLengthTooLarge()
|
||||
{
|
||||
Assert.Throws<EndOfStreamException>(
|
||||
() =>
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = "Hel"u8;
|
||||
var reader = new SpanReader(buffer);
|
||||
reader.ReadAscii(10);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadAsciiSafe()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = [(byte)'H', (byte)'e', 0xFF, (byte)'l', (byte)'o'];
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
var result = reader.ReadAsciiSafe();
|
||||
|
||||
Assert.Equal("He?lo", result);
|
||||
Assert.Equal(5, reader.Position);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadUTF8String()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = "Hello"u8;
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
var result = reader.ReadUTF8();
|
||||
|
||||
Assert.Equal("Hello", result);
|
||||
Assert.Equal(5, reader.Position);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadUTF8StringWithNull()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = "Hi\0Bye"u8;
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
var result = reader.ReadUTF8();
|
||||
|
||||
Assert.Equal("Hi", result);
|
||||
Assert.Equal(3, reader.Position);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadLittleUniString()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = "H\0i\0"u8;
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
var result = reader.ReadLittleUni();
|
||||
|
||||
Assert.Equal("Hi", result);
|
||||
Assert.Equal(4, reader.Position);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadLittleUniStringWithNull()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = "H\0i\0\0\0X\0"u8;
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
var result = reader.ReadLittleUni();
|
||||
|
||||
Assert.Equal("Hi", result);
|
||||
Assert.Equal(5, reader.Position);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadLittleUniStringFixedLength()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = "H\0i\0\0\0\0\0"u8;
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
var result = reader.ReadLittleUni(4);
|
||||
|
||||
Assert.Equal("Hi", result);
|
||||
Assert.Equal(8, reader.Position);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadLittleUniSafe()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = [(byte)'H', 0, 0xFF, 0xD8, (byte)'i', 0];
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
var result = reader.ReadLittleUniSafe();
|
||||
|
||||
Assert.Equal("H\uFFFDi", result);
|
||||
Assert.Equal(6, reader.Position);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadBigUniString()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = "\0H\0i"u8;
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
var result = reader.ReadBigUni();
|
||||
|
||||
Assert.Equal("Hi", result);
|
||||
Assert.Equal(4, reader.Position);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadBigUniStringWithNull()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = "\0H\0i\0\0\0X"u8;
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
var result = reader.ReadBigUni();
|
||||
|
||||
Assert.Equal("Hi", result);
|
||||
Assert.Equal(5, reader.Position);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadBigUniStringFixedLength()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = "\0H\0i\0\0\0\0"u8;
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
var result = reader.ReadBigUni(4);
|
||||
|
||||
Assert.Equal("Hi", result);
|
||||
Assert.Equal(8, reader.Position);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadBigUniSafe()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = [0, (byte)'H', 0xD8, 0xFF, 0, (byte)'i'];
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
var result = reader.ReadBigUniSafe();
|
||||
|
||||
Assert.Equal("H\uFFFDi", result);
|
||||
Assert.Equal(6, reader.Position);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestSeekBegin()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = [0x01, 0x02, 0x03, 0x04, 0x05];
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
reader.ReadByte();
|
||||
reader.ReadByte();
|
||||
|
||||
var pos = reader.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
Assert.Equal(0, pos);
|
||||
Assert.Equal(0, reader.Position);
|
||||
Assert.Equal(0x01, reader.ReadByte());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestSeekCurrent()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = [0x01, 0x02, 0x03, 0x04, 0x05];
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
reader.ReadByte();
|
||||
var pos = reader.Seek(2, SeekOrigin.Current);
|
||||
|
||||
Assert.Equal(3, pos);
|
||||
Assert.Equal(3, reader.Position);
|
||||
Assert.Equal(0x04, reader.ReadByte());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestSeekEnd()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = [0x01, 0x02, 0x03, 0x04, 0x05];
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
var pos = reader.Seek(-2, SeekOrigin.End);
|
||||
|
||||
Assert.Equal(3, pos);
|
||||
Assert.Equal(3, reader.Position);
|
||||
Assert.Equal(0x04, reader.ReadByte());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestSeekNegativeThrows()
|
||||
{
|
||||
Assert.Throws<ArgumentOutOfRangeException>(
|
||||
() =>
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = [0x01, 0x02, 0x03];
|
||||
var reader = new SpanReader(buffer);
|
||||
reader.Seek(-1, SeekOrigin.Begin);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestSeekBeyondEndThrows()
|
||||
{
|
||||
Assert.Throws<ArgumentOutOfRangeException>(
|
||||
() =>
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = [0x01, 0x02, 0x03];
|
||||
var reader = new SpanReader(buffer);
|
||||
reader.Seek(10, SeekOrigin.Begin);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestRead()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = [0x01, 0x02, 0x03, 0x04, 0x05];
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
Span<byte> dest = stackalloc byte[3];
|
||||
var bytesRead = reader.Read(dest);
|
||||
|
||||
Assert.Equal(3, bytesRead);
|
||||
Assert.Equal(3, reader.Position);
|
||||
AssertThat.Equal(dest, [0x01, 0x02, 0x03]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadPartial()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = [0x01, 0x02, 0x03];
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
Span<byte> dest = stackalloc byte[5];
|
||||
var bytesRead = reader.Read(dest);
|
||||
|
||||
Assert.Equal(3, bytesRead);
|
||||
Assert.Equal(3, reader.Position);
|
||||
AssertThat.Equal(dest[..3], [0x01, 0x02, 0x03]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadEmpty()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = [0x01, 0x02, 0x03];
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
Span<byte> dest = [];
|
||||
var bytesRead = reader.Read(dest);
|
||||
|
||||
Assert.Equal(0, bytesRead);
|
||||
Assert.Equal(0, reader.Position);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadAtEnd()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = [0x01, 0x02, 0x03];
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
reader.Seek(3, SeekOrigin.Begin);
|
||||
|
||||
Span<byte> dest = stackalloc byte[5];
|
||||
var bytesRead = reader.Read(dest);
|
||||
|
||||
Assert.Equal(0, bytesRead);
|
||||
Assert.Equal(3, reader.Position);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestLength()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = [0x01, 0x02, 0x03, 0x04, 0x05];
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
Assert.Equal(5, reader.Length);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestPosition()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = [0x01, 0x02, 0x03];
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
Assert.Equal(0, reader.Position);
|
||||
|
||||
reader.ReadByte();
|
||||
Assert.Equal(1, reader.Position);
|
||||
|
||||
reader.ReadUInt16();
|
||||
Assert.Equal(3, reader.Position);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestRemaining()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = [0x01, 0x02, 0x03, 0x04, 0x05];
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
Assert.Equal(5, reader.Remaining);
|
||||
|
||||
reader.ReadByte();
|
||||
Assert.Equal(4, reader.Remaining);
|
||||
|
||||
reader.ReadUInt16();
|
||||
Assert.Equal(2, reader.Remaining);
|
||||
|
||||
reader.ReadUInt16();
|
||||
Assert.Equal(0, reader.Remaining);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestBuffer()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = [0x01, 0x02, 0x03];
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
var bufferProperty = reader.Buffer;
|
||||
|
||||
Assert.Equal(3, bufferProperty.Length);
|
||||
AssertThat.Equal(bufferProperty, buffer);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadStringEmptyFixedLength()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = [0x01, 0x02, 0x03];
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
var result = reader.ReadAscii(0);
|
||||
|
||||
Assert.Equal("", result);
|
||||
Assert.Equal(0, reader.Position);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadMultipleStringsWithNullTerminators()
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = "AB\0CD\0EF"u8;
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
Assert.Equal("AB", reader.ReadAscii());
|
||||
Assert.Equal("CD", reader.ReadAscii());
|
||||
Assert.Equal("EF", reader.ReadAscii());
|
||||
Assert.Equal(8, reader.Position);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadLittleUniOddByteCount()
|
||||
{
|
||||
// If buffer has odd number of bytes, the last byte should be ignored
|
||||
ReadOnlySpan<byte> buffer = [(byte)'H', 0, (byte)'i', 0, 0xFF];
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
var result = reader.ReadLittleUni();
|
||||
|
||||
Assert.Equal("Hi", result);
|
||||
Assert.Equal(4, reader.Position);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadBigUniOddByteCount()
|
||||
{
|
||||
// If buffer has odd number of bytes, the last byte should be ignored
|
||||
ReadOnlySpan<byte> buffer = [0, (byte)'H', 0, (byte)'i', 0xFF];
|
||||
var reader = new SpanReader(buffer);
|
||||
|
||||
var result = reader.ReadBigUni();
|
||||
|
||||
Assert.Equal("Hi", result);
|
||||
Assert.Equal(4, reader.Position);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,63 +1,591 @@
|
|||
using System;
|
||||
using System.Buffers;
|
||||
using System.IO;
|
||||
using Xunit;
|
||||
|
||||
namespace Server.Tests
|
||||
namespace Server.Tests;
|
||||
|
||||
public class SpanWriterTests
|
||||
{
|
||||
public class SpanWriterTests
|
||||
[Fact]
|
||||
public unsafe void TestSpanWriterResizes()
|
||||
{
|
||||
[Fact]
|
||||
public unsafe void TestSpanWriterResizes()
|
||||
{
|
||||
Span<byte> smallStack = stackalloc byte[8];
|
||||
using var writer = new SpanWriter(smallStack, true);
|
||||
writer.Write(0x1024L);
|
||||
writer.Write(0x1024L);
|
||||
Span<byte> smallStack = stackalloc byte[8];
|
||||
var writer = new SpanWriter(smallStack, true);
|
||||
writer.Write(0x1024L);
|
||||
writer.Write(0x1024L);
|
||||
|
||||
var span = writer.RawBuffer;
|
||||
fixed (byte* spanPtr = span)
|
||||
var span = writer.RawBuffer;
|
||||
fixed (byte* spanPtr = span)
|
||||
{
|
||||
fixed (byte* stackPtr = smallStack)
|
||||
{
|
||||
fixed (byte* stackPtr = smallStack)
|
||||
{
|
||||
Assert.True(spanPtr != stackPtr);
|
||||
}
|
||||
Assert.True(spanPtr != stackPtr);
|
||||
}
|
||||
|
||||
Assert.True(span.Length > smallStack.Length);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public unsafe void TestSpanWriterOnlyStackAlloc()
|
||||
{
|
||||
Span<byte> smallStack = stackalloc byte[8];
|
||||
using var writer = new SpanWriter(smallStack, true);
|
||||
writer.Write(0x1024L);
|
||||
Assert.True(span.Length > smallStack.Length);
|
||||
writer.Dispose();
|
||||
}
|
||||
|
||||
var span = writer.RawBuffer;
|
||||
fixed (byte* spanPtr = span)
|
||||
[Fact]
|
||||
public unsafe void TestSpanWriterOnlyStackAlloc()
|
||||
{
|
||||
Span<byte> smallStack = stackalloc byte[8];
|
||||
var writer = new SpanWriter(smallStack, true);
|
||||
writer.Write(0x1024L);
|
||||
|
||||
var span = writer.RawBuffer;
|
||||
fixed (byte* spanPtr = span)
|
||||
{
|
||||
fixed (byte* stackPtr = smallStack)
|
||||
{
|
||||
fixed (byte* stackPtr = smallStack)
|
||||
{
|
||||
Assert.True(spanPtr == stackPtr);
|
||||
}
|
||||
Assert.True(spanPtr == stackPtr);
|
||||
}
|
||||
|
||||
Assert.True(span.Length == smallStack.Length);
|
||||
AssertThat.Equal(smallStack, stackalloc byte[] { 0, 0, 0, 0, 0, 0, 0x10, 0x24 });
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestSpanWriterNoResizeThrows()
|
||||
{
|
||||
Assert.Throws<OutOfMemoryException>(
|
||||
() =>
|
||||
{
|
||||
Span<byte> smallStack = stackalloc byte[8];
|
||||
using var writer = new SpanWriter(smallStack);
|
||||
writer.Write(0x1024L);
|
||||
writer.Write(0x1024L);
|
||||
}
|
||||
);
|
||||
}
|
||||
Assert.Equal(8, span.Length);
|
||||
AssertThat.Equal(smallStack, [0, 0, 0, 0, 0, 0, 0x10, 0x24]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestSpanWriterNoResizeThrows()
|
||||
{
|
||||
Assert.Throws<InvalidOperationException>(
|
||||
() =>
|
||||
{
|
||||
Span<byte> smallStack = stackalloc byte[8];
|
||||
var writer = new SpanWriter(smallStack);
|
||||
writer.Write(0x1024L);
|
||||
writer.Write(0x1024L);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestWriteBool()
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[2];
|
||||
var writer = new SpanWriter(buffer);
|
||||
|
||||
writer.Write(true);
|
||||
writer.Write(false);
|
||||
|
||||
Assert.Equal(2, writer.Position);
|
||||
AssertThat.Equal(writer.Span, [1, 0]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestWriteByte()
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[2];
|
||||
var writer = new SpanWriter(buffer);
|
||||
|
||||
writer.Write((byte)0x12);
|
||||
writer.Write((byte)0x34);
|
||||
|
||||
Assert.Equal(2, writer.Position);
|
||||
AssertThat.Equal(writer.Span, [0x12, 0x34]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestWriteSByte()
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[2];
|
||||
var writer = new SpanWriter(buffer);
|
||||
|
||||
writer.Write((sbyte)-1);
|
||||
writer.Write((sbyte)127);
|
||||
|
||||
Assert.Equal(2, writer.Position);
|
||||
AssertThat.Equal(writer.Span, [0xFF, 0x7F]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestWriteInt16BigEndian()
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[2];
|
||||
var writer = new SpanWriter(buffer);
|
||||
|
||||
writer.Write((short)0x1234);
|
||||
|
||||
Assert.Equal(2, writer.Position);
|
||||
AssertThat.Equal(writer.Span, [0x12, 0x34]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestWriteInt16LittleEndian()
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[2];
|
||||
var writer = new SpanWriter(buffer);
|
||||
|
||||
writer.WriteLE((short)0x1234);
|
||||
|
||||
Assert.Equal(2, writer.Position);
|
||||
AssertThat.Equal(writer.Span, [0x34, 0x12]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestWriteUInt16BigEndian()
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[2];
|
||||
var writer = new SpanWriter(buffer);
|
||||
|
||||
writer.Write((ushort)0x1234);
|
||||
|
||||
Assert.Equal(2, writer.Position);
|
||||
AssertThat.Equal(writer.Span, [0x12, 0x34]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestWriteUInt16LittleEndian()
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[2];
|
||||
var writer = new SpanWriter(buffer);
|
||||
|
||||
writer.WriteLE((ushort)0x1234);
|
||||
|
||||
Assert.Equal(2, writer.Position);
|
||||
AssertThat.Equal(writer.Span, [0x34, 0x12]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestWriteInt32BigEndian()
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[4];
|
||||
var writer = new SpanWriter(buffer);
|
||||
|
||||
writer.Write(0x12345678);
|
||||
|
||||
Assert.Equal(4, writer.Position);
|
||||
AssertThat.Equal(writer.Span, [0x12, 0x34, 0x56, 0x78]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestWriteInt32LittleEndian()
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[4];
|
||||
var writer = new SpanWriter(buffer);
|
||||
|
||||
writer.WriteLE(0x12345678);
|
||||
|
||||
Assert.Equal(4, writer.Position);
|
||||
AssertThat.Equal(writer.Span, [0x78, 0x56, 0x34, 0x12]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestWriteUInt32BigEndian()
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[4];
|
||||
var writer = new SpanWriter(buffer);
|
||||
|
||||
writer.Write(0x12345678u);
|
||||
|
||||
Assert.Equal(4, writer.Position);
|
||||
AssertThat.Equal(writer.Span, [0x12, 0x34, 0x56, 0x78]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestWriteUInt32LittleEndian()
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[4];
|
||||
var writer = new SpanWriter(buffer);
|
||||
|
||||
writer.WriteLE(0x12345678u);
|
||||
|
||||
Assert.Equal(4, writer.Position);
|
||||
AssertThat.Equal(writer.Span, [0x78, 0x56, 0x34, 0x12]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestWriteInt64BigEndian()
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[8];
|
||||
var writer = new SpanWriter(buffer);
|
||||
|
||||
writer.Write(0x123456789ABCDEF0L);
|
||||
|
||||
Assert.Equal(8, writer.Position);
|
||||
AssertThat.Equal(writer.Span, [0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestWriteUInt64BigEndian()
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[8];
|
||||
var writer = new SpanWriter(buffer);
|
||||
|
||||
writer.Write(0x123456789ABCDEF0UL);
|
||||
|
||||
Assert.Equal(8, writer.Position);
|
||||
AssertThat.Equal(writer.Span, [0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestWriteSpan()
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[6];
|
||||
var writer = new SpanWriter(buffer);
|
||||
|
||||
ReadOnlySpan<byte> data = [0x01, 0x02, 0x03];
|
||||
writer.Write(data);
|
||||
writer.Write(data);
|
||||
|
||||
Assert.Equal(6, writer.Position);
|
||||
AssertThat.Equal(writer.Span, [0x01, 0x02, 0x03, 0x01, 0x02, 0x03]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestWriteAsciiChar()
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[2];
|
||||
var writer = new SpanWriter(buffer);
|
||||
|
||||
writer.WriteAscii('A');
|
||||
writer.WriteAscii('B');
|
||||
|
||||
Assert.Equal(2, writer.Position);
|
||||
AssertThat.Equal(writer.Span, "AB"u8);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestWriteAsciiString()
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[5];
|
||||
var writer = new SpanWriter(buffer);
|
||||
|
||||
writer.WriteAscii("Hello");
|
||||
|
||||
Assert.Equal(5, writer.Position);
|
||||
AssertThat.Equal(writer.Span, "Hello"u8);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestWriteAsciiStringNull()
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[6];
|
||||
var writer = new SpanWriter(buffer);
|
||||
|
||||
writer.WriteAsciiNull("Hello");
|
||||
|
||||
Assert.Equal(6, writer.Position);
|
||||
AssertThat.Equal(writer.Span, "Hello\0"u8);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestWriteAsciiStringFixedLength()
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[10];
|
||||
var writer = new SpanWriter(buffer);
|
||||
|
||||
writer.WriteAscii("Hello", 10);
|
||||
|
||||
Assert.Equal(10, writer.Position);
|
||||
AssertThat.Equal(writer.Span, "Hello\0\0\0\0\0"u8);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestWriteUTF8String()
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[5];
|
||||
var writer = new SpanWriter(buffer);
|
||||
|
||||
writer.WriteUTF8("Hello");
|
||||
|
||||
Assert.Equal(5, writer.Position);
|
||||
AssertThat.Equal(writer.Span, "Hello"u8);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestWriteUTF8StringNull()
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[6];
|
||||
var writer = new SpanWriter(buffer);
|
||||
|
||||
writer.WriteUTF8Null("Hello");
|
||||
|
||||
Assert.Equal(6, writer.Position);
|
||||
AssertThat.Equal(writer.Span, "Hello\0"u8);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestWriteLittleUniString()
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[10];
|
||||
var writer = new SpanWriter(buffer);
|
||||
|
||||
writer.WriteLittleUni("Hello");
|
||||
|
||||
Assert.Equal(10, writer.Position);
|
||||
AssertThat.Equal(writer.Span, "H\0e\0l\0l\0o\0"u8);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestWriteLittleUniStringNull()
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[12];
|
||||
var writer = new SpanWriter(buffer);
|
||||
|
||||
writer.WriteLittleUniNull("Hello");
|
||||
|
||||
Assert.Equal(12, writer.Position);
|
||||
AssertThat.Equal(writer.Span, "H\0e\0l\0l\0o\0\0\0"u8);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestWriteBigUniString()
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[10];
|
||||
var writer = new SpanWriter(buffer);
|
||||
|
||||
writer.WriteBigUni("Hello");
|
||||
|
||||
Assert.Equal(10, writer.Position);
|
||||
AssertThat.Equal(writer.Span, "\0H\0e\0l\0l\0o"u8);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestWriteBigUniStringNull()
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[12];
|
||||
var writer = new SpanWriter(buffer);
|
||||
|
||||
writer.WriteBigUniNull("Hello");
|
||||
|
||||
Assert.Equal(12, writer.Position);
|
||||
AssertThat.Equal(writer.Span, "\0H\0e\0l\0l\0o\0\0"u8);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestClear()
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[10];
|
||||
buffer.Fill(0xFF);
|
||||
var writer = new SpanWriter(buffer);
|
||||
|
||||
writer.Write((byte)0x01);
|
||||
writer.Clear(5);
|
||||
writer.Write((byte)0x02);
|
||||
|
||||
Assert.Equal(7, writer.Position);
|
||||
AssertThat.Equal(writer.Span, [0x01, 0, 0, 0, 0, 0, 0x02]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestSeekBegin()
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[10];
|
||||
var writer = new SpanWriter(buffer);
|
||||
|
||||
writer.Write((byte)0x01);
|
||||
writer.Write((byte)0x02);
|
||||
writer.Write((byte)0x03);
|
||||
|
||||
var pos = writer.Seek(1, SeekOrigin.Begin);
|
||||
|
||||
Assert.Equal(1, pos);
|
||||
Assert.Equal(1, writer.Position);
|
||||
Assert.Equal(3, writer.BytesWritten);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestSeekCurrent()
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[10];
|
||||
var writer = new SpanWriter(buffer);
|
||||
|
||||
writer.Write((byte)0x01);
|
||||
writer.Write((byte)0x02);
|
||||
|
||||
var pos = writer.Seek(2, SeekOrigin.Current);
|
||||
|
||||
Assert.Equal(4, pos);
|
||||
Assert.Equal(4, writer.Position);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestSeekEnd()
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[10];
|
||||
var writer = new SpanWriter(buffer);
|
||||
|
||||
writer.Write((byte)0x01);
|
||||
writer.Write((byte)0x02);
|
||||
writer.Write((byte)0x03);
|
||||
|
||||
var pos = writer.Seek(-1, SeekOrigin.End);
|
||||
|
||||
Assert.Equal(2, pos);
|
||||
Assert.Equal(2, writer.Position);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestSeekNegativeThrows()
|
||||
{
|
||||
Assert.Throws<ArgumentOutOfRangeException>(
|
||||
() =>
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[10];
|
||||
var writer = new SpanWriter(buffer);
|
||||
writer.Seek(-1, SeekOrigin.Begin);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestSeekBeyondCapacityNoResizeThrows()
|
||||
{
|
||||
Assert.Throws<InvalidOperationException>(
|
||||
() =>
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[10];
|
||||
var writer = new SpanWriter(buffer);
|
||||
writer.Seek(20, SeekOrigin.Begin);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestSeekBeyondCapacityWithResize()
|
||||
{
|
||||
var writer = new SpanWriter(10, true);
|
||||
|
||||
var pos = writer.Seek(20, SeekOrigin.Begin);
|
||||
|
||||
Assert.Equal(20, pos);
|
||||
Assert.True(writer.Capacity >= 20);
|
||||
writer.Dispose();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestEnsureCapacityNoResize()
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[10];
|
||||
var writer = new SpanWriter(buffer);
|
||||
|
||||
writer.EnsureCapacity(10);
|
||||
Assert.Equal(10, writer.Capacity);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestEnsureCapacityNoResizeThrows()
|
||||
{
|
||||
Assert.Throws<InvalidOperationException>(
|
||||
() =>
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[10];
|
||||
var writer = new SpanWriter(buffer);
|
||||
writer.EnsureCapacity(20);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestEnsureCapacityWithResize()
|
||||
{
|
||||
var writer = new SpanWriter(10, true);
|
||||
|
||||
writer.EnsureCapacity(50);
|
||||
|
||||
Assert.True(writer.Capacity >= 50);
|
||||
writer.Dispose();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestToSpanWithStackAlloc()
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[10];
|
||||
var writer = new SpanWriter(buffer);
|
||||
|
||||
writer.Write((byte)0x01);
|
||||
writer.Write((byte)0x02);
|
||||
writer.Write((byte)0x03);
|
||||
|
||||
using var owner = writer.ToSpan();
|
||||
|
||||
Assert.Equal(3, owner.Span.Length);
|
||||
AssertThat.Equal(owner.Span, [0x01, 0x02, 0x03]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestToSpanWithRentedBuffer()
|
||||
{
|
||||
var writer = new SpanWriter(10);
|
||||
|
||||
writer.Write((byte)0x01);
|
||||
writer.Write((byte)0x02);
|
||||
writer.Write((byte)0x03);
|
||||
|
||||
using var owner = writer.ToSpan();
|
||||
|
||||
Assert.Equal(3, owner.Span.Length);
|
||||
AssertThat.Equal(owner.Span, [0x01, 0x02, 0x03]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestToSpanEmpty()
|
||||
{
|
||||
var writer = new SpanWriter(10);
|
||||
|
||||
using var owner = writer.ToSpan();
|
||||
|
||||
Assert.Equal(0, owner.Span.Length);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestBytesWritten()
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[10];
|
||||
var writer = new SpanWriter(buffer);
|
||||
|
||||
Assert.Equal(0, writer.BytesWritten);
|
||||
|
||||
writer.Write((byte)0x01);
|
||||
Assert.Equal(1, writer.BytesWritten);
|
||||
|
||||
writer.Write((ushort)0x0203);
|
||||
Assert.Equal(3, writer.BytesWritten);
|
||||
|
||||
writer.Seek(1, SeekOrigin.Begin);
|
||||
Assert.Equal(3, writer.BytesWritten);
|
||||
|
||||
writer.Write((byte)0xFF);
|
||||
Assert.Equal(3, writer.BytesWritten);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestCapacity()
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[10];
|
||||
var writer = new SpanWriter(buffer);
|
||||
|
||||
Assert.Equal(10, writer.Capacity);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestRawBuffer()
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[10];
|
||||
var writer = new SpanWriter(buffer);
|
||||
|
||||
writer.Write((byte)0x01);
|
||||
|
||||
var raw = writer.RawBuffer;
|
||||
Assert.Equal(10, raw.Length);
|
||||
Assert.Equal(0x01, raw[0]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestSpan()
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[10];
|
||||
var writer = new SpanWriter(buffer);
|
||||
|
||||
writer.Write((byte)0x01);
|
||||
writer.Write((byte)0x02);
|
||||
|
||||
var span = writer.Span;
|
||||
Assert.Equal(2, span.Length);
|
||||
AssertThat.Equal(span, [0x01, 0x02]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -275,7 +275,7 @@ public ref struct SpanReader
|
|||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int Read(Span<byte> bytes)
|
||||
public int Read(scoped Span<byte> bytes)
|
||||
{
|
||||
if (bytes.Length == 0)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue