Prhub

#47873 [Rust Frontend] Fix flaky `tls_handshake_timeout_drops_silent_client` test

原始 PR 作者 tahsintunan 合并时间 2026-07-15 19:05 文件变更 2 提交数 2 评论 3 代码增减 +12 / -6

执行摘要

修复 Rust 前端 TLS 握手测试的竞态条件

测试 tls_handshake_timeout_drops_silent_client 因手动推进时钟与 socket read 之间的竞态条件导致不稳定。PR body 描述:'the test manually advanced the paused clock and raced the handshake close against the socket read, making it flaky'。

该 PR 是值得学习的小型测试稳定性修复案例,展示了如何使用 tokio 的暂停时钟原生机制避免竞态。对于 Rust 测试编写者,可以关注其中的设计权衡。

讨论亮点

Codex bot 建议给 read().await 加上本地超时,防止测试挂起。作者回应已通过 nextest 的 slow-timeout 配置覆盖,且 nextest 是 CI 标准运行器。该建议未被采纳,但达成了共识。

实现拆解

  1. 移除手动时钟推进与 yield:删掉 yield_now()advance() 调用,改为在连接后直接执行 tcp.read(&mut buf).await,让 tokio 的暂停时钟在等待读操作时自动推进到超时。
  2. 保持原粒度断言assert! 从检查 Ok(Ok(0)) | Ok(Err(_)) 简化为 Ok(0) | Err(_),因为去掉了外层 timeout 包装。
  3. 添加关闭时机验证:新增 start.elapsed() >= TLS_HANDSHAKE_TIMEOUT 断言,确保连接关闭发生在握手超时之后,而非提前关闭。
  4. 引入 nextest 慢超时配置:在 rust/.config/nextest.toml 新增 slow-timeout 配置,period = "60s"terminate-after = 2,确保万一测试挂起时被终止而不是无限等待。
  5. 仅修改测试文件和配置文件:不涉及生产代码。
文件 模块 状态 重要度
rust/src/server/src/tls_tests.rs Rust 前端 modified 6.04
rust/.config/nextest.toml 构建配置 added 3.81

关键符号

tls_handshake_timeout_drops_silent_client

关键源码片段

rust/src/server/src/tls_tests.rs core-logic

测试修复的核心文件,修改了手握手超时测试的逻辑。

#[tokio::test(start_paused = true)]
async fn tls_handshake_timeout_drops_silent_client() {
    // Silent client (no ClientHello) must be dropped at the handshake deadline.
    let certs = TestCerts::generate();
    let (addr, shutdown) = spawn_server(Some(server_tls(&certs, 0))).await;    let mut tcp = TcpStream::connect(&addr).await.expect("connect");
    let start = tokio::time::Instant::now();
    let mut buf = [0u8; 1];
    // 不再手动 advance 时钟,让 tokio 暂停时钟在 read 等待时自动推进
    let read = tcp.read(&mut buf).await;
    assert!(
        matches!(read, Ok(0) | Err(_)),
        "server must drop a stalled TLS handshake (expected close, got {read:?})"
    );
    // 验证关闭发生在握手超时之后,而非提前关闭
    assert!(
        start.elapsed() >= tls::TLS_HANDSHAKE_TIMEOUT,
        "closed too early to be the handshake deadline: {:?}",
        start.elapsed()
    );
    shutdown.cancel();
}

评论区精华

bare read 是否需要用 timeout 包裹 测试

Codex bot 建议给 read 加上本地超时,否则测试挂起时无法自动失败。

结论:作者指出已通过 nextest slow-timeout 配置覆盖,且 nextest 是 CI 唯一运行器,不采纳建议。 · 已解决

风险与影响

低风险。仅修改测试用例,不涉及生产代码。潜在风险:若 tokio 暂停时钟行为在版本升级后变化,可能导致测试重入性不稳定,但可以通过 CI 定期运行发现。nextest 慢超时配置是全局生效的,可能掩盖其他测试的无限等待,但配置旨在缓解而非完全解决问题。

影响范围小,仅限于 Rust 前端测试。修复了 tls_handshake_timeout_drops_silent_client 的竞态条件,使其在 CI 中稳定通过。新增的 nextest 配置适用于整个 workspace,提高了测试套件的健壮性。

测试增强

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论