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

namespace XUnitTest.Net;

/// <summary>客户端 TLS 握手的超时与取消覆盖测试。服务端为“接受连接但从不进行 TLS 应答”的裸监听套接字</summary>
[Collection("Net.D")]
public class TcpSslHandshakeTests
{
    [Fact]
    [DisplayName("tls客户端_服务端不应答握手_超时预算生效")]
    public async Task Handshake_NoServerResponse_TimeoutBudget()
    {
        using var listener = StartSilentListener(out var port);

        using var client = new TcpSession
        {
            Remote = new NetUri($"tcp://127.0.0.1:{port}"),
            SslProtocol = SslProtocols.Tls12,
            Timeout = 1_000,
        };

        var sw = Stopwatch.StartNew();
        await Assert.ThrowsAnyAsync<OperationCanceledException>(() => client.OpenAsync()).WaitAsync(TimeSpan.FromSeconds(10));
        sw.Stop();

        Assert.True(sw.ElapsedMilliseconds < 8_000, $"超时应按预算失败,实际 {sw.ElapsedMilliseconds}ms");
    }

    [Fact]
    [DisplayName("tls客户端_握手期间取消_取消令牌生效")]
    public async Task Handshake_Cancelled_ByCallerToken()
    {
        using var listener = StartSilentListener(out var port);

        // Timeout 故意放长:证明是取消令牌在起作用,而不是超时预算兜底
        using var client = new TcpSession
        {
            Remote = new NetUri($"tcp://127.0.0.1:{port}"),
            SslProtocol = SslProtocols.Tls12,
            Timeout = 60_000,
        };

        using var cts = new CancellationTokenSource(500);
        var sw = Stopwatch.StartNew();
        await Assert.ThrowsAnyAsync<OperationCanceledException>(() => client.OpenAsync(cts.Token)).WaitAsync(TimeSpan.FromSeconds(10));
        sw.Stop();

        Assert.True(sw.ElapsedMilliseconds < 8_000, $"取消应尽快生效,实际 {sw.ElapsedMilliseconds}ms");
    }

    /// <summary>裸监听套接字:接受连接后保持沉默,不对 TLS 握手作答</summary>
    private static Socket StartSilentListener(out Int32 port)
    {
        var listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        listener.Bind(new IPEndPoint(IPAddress.Loopback, 0));
        listener.Listen(1);
        port = ((IPEndPoint)listener.LocalEndPoint!).Port;

        // 接受连接并保持沉默一段时间;客户端超时/取消后自行断开
        _ = Task.Run(async () =>
        {
            try
            {
                using var socket = await listener.AcceptAsync();
                await Task.Delay(TimeSpan.FromSeconds(20));
            }
            catch
            {
                // 监听套接字释放属预期
            }
        });

        return listener;
    }
}