AGC Rust 分片失败复核改按名单精确匹配,覆盖 bin 目标用例名
- run-rust-shell-test-shards.mjs:extractFailingTestNames 改为按本片名单精确匹配用例名,不再用 `tests::` / `process_session::tests::` 前缀白名单——bin 目标的 `agent::…::tests::…` 原先永远进不了复核,偶发假红直接判红 - run-rust-shell-test-shards.mjs:复核也失败时同时保留首次失败现场,不再只留复核那一次 - run-rust-shell-test-shards.test.mjs:新增「命名空间用例名也会进复核」的回归用例 - 验证:node --test apps/ai-game-creator-shell/scripts/run-rust-shell-test-shards.test.mjs 3 项通过
This commit is contained in:
@@ -447,7 +447,12 @@ async function runWithConcurrency(shards, runner) {
|
||||
return results;
|
||||
}
|
||||
|
||||
function extractFailingTestNames(result) {
|
||||
// 只认**本片名单里真实存在**的用例名:先按 `---- <name> stdout ----` / 失败清单行归一化,
|
||||
// 再拿名单做精确匹配。不要再用名字前缀白名单猜用例(历史上只放行 `tests::` 与
|
||||
// `process_session::tests::`,而 bin 目标的用例名形如 `agent::thread_manager::tests::…`,
|
||||
// 于是绝大多数用例永远进不了复核,偶发假红就直接判红)。
|
||||
function extractFailingTestNames(result, shardTestNames) {
|
||||
const known = new Set(shardTestNames);
|
||||
const names = new Set();
|
||||
for (const line of result.failures) {
|
||||
const normalized = line
|
||||
@@ -457,11 +462,8 @@ function extractFailingTestNames(result) {
|
||||
.replace(/\s*stdout\s*----$/, '')
|
||||
.replace(/\s*\(\d+\)\s*$/, '')
|
||||
.trim();
|
||||
const match = normalized.match(
|
||||
/^(process_session::tests::[A-Za-z0-9_:]+|tests::[A-Za-z0-9_:]+)$/,
|
||||
);
|
||||
if (match) {
|
||||
names.add(match[1]);
|
||||
if (known.has(normalized)) {
|
||||
names.add(normalized);
|
||||
}
|
||||
}
|
||||
return [...names];
|
||||
@@ -518,9 +520,7 @@ async function main() {
|
||||
}
|
||||
// 片内串行的时序型用例在高负载 CI 上会偶发假红。只对失败用例做一次
|
||||
// 有界复核:复核通过按 flaky 记录,复核失败才判红,避免把真实回归洗掉。
|
||||
const failingTestNames = extractFailingTestNames(result).filter((name) =>
|
||||
shardTestNames.includes(name),
|
||||
);
|
||||
const failingTestNames = extractFailingTestNames(result, shardTestNames);
|
||||
if (failingTestNames.length === 0) {
|
||||
return result;
|
||||
}
|
||||
@@ -531,10 +531,13 @@ async function main() {
|
||||
failingTestNames,
|
||||
);
|
||||
if (!retry.ok) {
|
||||
// 复核也失败就判红,但**两次的现场都留**:首次是整片的上下文,复核只跑失败用例,
|
||||
// 丢掉首次现场会让"到底整片跑成什么样"这件事在日志里消失。
|
||||
return {
|
||||
...result,
|
||||
failures: [
|
||||
`re-run of ${failingTestNames.length} failing test(s) also failed`,
|
||||
...result.failures,
|
||||
...retry.failures,
|
||||
],
|
||||
};
|
||||
|
||||
@@ -68,3 +68,25 @@ test('successful shard keeps its compact summary', (t) => {
|
||||
assert.match(result.output, /shard 1\/1 ok: 1 test\(s\)/);
|
||||
assert.doesNotMatch(result.output, /test passing_case \.\.\. ok/);
|
||||
});
|
||||
|
||||
// bin 目标的用例名带命名空间(`agent::thread_manager::tests::…`)。复核名单必须靠
|
||||
// 「本片名单精确匹配」认用例,不能靠名字前缀白名单,否则这类用例永远进不了重跑。
|
||||
test('namespaced failing test is re-run once before the shard is judged', (t) => {
|
||||
const result = runFixture(
|
||||
t,
|
||||
`
|
||||
mod agent {
|
||||
pub mod thread_manager {
|
||||
#[test]
|
||||
fn flaky_case() {
|
||||
assert_eq!(1, 2, "namespaced panic evidence");
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
);
|
||||
assert.equal(result.status, 1, result.output);
|
||||
assert.match(result.output, /re-run of 1 failing test\(s\) also failed/);
|
||||
assert.match(result.output, /agent::thread_manager::flaky_case/);
|
||||
assert.match(result.output, /namespaced panic evidence/);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user