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

namespace XUnitTest.Compat;

/// <summary>SequenceReader 兼容性测试:net462 走 NewLife.Core 垫片、net8.0 走 BCL,同一套用例校验行为一致</summary>
public class SequenceReaderCompatTests
{
    [Fact]
    [DisplayName("TryRead_跨段顺序读取_值正确且推进完整")]
    public void TryRead_Across()
    {
        var seq = SequenceFactory.Build(new Byte[] { 1, 2 }, new Byte[] { 3 }, new Byte[] { 4, 5, 6 });
        var reader = new SequenceReader<Byte>(seq);
        for (var i = 1; i <= 6; i++)
        {
            Assert.True(reader.TryRead(out var b));
            Assert.Equal((Byte)i, b);
        }

        Assert.False(reader.TryRead(out _));
        Assert.True(reader.End);
        Assert.Equal(6L, reader.Consumed);
        Assert.Equal(0L, reader.Remaining);
    }

    [Fact]
    [DisplayName("TryPeek_段边界_不推进位置")]
    public void TryPeek_Boundary()
    {
        var seq = SequenceFactory.Build(new Byte[] { 1, 2 }, new Byte[] { 3 });
        var reader = new SequenceReader<Byte>(seq);
        Assert.True(reader.TryPeek(out var b));
        Assert.Equal((Byte)1, b);

        reader.Advance(2);
        Assert.Equal(2L, reader.Consumed);
        Assert.True(reader.TryPeek(out b));
        Assert.Equal((Byte)3, b);
    }

    [Fact]
    [DisplayName("Rewind_跨段回退_重读一致")]
    public void Rewind_Across()
    {
        var seq = SequenceFactory.Build(new Byte[] { 1, 2 }, new Byte[] { 3, 4 }, new Byte[] { 5 });
        var reader = new SequenceReader<Byte>(seq);
        reader.Advance(4);
        Assert.Equal(4L, reader.Consumed);

        reader.Rewind(3);
        Assert.Equal(1L, reader.Consumed);
        Assert.True(reader.TryRead(out var b));
        Assert.Equal((Byte)2, b);
    }

    [Fact]
    [DisplayName("TryCopyTo_跨段拷贝成功_数据不足失败_均不推进")]
    public void TryCopyTo_Across()
    {
        var seq = SequenceFactory.Build(new Byte[] { 1, 2 }, new Byte[] { 3, 4, 5 });
        var reader = new SequenceReader<Byte>(seq);
        reader.Advance(1);

        Span<Byte> dest = stackalloc Byte[4];
        Assert.True(reader.TryCopyTo(dest));
        Assert.Equal(new Byte[] { 2, 3, 4, 5 }, dest.ToArray());
        Assert.Equal(1L, reader.Consumed);

        Span<Byte> tooBig = stackalloc Byte[5];
        Assert.False(reader.TryCopyTo(tooBig));
        Assert.Equal(1L, reader.Consumed);
    }

    [Fact]
    [DisplayName("TryReadLittleEndian_跨段边界_与BinaryPrimitives一致")]
    public void LittleEndian_Boundary()
    {
        var value = 0x12345678;
        var bytes = new Byte[4];
        BinaryPrimitives.WriteInt32LittleEndian(bytes, value);
        var seq = SequenceFactory.Build(new Byte[] { 0xAA, bytes[0] }, new Byte[] { bytes[1], bytes[2], bytes[3] });
        var reader = new SequenceReader<Byte>(seq);

        Assert.True(reader.TryRead(out var head));
        Assert.Equal(0xAA, head);
        Assert.True(reader.TryReadLittleEndian(out Int32 actual));
        Assert.Equal(value, actual);
        Assert.Equal(5L, reader.Consumed);
    }

    [Fact]
    [DisplayName("TryReadBigEndian_Int16与Int64跨段_与BinaryPrimitives一致")]
    public void BigEndian_Boundary()
    {
        var i16 = 0x1234;
        var i64 = 0x0102030405060708L;
        var b16 = new Byte[2];
        var b64 = new Byte[8];
        BinaryPrimitives.WriteInt16BigEndian(b16, (Int16)i16);
        BinaryPrimitives.WriteInt64BigEndian(b64, i64);

        var seq = SequenceFactory.Build(
            new Byte[] { b16[0] },
            new Byte[] { b16[1], b64[0], b64[1] },
            new Byte[] { b64[2], b64[3], b64[4], b64[5], b64[6], b64[7] });
        var reader = new SequenceReader<Byte>(seq);

        Assert.True(reader.TryReadBigEndian(out Int16 v16));
        Assert.Equal((Int16)i16, v16);
        Assert.True(reader.TryReadBigEndian(out Int64 v64));
        Assert.Equal(i64, v64);
        Assert.Equal(10L, reader.Consumed);
    }

    [Fact]
    [DisplayName("TryReadLittleEndian_数据不足_返回false且不推进")]
    public void LittleEndian_Insufficient()
    {
        var seq = SequenceFactory.Build(new Byte[] { 1, 2, 3 });
        var reader = new SequenceReader<Byte>(seq);
        reader.Advance(2);

        Assert.False(reader.TryReadLittleEndian(out Int32 _));
        Assert.Equal(2L, reader.Consumed);
    }

