qwen-code/scripts/tests/vitest.config.ts
易良 7bd863daaf
fix(ci): stop the scripts-suite timeout knob from failing open on an empty value (#10910)
`scripts/tests/vitest.config.ts` read its ceiling as
`Number(process.env['QWEN_SCRIPTS_TEST_TIMEOUT_MS'] ?? 90_000)`. `??` only
catches `undefined`, so an empty value yields `Number('')` === 0, and vitest
reads 0 as "no timeout at all" — the knob meant to raise the ceiling would
instead remove it, and a hung test would run until the job cap. `NaN` from a
typo does the same.

`''` is not a hypothetical spelling. It is exactly what this repo's
`${{ cond && 'x' || '' }}` idiom renders when the condition is false, which is
how the sibling `QWEN_SKIP_LATENCY_BUDGETS` knob one line away in ci.yml is
wired. Nothing sets this variable in a workflow today, so the fault is latent
rather than live.

Measured, on this config:

    undefined -> 90000    '' -> 0    'abc' -> NaN    '5000' -> 5000

`||` instead of `??` sends every non-positive spelling to the default. The
cost is that 0 can no longer be passed to mean "no timeout"; that is a footgun
rather than a feature, and no caller uses it.

The companion pin could not have caught this. It stubbed `''` and then called
`vi.unstubAllEnvs()` on the next line, so both of its arms measured the unset
path and the one value that would fail was discarded. It now asserts `''`,
`'abc'` and `'0'` alongside the two original arms; `vi.stubEnv(k, undefined)`
deletes the variable, so the unset arm no longer needs the if/else. Verified
both ways: the rewritten pin fails on the old expression
(`expected +0 to be 90000`) and passes on the new one.

Also drops six per-test `}, 30000)` ceilings in qwen-autofix-workflow.test.js.
They predate the suite ceiling and now shadow it, pinning exactly the
bash-spawning cases that the 90s default exists to protect back down to the old
flat 30s. None of them asserts a duration property — each is a "give this
subprocess-spawning test room" budget, and the last one says so in its own
comment, which is updated to point at the suite ceiling. The three
`timeout: 30_000` options that remain are `spawnSync` bounds, deliberately
separate because spawnSync blocks the event loop where vitest's async timeout
cannot fire.

The ceiling removals were first proposed by qwen-code-dev-bot in #10858, which
conflicts with the knob that landed in #10870 and is superseded here.

Follow-up to #10870; the empty-value fault was raised there by doudouOUC (S1)
and chiga0 (R3-1) and confirmed post-merge by wenshao.
2026-09-06 01:00:42 +00:00

63 lines
2.9 KiB
TypeScript

/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import { configDefaults, defineConfig } from 'vitest/config';
export default defineConfig({
test: {
globals: true,
environment: 'node',
include: ['scripts/tests/**/*.test.{js,ts}'],
// Script tests that drive Linux-only CI (ubuntu-latest workflow jobs, or
// bash/shell fixtures Windows cannot express) fail on a Windows runner.
// Linux CI remains their authoritative coverage.
exclude:
process.platform === 'win32'
? [
...configDefaults.exclude,
'scripts/tests/e2e-shard-retry.test.js',
'scripts/tests/security-checks-audit-retry.test.js',
'scripts/tests/pr-self-report-label.test.js',
// Bash-driven workflow suites cannot run on Windows; pure
// YAML-parse workflow suites still do.
'scripts/tests/qwen-*-workflow.test.js',
'scripts/tests/serve-ab-workflow.test.js',
]
: [...configDefaults.exclude],
setupFiles: ['scripts/tests/test-setup.ts'],
// Several tests in install-script.test.js shell out to `node` to run
// create-standalone-package.js, which on Windows runs a full
// tar+gzip pass under antivirus inspection. Real runtimes observed on
// Windows CI: 4780ms / 1666ms / 1079ms — the 4.8s one is right at
// vitest's 5s default and flakes. Bump the suite timeout so a single
// slow subprocess startup doesn't fail an otherwise-healthy test run.
//
// 30s then proved to be the quiet-host figure. On the shared pool the
// same work runs about 5x slower, and release run 33725742855 lost its
// Quality Checks (Scripts) job to two files at once —
// qwen-autofix-workflow.test.js, whose heaviest case measures ~14s idle,
// and acp-serve-boundary-guard.test.js — neither of them slow, both past
// 30s under contention. Per-test `vi.setConfig` does not help: these
// cases register their timeout at collection, before it runs.
// `||`, not `??`: `??` only catches `undefined`, and the value this repo
// actually plants is `''` — that is what `${{ cond && 'x' || '' }}` renders
// when the condition is false. `Number('')` is 0, and vitest reads 0 as
// "no timeout at all", so the empty spelling would silently disarm every
// ceiling in this suite. `NaN` from a typo falls back the same way.
testTimeout: Number(process.env['QWEN_SCRIPTS_TEST_TIMEOUT_MS']) || 90_000,
coverage: {
provider: 'v8',
reporter: ['text', 'lcov'],
},
// No poolOptions override: the fixed 8-16 worker floor it used to carry
// oversubscribes the 3-core macOS runners. Vitest's default scales with
// the host cores, which is what every other suite in this repository
// uses.
//
// RPC-timeout exemption; see scripts/tests/unit-vitest-configs.test.ts.
dangerouslyIgnoreUnhandledErrors: process.platform !== 'linux',
},
});