first commit
This commit is contained in:
151
apps/miniprogram/pages/terminal/terminalRenderScheduler.test.ts
Normal file
151
apps/miniprogram/pages/terminal/terminalRenderScheduler.test.ts
Normal file
@@ -0,0 +1,151 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const { createTerminalRenderScheduler, mergeTerminalRenderOptions } = require("./terminalRenderScheduler.js");
|
||||
|
||||
describe("terminalRenderScheduler", () => {
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
it("会把渲染选项按单一真相源合并", () => {
|
||||
expect(mergeTerminalRenderOptions(null, null)).toEqual({ sendResize: false });
|
||||
expect(mergeTerminalRenderOptions({ sendResize: false }, { sendResize: true })).toEqual({
|
||||
sendResize: true
|
||||
});
|
||||
expect(mergeTerminalRenderOptions({ sendResize: true }, { sendResize: false })).toEqual({
|
||||
sendResize: true
|
||||
});
|
||||
});
|
||||
|
||||
it("stdout 高频输出会在一个批窗口内合并成一次渲染", () => {
|
||||
const runs = [];
|
||||
const scheduler = createTerminalRenderScheduler({
|
||||
batchWindowMs: 16,
|
||||
runRender(request, done) {
|
||||
runs.push(request);
|
||||
done({ ok: true });
|
||||
}
|
||||
});
|
||||
|
||||
scheduler.requestStdout({ appendStartedAt: 10, visibleBytes: 12 });
|
||||
scheduler.requestStdout({ appendStartedAt: 12, visibleBytes: 18 });
|
||||
|
||||
expect(runs).toHaveLength(0);
|
||||
|
||||
vi.advanceTimersByTime(16);
|
||||
|
||||
expect(runs).toHaveLength(1);
|
||||
expect(runs[0].reason).toBe("stdout_batch");
|
||||
expect(runs[0].stdoutSamples).toHaveLength(2);
|
||||
expect(runs[0].stdoutSamples[0]).toMatchObject({ appendStartedAt: 10, visibleBytes: 12 });
|
||||
expect(runs[0].stdoutSamples[1]).toMatchObject({ appendStartedAt: 12, visibleBytes: 18 });
|
||||
});
|
||||
|
||||
it("进行中的渲染完成后,只会补跑一轮合并后的后续请求", () => {
|
||||
const runs = [];
|
||||
const finishes = [];
|
||||
const callbackMarks = [];
|
||||
const scheduler = createTerminalRenderScheduler({
|
||||
batchWindowMs: 16,
|
||||
runRender(request, done) {
|
||||
runs.push(request);
|
||||
finishes.push(done);
|
||||
}
|
||||
});
|
||||
|
||||
scheduler.requestImmediate({}, (_result, request) => {
|
||||
callbackMarks.push(`first:${request.reason}`);
|
||||
});
|
||||
expect(runs).toHaveLength(1);
|
||||
|
||||
scheduler.requestImmediate({ sendResize: true }, (_result, request) => {
|
||||
callbackMarks.push(`second:${request.reason}:${request.stdoutSamples.length}`);
|
||||
});
|
||||
scheduler.requestStdout({ appendStartedAt: 20, visibleBytes: 5 });
|
||||
|
||||
expect(runs).toHaveLength(1);
|
||||
|
||||
finishes.shift()({ ok: true });
|
||||
|
||||
expect(runs).toHaveLength(2);
|
||||
expect(runs[1].reason).toBe("pending_stdout");
|
||||
expect(runs[1].options).toEqual({ sendResize: true });
|
||||
expect(runs[1].stdoutSamples).toHaveLength(1);
|
||||
|
||||
finishes.shift()({ ok: true });
|
||||
|
||||
expect(callbackMarks).toEqual(["first:immediate", "second:pending_stdout:1"]);
|
||||
});
|
||||
|
||||
it("普通立即渲染会抢占尚未触发的 stdout 定时批处理", () => {
|
||||
const runs = [];
|
||||
const scheduler = createTerminalRenderScheduler({
|
||||
batchWindowMs: 16,
|
||||
runRender(request, done) {
|
||||
runs.push(request);
|
||||
done({ ok: true });
|
||||
}
|
||||
});
|
||||
|
||||
scheduler.requestStdout({ appendStartedAt: 10, visibleBytes: 3 });
|
||||
scheduler.requestImmediate({ sendResize: true });
|
||||
|
||||
expect(runs).toHaveLength(1);
|
||||
expect(runs[0].reason).toBe("immediate");
|
||||
expect(runs[0].options).toEqual({ sendResize: true });
|
||||
expect(runs[0].stdoutSamples).toHaveLength(1);
|
||||
|
||||
vi.advanceTimersByTime(16);
|
||||
|
||||
expect(runs).toHaveLength(1);
|
||||
});
|
||||
|
||||
it("支持输出当前 pending 与 in-flight 的调度快照,便于慢场景诊断", () => {
|
||||
const finishes = [];
|
||||
let now = 100;
|
||||
const scheduler = createTerminalRenderScheduler({
|
||||
batchWindowMs: 16,
|
||||
now: () => now,
|
||||
runRender(request, done) {
|
||||
finishes.push(done);
|
||||
}
|
||||
});
|
||||
|
||||
scheduler.requestStdout({ text: "你好", appendStartedAt: 80, visibleBytes: 6 });
|
||||
now = 140;
|
||||
expect(scheduler.getSnapshot()).toMatchObject({
|
||||
inFlight: false,
|
||||
pending: {
|
||||
waitMs: 40,
|
||||
stdoutSampleCount: 1,
|
||||
stdoutRawBytes: 6
|
||||
},
|
||||
active: null
|
||||
});
|
||||
|
||||
vi.advanceTimersByTime(16);
|
||||
now = 180;
|
||||
expect(scheduler.getSnapshot()).toMatchObject({
|
||||
inFlight: true,
|
||||
pending: null,
|
||||
active: {
|
||||
reason: "stdout_batch",
|
||||
ageMs: 40,
|
||||
waitMs: 40,
|
||||
stdoutSampleCount: 1,
|
||||
stdoutRawBytes: 6
|
||||
}
|
||||
});
|
||||
|
||||
finishes.shift()({ ok: true });
|
||||
expect(scheduler.getSnapshot()).toMatchObject({
|
||||
inFlight: false,
|
||||
pending: null,
|
||||
active: null
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user