using System.Text;
using NewLife.Buffers;
using NewLife.Data;
using NewLife.Security;
using Xunit;
using System.IO; // 新增:流扩容测试
namespace XUnitTest.Buffers;
public class SpanReaderTests
{
[Fact]
public void CtorTest()
{
Span<Byte> span = stackalloc Byte[100];
var reader = new SpanReader(span);
Assert.Equal(0, reader.Position);
Assert.Equal(span.Length, reader.Capacity);
Assert.Equal(span.Length, reader.Available);
Assert.Equal(span.Length, reader.GetSpan().Length);
reader.Advance(33);
Assert.Equal(33, reader.Position);
Assert.Equal(span.Length, reader.Capacity);
Assert.Equal(span.Length - 33, reader.Available);
Assert.Equal(span.Length - 33, reader.GetSpan().Length);
}
[Theory]
[InlineData(true)]
[InlineData(false)]
public void Test2(Boolean isLittle)
{
Span<Byte> span = new Byte[1024];
var reader = new SpanReader(span) { IsLittleEndian = isLittle };
var writer = new SpanWriter(span) { IsLittleEndian = isLittle };
var b = (Byte)(Rand.Next(255) - 128);
writer.Write(b);
Assert.Equal(b, reader.ReadByte());
var n16 = (Int16)Rand.Next(65536);
writer.Write(n16);
Assert.Equal(n16, reader.ReadInt16());
var u16 = (UInt16)Rand.Next(65536);
writer.Write(u16);
Assert.Equal(u16, reader.ReadUInt16());
var n32 = (Int32)Rand.Next();
writer.Write(n32);
Assert.Equal(n32, reader.ReadInt32());
var u32 = (UInt32)Rand.Next();
writer.Write(u32);
Assert.Equal(u32, reader.ReadUInt32());
var n64 = (Int64)Rand.Next();
writer.Write(n64);
Assert.Equal(n64, reader.ReadInt64());
var u64 = (UInt64)Rand.Next();
writer.Write(u64);
Assert.Equal(u64, reader.ReadUInt64());
var s = (Single)Rand.Next() / 333f;
writer.Write(s);
Assert.Equal(s, reader.ReadSingle());
var d = (Double)Rand.Next() / 777d;
writer.Write(d);
Assert.Equal(d, reader.ReadDouble());
var n = Rand.Next(128);
writer.WriteEncodedInt(n);
Assert.Equal(n, reader.ReadEncodedInt());
n = Rand.Next(128, 65536);
writer.WriteEncodedInt(n);
Assert.Equal(n, reader.ReadEncodedInt());
n = Rand.Next(65536);
writer.WriteEncodedInt(n);
Assert.Equal(n, reader.ReadEncodedInt());
#if NET6_0_OR_GREATER
var buf = Rand.NextBytes(57);
writer.Write(buf);
Assert.Equal(buf, reader.ReadBytes(buf.Length));
var span2 = new Span<Byte>(buf);
writer.Write(span2);
Assert.Equal(span2, reader.ReadBytes(buf.Length));
var span3 = new ReadOnlySpan<Byte>(buf);
writer.Write(span3);
Assert.Equal(span3, reader.ReadBytes(buf.Length));
#endif
var str = Rand.NextString(33);
writer.Write(str);
Assert.Equal(str, reader.ReadString());
writer.Write(str, 32, Encoding.ASCII);
Assert.Equal(str[..32], reader.ReadString(32, Encoding.ASCII));
writer.Write(str, 44, Encoding.ASCII);
Assert.Equal(str + new String('\0', 44 - 33), reader.ReadString(44, Encoding.ASCII));
writer.Write(str, -1, Encoding.Default);
Assert.Equal(str, reader.ReadString(-1, Encoding.Default)[..str.Length]);
}
[Fact]
public void ReadByteTest()
{
var data = new Byte[] { 1, 2, 3 };
var reader = new SpanReader(data);
Assert.Equal(1, reader.ReadByte());
Assert.Equal(2, reader.ReadByte());
Assert.Equal(3, reader.ReadByte());
}
[Fact]
public void ReadInt16Test()
{
var data = new Byte[] { 1, 0, 2, 0 };
var reader = new SpanReader(data);
Assert.Equal(1, reader.ReadInt16());
Assert.Equal(2, reader.ReadInt16());
}
[Fact]
public void ReadInt32Test()
{
var data = new Byte[] { 1, 0, 0, 0, 2, 0, 0, 0 };
var reader = new SpanReader(data);
Assert.Equal(1, reader.ReadInt32());
Assert.Equal(2, reader.ReadInt32());
}
[Fact]
public void ReadStringTest()
{
var data = Encoding.UTF8.GetBytes("Hello, World!");
var reader = new SpanReader(data);
Assert.Equal("Hello, World!", reader.ReadString(data.Length));
}
[Fact]
public void ReadBytesTest()
{
var data = new Byte[] { 1, 2, 3, 4, 5 };
var reader = new SpanReader(data);
reader.Advance(1);
var result = reader.ReadBytes(3);
Assert.Equal(new Byte[] { 2, 3, 4 }, result.ToArray());
}
[Fact]
public void ReadTest()
{
var data = new Byte[] { 1, 2, 3, 4, 5 };
var reader = new SpanReader(data);
reader.Advance(1);
var buf = new Byte[3];
var result = reader.Read(buf);
Assert.Equal(new Byte[] { 2, 3, 4 }, buf);
}
[Fact]
public void ReadPacket()
{
var data = new Byte[] { 1, 2, 3, 4, 5 };
var reader = new SpanReader(data);
reader.Advance(1);
try
{
reader.ReadPacket(3);
}
catch (Exception ex)
{
Assert.NotNull(ex as InvalidOperationException);
}
var pk = new ArrayPacket(data);
reader = new SpanReader(pk);
reader.Advance(1);
var result = reader.ReadPacket(3);
Assert.Equal(new Byte[] { 2, 3, 4 }, result.ToArray());
Assert.True(data == ((ArrayPacket)result).Buffer);
}
[Fact]
public void StreamReadTest()
{
var data = new Byte[] { 1, 2, 3, 4, 5 };
var ms = new MemoryStream(data);
var reader = new SpanReader(ms);
reader.ReadByte();
var result = reader.ReadBytes(3);
Assert.Equal(new Byte[] { 2, 3, 4 }, result.ToArray());
}
[Fact]
public void StreamAutoExpansion()
{
var head = new Byte[] { 0x05 }; // 长度前缀
var body = Encoding.UTF8.GetBytes("Hello");
using var ms = new MemoryStream();
ms.Write(head, 0, head.Length);
ms.Write(body, 0, body.Length);
ms.Position = 0;
var reader = new SpanReader(ms, bufferSize: 2) { MaxCapacity = 32 };
var len = reader.ReadByte();
Assert.Equal(5, len);
var payload = reader.ReadBytes(len);
Assert.Equal("Hello", Encoding.UTF8.GetString(payload));
}
[Fact]
public void ReadPacketFromChainedPacket()
{
ArrayPacket head = new(new Byte[] { 0x81, 0x05 });
ArrayPacket payload = new(Encoding.UTF8.GetBytes("Hello"));
head.Next = payload;
var reader = new SpanReader((IPacket)head);
var frameHead = reader.ReadPacket(2);
Assert.Equal(2, frameHead.Length);
var body = reader.ReadPacket(5);
Assert.Equal(5, body.Length);
Assert.Equal("Hello", body.ToStr());
}
[Fact]
public void MaxCapacityLimit()
{
using var ms = new MemoryStream();
ms.WriteByte(10); // 后续要读的长度
ms.Write(new Byte[10], 0, 10);
ms.Position = 0;
var reader = new SpanReader(ms, bufferSize: 4) { MaxCapacity = 8 };
var len = reader.ReadByte();
Assert.Equal(10, len);
var threw = false;
try
{
_ = reader.ReadBytes(len);
}
catch (InvalidOperationException)
{
threw = true;
}
Assert.True(threw);
}
[Fact]
public void GCAllocationTest()
{
var data = new Byte[100];
var reader = new SpanReader(data);
var initialGen0Collections = GC.CollectionCount(0);
var initialGen1Collections = GC.CollectionCount(1);
var initialGen2Collections = GC.CollectionCount(2);
var memory = GC.GetAllocatedBytesForCurrentThread();
reader.ReadBytes(50);
Assert.Equal(memory, GC.GetAllocatedBytesForCurrentThread());
Assert.Equal(initialGen0Collections, GC.CollectionCount(0));
Assert.Equal(initialGen1Collections, GC.CollectionCount(1));
Assert.Equal(initialGen2Collections, GC.CollectionCount(2));
}
}
|