using System;
using System.Buffers;
using System.ComponentModel;
using System.Threading.Tasks;
using NewLife;
using NewLife.Data;
using Xunit;
namespace XUnitTest.Data;
/// <summary>é™é•¿è¯»å–å™¨æµ‹è¯•ã€‚ç®¡é“æµå¼æ¨¡å¼ç”± PipeTests çš„ Limit 用例覆盖,æ¤å¤„è¡¥å†…å˜æ¨¡å¼ï¼ˆæ•´å¸§è§£æžï¼‰çš„窗å£ã€é¢„ç®—ã€å¤ä½ä¸Žå–值è¯ä¹‰</summary>
public class LimitedReaderTests
{
private static Byte[] B(params Int32[] values)
{
var buf = new Byte[values.Length];
for (var i = 0; i < values.Length; i++) buf[i] = (Byte)values[i];
return buf;
}
[Fact]
[DisplayName("é™é•¿è¯»å–_å†…å˜æ¨¡å¼_窗å£è£å‰ªåˆ°é¢„算内")]
public async Task MemoryMode_BufferWithinBudget()
{
var packet = new ArrayPacket(B(1, 2, 3, 4, 5));
var body = new LimitedReader(packet, 1, 3);
Assert.False(body.IsStreaming);
Assert.Equal(3, body.Remaining);
Assert.Equal(B(2, 3, 4), body.Buffer.ToArray());
// æ•°æ®å·²åœ¨å†…å˜ï¼šè¯»å–ç«‹å³å®Œæˆï¼Œä¸”带“结æŸâ€æ ‡è®°
var rr = await body.ReadAsync();
Assert.True(rr.IsCompleted);
Assert.False(rr.IsCanceled);
Assert.Equal(B(2, 3, 4), rr.Buffer.ToArray());
// 读å–䏿¶ˆè´¹ï¼šé¢„ç®—ä¸å˜
Assert.Equal(3, body.Remaining);
}
[Fact]
[DisplayName("é™é•¿è¯»å–_å†…å˜æ¨¡å¼_推进扣å‡é¢„ç®—")]
public async Task MemoryMode_AdvanceDecrementsBudget()
{
var packet = new ArrayPacket(B(1, 2, 3, 4, 5));
var body = new LimitedReader(packet, 1, 3);
body.AdvanceTo(1);
Assert.Equal(2, body.Remaining);
Assert.Equal(B(3, 4), body.Buffer.ToArray());
var rr = await body.ReadAsync();
Assert.Equal(B(3, 4), rr.Buffer.ToArray());
}
[Fact]
[DisplayName("é™é•¿è¯»å–_推进超出预算_æŠ›å‚æ•°å¼‚常")]
public void Advance_BeyondBudget_Throws()
{
var packet = new ArrayPacket(B(1, 2, 3, 4, 5));
var body = new LimitedReader(packet, 1, 2);
Assert.Throws<ArgumentOutOfRangeException>(() => body.AdvanceTo(3));
Assert.Throws<ArgumentOutOfRangeException>(() => body.AdvanceTo(-1));
}
[Fact]
[DisplayName("é™é•¿è¯»å–_预算耗尽_读å–返回已结æŸç©ºç»“æžœ")]
public async Task BudgetExhausted_ReturnsCompletedEmpty()
{
var packet = new ArrayPacket(B(1, 2, 3));
var body = new LimitedReader(packet, 0, 2);
body.AdvanceTo(2);
Assert.Equal(0, body.Remaining);
Assert.Null(body.AsPacket());
var rr = await body.ReadAsync();
Assert.True(rr.IsCompleted);
Assert.True(rr.Buffer.IsEmpty);
// åŒæ¥å½¢æ€ä¸Žå¼‚æ¥ä¸€è‡´
Assert.True(body.TryRead(out var sync));
Assert.True(sync.IsCompleted);
Assert.True(sync.Buffer.IsEmpty);
}
[Fact]
[DisplayName("é™é•¿è¯»å–_å†…å˜æ¨¡å¼_AsPacketä¸ºå‰©ä½™ä½“è§†å›¾ä¸”ä¸æ¶ˆè´¹")]
public void MemoryMode_AsPacketView()
{
var packet = new ArrayPacket(B(1, 2, 3, 4, 5));
var body = new LimitedReader(packet, 1, 4);
var view = body.AsPacket();
Assert.NotNull(view);
Assert.Equal(B(2, 3, 4, 5), view!.ToArray());
// å–è§†å›¾ä¸æ¶ˆè´¹
body.AdvanceTo(2);
Assert.Equal(2, body.Remaining);
Assert.Equal(B(4, 5), body.AsPacket()!.ToArray());
}
[Fact]
[DisplayName("é™é•¿è¯»å–_å†…å˜æ¨¡å¼_ReadAllAsync读满并推进到帧尾")]
public async Task MemoryMode_ReadAll()
{
var packet = new ArrayPacket(B(1, 2, 3, 4, 5));
var body = new LimitedReader(packet, 1, 3);
var all = await body.ReadAllAsync();
Assert.Equal(B(2, 3, 4), all.ToArray());
Assert.Equal(0, body.Remaining);
}
[Fact]
[DisplayName("é™é•¿è¯»å–_å†…å˜æ¨¡å¼_ReadAllAsyncåŽä¸å¯é‡å¤è¯»")]
public async Task MemoryMode_ReadAllConsumes()
{
var packet = new ArrayPacket(B(1, 2, 3));
var body = new LimitedReader(packet, 0, 3);
var first = await body.ReadAllAsync();
Assert.Equal(B(1, 2, 3), first.ToArray());
// 已推进到帧尾:å†è¯»åªå¾—空包
var second = await body.ReadAllAsync();
Assert.Equal(0, second.Length);
}
[Fact]
[DisplayName("é™é•¿è¯»å–_å†…å˜æ¨¡å¼_å¤ä½åŽå¯é‡å¤è¯»")]
public async Task MemoryMode_Reset()
{
var packet = new ArrayPacket(B(1, 2, 3, 4, 5));
var body = new LimitedReader(packet, 1, 3);
var all = await body.ReadAllAsync();
Assert.Equal(B(2, 3, 4), all.ToArray());
// 事件链消费完消æ¯ä½“åŽã€äº¤ä»˜ç‰å¾…æ–¹å‰å¤ä½ï¼šå†…容å¯è¢«é‡å¤è¯»å–
body.Reset();
Assert.Equal(3, body.Remaining);
var again = await body.ReadAllAsync();
Assert.Equal(B(2, 3, 4), again.ToArray());
}
[Fact]
[DisplayName("é™é•¿è¯»å–_å†…å˜æ¨¡å¼_Drain丢弃余é‡")]
public async Task MemoryMode_Drain()
{
var packet = new ArrayPacket(B(1, 2, 3, 4, 5));
var body = new LimitedReader(packet, 1, 4);
await body.DrainAsync();
Assert.Equal(0, body.Remaining);
Assert.Null(body.AsPacket());
}
[Fact]
[DisplayName("é™é•¿è¯»å–_æµå¼æ¨¡å¼_å–包与å¤ä½è¢«æ‹’ç»")]
public void StreamingMode_AsPacketAndResetRejected()
{
using var pipe = new Pipe();
var body = pipe.Reader.Limit(4);
Assert.True(body.IsStreaming);
Assert.Equal(4, body.Remaining);
// æµå¼ä½“的数æ®ç”±ç®¡é“承载ã€ä¸å¯é‡æ”¾ï¼Œä¹Ÿä¸å…许直接å–包
Assert.Throws<InvalidOperationException>(() => body.AsPacket());
Assert.Throws<InvalidOperationException>(() => body.Reset());
}
[Fact]
[DisplayName("é™é•¿è¯»å–_æž„é€ å‡½æ•°_éžæ³•傿•°è¢«æ‹’ç»")]
public void Ctor_InvalidArguments_Throws()
{
var packet = new ArrayPacket(B(1, 2, 3));
Assert.Throws<ArgumentNullException>(() => new LimitedReader((IPacket)null!, 0, 1));
Assert.Throws<ArgumentOutOfRangeException>(() => new LimitedReader(packet, -1, 1));
Assert.Throws<ArgumentOutOfRangeException>(() => new LimitedReader(packet, 0, -1));
}
}
|