③ 驱逐用例抗并发负载:一次灌满替代 48 轮逐张等待
- 现象:驱逐用例逐张 waitFor 48 张(3 个读取槽 + 48 轮 act/轮询)在同树多个写者并发跑测试时,会把用例 5s 超时耗光(Test timed out in 5000ms),红的是超时不是断言; - 改法:48 张一次性入队,只等"读取都已发出"(read 次数 ≥ 49),不再逐张断言 48 个卡的状态; - 原因说明:驱逐本来就会连锁(目标卡被驱逐 → 补扫描重读 → 再挤掉一张未被观察的填充卡),逐张断言会在链条行进中读到 undefined,红的是时序不是契约; - 核心断言一条不动:目标卡必须被重新请求(读次数 1 → 2)且最终回到 loaded;本用例超时放宽到 60s、内部 waitFor 20s; - 验证:改动前后各连跑 6 轮 + 4 路并发同时跑两个用例文件,全绿。
This commit is contained in:
@@ -1920,7 +1920,7 @@ describe('冷启动首屏的放行范围与放行顺序', () => {
|
|||||||
}
|
}
|
||||||
// 首屏要保证有图可读:可见的 12 张一张都不能少。
|
// 首屏要保证有图可读:可见的 12 张一张都不能少。
|
||||||
expect(readPathsSet.size).toBe(resources.length - offscreen.length);
|
expect(readPathsSet.size).toBe(resources.length - offscreen.length);
|
||||||
});
|
}, 30000);
|
||||||
|
|
||||||
it('releases intersecting cards in two bands: viewport first, margin second', async () => {
|
it('releases intersecting cards in two bands: viewport first, margin second', async () => {
|
||||||
// B:一次 observer 回调可能同时报来 ~21 张相交卡,物理读取只有 3 个槽。
|
// B:一次 observer 回调可能同时报来 ~21 张相交卡,物理读取只有 3 个槽。
|
||||||
@@ -2037,16 +2037,31 @@ describe('预览缓存驱逐后的可见性复核', () => {
|
|||||||
expect(targetReads()).toHaveLength(1);
|
expect(targetReads()).toHaveLength(1);
|
||||||
|
|
||||||
// 灌满缓存:第 49 张落地时把最早的、仍然可见的这张挤出去。
|
// 灌满缓存:第 49 张落地时把最早的、仍然可见的这张挤出去。
|
||||||
for (const filler of fillers) {
|
//
|
||||||
const identity = result.current.identityByResourceId.get(filler.id)!;
|
// 一次性把 48 张都排进队列、只等"读取都发出去了",**不逐张断言 48 个卡的状态**:
|
||||||
act(() => result.current.requestPreview(filler, identity, 'visible'));
|
// 驱逐本来就会往后连锁(目标卡被驱逐 → 补扫描重读 → 再挤掉一张别人),
|
||||||
await waitFor(() =>
|
// 逐张断言会在链条行进中读到 `undefined`,红的是时序不是契约。
|
||||||
expect(result.current.previews.get(identity)?.status).toBe('loaded'),
|
act(() => {
|
||||||
);
|
for (const filler of fillers) {
|
||||||
}
|
result.current.requestPreview(
|
||||||
|
filler,
|
||||||
|
result.current.identityByResourceId.get(filler.id)!,
|
||||||
|
'visible',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await waitFor(
|
||||||
|
() =>
|
||||||
|
expect(previewReadCalls(invoke).length).toBeGreaterThanOrEqual(
|
||||||
|
fillers.length + 1,
|
||||||
|
),
|
||||||
|
{ timeout: 20000 },
|
||||||
|
);
|
||||||
|
|
||||||
// 驱逐后必须补一次可见性复核:仍可见的卡要重新入队并重新读到图。
|
// 驱逐后必须补一次可见性复核:仍可见的卡要重新入队并重新读到图。
|
||||||
await waitFor(() => expect(targetReads()).toHaveLength(2));
|
await waitFor(() => expect(targetReads()).toHaveLength(2), {
|
||||||
|
timeout: 20000,
|
||||||
|
});
|
||||||
expect(result.current.previews.get(targetIdentity)?.status).toBe('loaded');
|
expect(result.current.previews.get(targetIdentity)?.status).toBe('loaded');
|
||||||
});
|
}, 60000);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user