    [Fact]
    [DisplayName("TryAdvanceTo_跨段查找分隔符_前进到分隔符之后")]
    public void TryAdvanceTo_Found()
    {
        var seq = SequenceFactory.Build(new Byte[] { 1, 2, (Byte)'#' }, new Byte[] { 9, 9 });
        var reader = new SequenceReader<Byte>(seq);
        Assert.True(reader.TryAdvanceTo((Byte)'#', true));
        Assert.Equal(3L, reader.Consumed);
        Assert.True(reader.TryRead(out var b));
        Assert.Equal((Byte)9, b);
    }

    [Fact]
    [DisplayName("TryAdvanceTo_未找到_不改变读取位置")]
    public void TryAdvanceTo_NotFound()
    {
        var seq = SequenceFactory.Build(new Byte[] { 1, 2 }, new Byte[] { 3 });
        var reader = new SequenceReader<Byte>(seq);
        Assert.False(reader.TryAdvanceTo((Byte)'#', true));
        Assert.Equal(0L, reader.Consumed);
    }

    [Fact]
    [DisplayName("TryReadTo_跨段读取到分隔符_返回切片且正确推进")]
    public void TryReadTo_Delimiter()
    {
        var seq = SequenceFactory.Build(new Byte[] { 1, 2 }, new Byte[] { 3, (Byte)';', 4 });
        var reader = new SequenceReader<Byte>(seq);
        Assert.True(reader.TryReadTo(out ReadOnlySequence<Byte> line, (Byte)';', true));
        Assert.Equal(3L, line.Length);
        Assert.Equal(new Byte[] { 1, 2, 3 }, line.ToArray());
        Assert.True(reader.TryRead(out var next));
        Assert.Equal((Byte)4, next);
    }

    [Fact]
    [DisplayName("AdvancePast_跨段连续相同值_返回推进数量")]
    public void AdvancePast_Across()
    {
        var seq = SequenceFactory.Build(new Byte[] { 0, 0 }, new Byte[] { 0, 5 });
        var reader = new SequenceReader<Byte>(seq);
        Assert.Equal(3L, reader.AdvancePast((Byte)0));
        Assert.True(reader.TryRead(out var b));
        Assert.Equal((Byte)5, b);
    }

    [Fact]
    [DisplayName("AdvancePastAny_跨段跳过两种空白字符")]
    public void AdvancePastAny_Across()
    {
        var seq = SequenceFactory.Build(new Byte[] { 0x20 }, new Byte[] { 0x09, 0x20, (Byte)'x' });
        var reader = new SequenceReader<Byte>(seq);
        Assert.Equal(3L, reader.AdvancePastAny((Byte)0x20, (Byte)0x09));
        Assert.True(reader.TryRead(out var b));
        Assert.Equal((Byte)'x', b);
    }

    [Fact]
    [DisplayName("IsNext_跨段比对_可选推进")]
    public void IsNext_Across()
    {
        var seq = SequenceFactory.Build(new Byte[] { 1 }, new Byte[] { 2, 3 });
        var reader = new SequenceReader<Byte>(seq);
        Assert.False(reader.IsNext(new Byte[] { 1, 9 }, false));
        Assert.True(reader.IsNext(new Byte[] { 1, 2 }, true));
        Assert.Equal(2L, reader.Consumed);
        Assert.True(reader.TryRead(out var b));
        Assert.Equal((Byte)3, b);
    }

    [Fact]
    [DisplayName("Rewind_超过已消费数量_抛ArgumentOutOfRangeException")]
    public void Rewind_Overflow_Throws()
    {
        Assert.Throws<ArgumentOutOfRangeException>(() =>
        {
            var reader = new SequenceReader<Byte>(SequenceFactory.Build(new Byte[] { 1, 2 }));
            reader.Advance(1);
            reader.Rewind(2);
        });
    }

    [Fact]
    [DisplayName("Advance_超出剩余数据_抛ArgumentOutOfRangeException")]
    public void Advance_Overflow_Throws()
    {
        Assert.Throws<ArgumentOutOfRangeException>(() =>
        {
            var reader = new SequenceReader<Byte>(SequenceFactory.Build(new Byte[] { 1, 2 }));
            reader.Advance(3);
        });
    }

    [Fact]
    [DisplayName("空序列_End为真且读取失败")]
    public void Empty_Sequence()
    {
        var reader = new SequenceReader<Byte>(ReadOnlySequence<Byte>.Empty);
        Assert.True(reader.End);
        Assert.False(reader.TryRead(out _));
        Assert.Equal(0L, reader.Length);
        Assert.Equal(0L, reader.Remaining);
    }

    [Fact]
    [DisplayName("首段为空的多段链_构造后直接定位到有效数据")]
    public void Leading_Empty_Segment()
    {
        var seq = SequenceFactory.Build(Array.Empty<Byte>(), new Byte[] { 7, 8 });
        var reader = new SequenceReader<Byte>(seq);
        Assert.False(reader.End);
        Assert.True(reader.TryRead(out var b));
        Assert.Equal((Byte)7, b);
        Assert.Equal(1L, reader.Consumed);
    }

