解决MySql布尔型新旧版本兼容问题,采用枚举来表示布尔型的数据表。由正向工程赋值
大石头 authored at 2018-05-15 21:21:05
5.11 KiB
X
using System.Buffers;
using System.ComponentModel;
using System.Text;
using NewLife;
using NewLife.Data;
using NewLife.Messaging;
using Xunit;

namespace XUnitTest.Messaging;

/// <summary>分隔符消息编解码器(SplitDataCodec)测试</summary>
public class SplitDataCodecTests
{
    #region 工具
    private static readonly SplitDataCodec _codec = new();

    private static MessagePump NewPump() => new(new SplitDataCodec());

    private static async Task<String> ReadLineAsync(IMessage message)
    {
        var body = await message.Body!.ReadAllAsync();
        var str = Encoding.UTF8.GetString(body.AsReadOnlySequence().ToArray());
        body.TryDispose();

        return str;
    }
    #endregion

    [Fact]
    [DisplayName("分隔符编解码_单行_内容定界")]
    public void TryParse_Line()
    {
        var frame = Encoding.UTF8.GetBytes("hello\r\n");
        var rs = _codec.TryParse(new ArrayPacket(frame).AsReadOnlySequence());
        Assert.NotNull(rs);
        Assert.NotNull(rs.Value.Message);
        Assert.Equal(0, rs.Value.HeaderSize);
        Assert.Equal(5L, rs.Value.BodyLength);

        // 分隔符未出现:等待(不产生对象)
        Assert.Null(_codec.TryParse(new ArrayPacket(Encoding.UTF8.GetBytes("hel")).AsReadOnlySequence()));
    }

    [Fact]
    [DisplayName("分隔符编解码_空行_无消息帧语义")]
    public void TryParse_EmptyLine_NoMessage()
    {
        // "a\r\n\r\nb\r\n":从 a 的帧尾分隔符开始解析([sep][sep][b][sep])
        var seq = new ArrayPacket(Encoding.UTF8.GetBytes("a\r\n\r\nb\r\n")).AsReadOnlySequence();

        var rs1 = _codec.TryParse(seq);
        Assert.NotNull(rs1);
        Assert.NotNull(rs1.Value.Message);
        Assert.Equal(0, rs1.Value.HeaderSize);
        Assert.Equal(1L, rs1.Value.BodyLength);

        // 第二帧:前导分隔符 + 空行分隔符 → 无消息帧(跳过 4 字节)
        var rs2 = _codec.TryParse(seq.Slice(rs1.Value.HeaderSize + rs1.Value.BodyLength));
        Assert.NotNull(rs2);
        Assert.Null(rs2.Value.Message);
        Assert.Equal(4, rs2.Value.HeaderSize);
        Assert.Equal(0L, rs2.Value.BodyLength);
    }

    [Fact]
    [DisplayName("帧泵_分隔符两行连续_逐条交付")]
    public async Task TryRead_TwoLines()
    {
        var pump = NewPump();
        using var pipe = new Pipe();

        pipe.Writer.Append(new ArrayPacket(Encoding.UTF8.GetBytes("one\r\ntwo\r\n")));

        Assert.True(pump.TryRead(pipe.Reader, out var m1));
        Assert.Equal("one", await ReadLineAsync(m1!));
        m1!.Dispose();

        Assert.True(pump.TryRead(pipe.Reader, out var m2));
        Assert.Equal("two", await ReadLineAsync(m2!));
        m2!.Dispose();

        // 帧尾分隔符无后继内容:等待(留在窗口)
        Assert.False(pump.TryRead(pipe.Reader, out _));
        Assert.Equal(2, pipe.UnconsumedLength);
    }

    [Fact]
    [DisplayName("帧泵_空行跳过_不产出空消息")]
    public async Task TryRead_EmptyLine_Skipped()
    {
        var pump = NewPump();
        using var pipe = new Pipe();

        pipe.Writer.Append(new ArrayPacket(Encoding.UTF8.GetBytes("a\r\n\r\nb\r\n")));

        Assert.True(pump.TryRead(pipe.Reader, out var m1));
        Assert.Equal("a", await ReadLineAsync(m1!));
        m1!.Dispose();

        // 空行被自动跳过,直接产出 b
        Assert.True(pump.TryRead(pipe.Reader, out var m2));
        Assert.Equal("b", await ReadLineAsync(m2!));
        m2!.Dispose();
    }

    [Fact]
    [DisplayName("帧泵_分隔符跨段_正常定界")]
    public async Task TryRead_SplitAcrossSegments()
    {
        var pump = NewPump();
        using var pipe = new Pipe();

        // \r 已到、\n 未到(分隔符跨段)
        pipe.Writer.Append(new ArrayPacket(Encoding.UTF8.GetBytes("hello\r")));
        Assert.False(pump.TryRead(pipe.Reader, out _));
        Assert.Equal(6, pipe.UnconsumedLength);

        // \n 到达:定界出 hello,随后 two 续上
        pipe.Writer.Append(new ArrayPacket(Encoding.UTF8.GetBytes("\ntwo\r\n")));
        Assert.True(pump.TryRead(pipe.Reader, out var m1));
        Assert.Equal("hello", await ReadLineAsync(m1!));
        m1!.Dispose();

        Assert.True(pump.TryRead(pipe.Reader, out var m2));
        Assert.Equal("two", await ReadLineAsync(m2!));
        m2!.Dispose();
    }

    [Fact]
    [DisplayName("分隔符编解码_整帧构建_内容加分隔符")]
    public void Build_AppendsSplit()
    {
        var msg = new Message();
        msg.SetBody(new ArrayPacket(Encoding.UTF8.GetBytes("hello")));

        var pk = _codec.Build(msg);
        Assert.NotNull(pk);
        Assert.Equal(Encoding.UTF8.GetBytes("hello\r\n"), pk!.AsReadOnlySequence().ToArray());
        Assert.NotNull(msg.Payload);     // 构建不消费消息负载
        pk.TryDispose();

        // 空消息:仅分隔符
        var pk2 = _codec.Build(new Message());
        Assert.NotNull(pk2);
        Assert.Equal(Encoding.UTF8.GetBytes("\r\n"), pk2!.AsReadOnlySequence().ToArray());
        pk2.TryDispose();

        // 头部构建不支持
        Assert.Throws<NotSupportedException>(() => _codec.BuildHeader(msg, 10));
    }
}