    [Fact]
    [DisplayName("Position_跨段推进_与GetPosition结果一致")]
    public void Position_Across()
    {
        var seq = SequenceFactory.Build(new Byte[] { 1, 2 }, new Byte[] { 3, 4 });
        var reader = new SequenceReader<Byte>(seq);
        reader.Advance(3);
        Assert.True(reader.Position.Equals(seq.GetPosition(3)));
        Assert.Equal(3L, reader.Consumed);
    }

    [Fact]
    [DisplayName("UnreadSpan_恰好读完一段_指向下一段")]
    public void UnreadSpan_Next()
    {
        var seq = SequenceFactory.Build(new Byte[] { 1, 2 }, new Byte[] { 3, 4, 5 });
        var reader = new SequenceReader<Byte>(seq);
        reader.Advance(2);
        var span = reader.UnreadSpan;
        Assert.Equal(3, span.Length);
        Assert.Equal((Byte)3, span[0]);
    }

    [Fact]
    [DisplayName("TryRead_64个单字节段_连续读取完整")]
    public void Many_Segments()
    {
        var segments = new Byte[64][];
        for (var i = 0; i < 64; i++)
            segments[i] = new[] { (Byte)i };

        var reader = new SequenceReader<Byte>(SequenceFactory.Build(segments));
        for (var i = 0; i < 64; i++)
        {
            Assert.True(reader.TryRead(out var b));
            Assert.Equal((Byte)i, b);
        }

        Assert.True(reader.End);
        Assert.Equal(64L, reader.Consumed);
    }

    [Fact]
    [DisplayName("TryReadToAny_跨段任一分隔符_返回切片")]
    public void TryReadToAny_Across()
    {
        var seq = SequenceFactory.Build(new Byte[] { 1 }, new Byte[] { 2, (Byte)';', 3 });
        var reader = new SequenceReader<Byte>(seq);
        Assert.True(reader.TryReadToAny(out ReadOnlySequence<Byte> line, new Byte[] { (Byte)',', (Byte)';' }, true));
        Assert.Equal(new Byte[] { 1, 2 }, line.ToArray());
        Assert.Equal(3L, reader.Consumed);
        Assert.True(reader.TryRead(out var next));
        Assert.Equal((Byte)3, next);
    }

    [Fact]
    [DisplayName("TryAdvanceToAny_跨段查找并跳过分隔符")]
    public void TryAdvanceToAny_Across()
    {
        var seq = SequenceFactory.Build(new Byte[] { 1, (Byte)',' }, new Byte[] { 9 });
        var reader = new SequenceReader<Byte>(seq);
        Assert.True(reader.TryAdvanceToAny(new Byte[] { (Byte)';', (Byte)',' }, true));
        Assert.Equal(2L, reader.Consumed);
    }

    [Fact]
    [DisplayName("AdvancePastAny_三参数重载_跳过分隔符")]
    public void AdvancePastAny_Overloads()
    {
        var seq = SequenceFactory.Build(new Byte[] { 0x20, 0x09 }, new Byte[] { 0x0D, (Byte)'x' });
        var reader = new SequenceReader<Byte>(seq);
        Assert.Equal(3L, reader.AdvancePastAny((Byte)0x20, (Byte)0x09, (Byte)0x0D));
        Assert.True(reader.TryRead(out var b));
        Assert.Equal((Byte)'x', b);
    }

    [Fact]
    [DisplayName("TryReadTo_转义分隔符_跳过被转义项")]
    public void TryReadTo_Escape()
    {
        // a % ; b ; z:第二个 ';' 被 '%' 转义跳过,读到末尾第一个未转义 ';'
        var seq = SequenceFactory.Build(new Byte[] { (Byte)'a', (Byte)'%' }, new Byte[] { (Byte)';', (Byte)'b', (Byte)';', (Byte)'z' });
        var reader = new SequenceReader<Byte>(seq);
        Assert.True(reader.TryReadTo(out ReadOnlySequence<Byte> line, (Byte)';', (Byte)'%', true));
        Assert.Equal(new Byte[] { (Byte)'a', (Byte)'%', (Byte)';', (Byte)'b' }, line.ToArray());
        Assert.True(reader.TryRead(out var next));
        Assert.Equal((Byte)'z', next);
    }

    [Fact]
    [DisplayName("TryReadTo_多字节分隔符跨段_匹配完整分隔符")]
    public void TryReadTo_MultiByteDelimiter()
    {
        var seq = SequenceFactory.Build(new Byte[] { 1, 2, 3 }, new Byte[] { (Byte)'\r', (Byte)'\n', 9 });
        var reader = new SequenceReader<Byte>(seq);
        Assert.True(reader.TryReadTo(out ReadOnlySequence<Byte> line, new Byte[] { (Byte)'\r', (Byte)'\n' }, true));
        Assert.Equal(new Byte[] { 1, 2, 3 }, line.ToArray());
        Assert.True(reader.TryRead(out var next));
        Assert.Equal((Byte)9, next);
    }
}