返回 DeepSeek-Reasonix
desktop-windows-go-tests.mjs
根目录 / scripts / desktop-windows-go-tests.mjs
1 import { spawnSync } from "node:child_process";
2 import { resolve } from "node:path";
3 import { fileURLToPath } from "node:url";
4
5 export const historyTests = {
6 "history-3-5": "TestTaggedHistory1383To1385",
7 "history-6-7": "TestTaggedHistory1386To1387",
8 "history-8-9": "TestTaggedHistory1388To1389",
9 "history-10-11": "TestTaggedHistory13810To13811",
10 };
11 export const groups = ["A-B", "C", "D", "E-H", "I-M", "N-P", "Q-S", "T-Z", ...Object.keys(historyTests)];
12 export const conptyProbe = "TestWindowsTerminalProcessConPTYSmoke";
13 export const filters = {
14 "A-B": { skip: "^Test[C-Z]" },
15 "C": { run: "^TestC" },
16 "D": { run: "^TestD" },
17 "E-H": { run: "^Test[E-H]" },
18 "I-M": { run: "^Test[I-M]" },
19 "N-P": { run: "^Test[N-P]" },
20 "Q-S": { run: "^Test[Q-S]" },
21 "T-Z": { run: "^Test[T-Z]", skip: `^(${[conptyProbe, ...Object.values(historyTests)].join("|")})$` },
22 ...Object.fromEntries(Object.entries(historyTests).map(([group, name]) => [group, { run: `^${name}$` }])),
23 };
24
25 export function owners(name) {
26 const assigned = groups.filter(group => {
27 const { run, skip } = filters[group];
28 return (!run || new RegExp(run).test(name)) && (!skip || !new RegExp(skip).test(name));
29 });
30 if (name === conptyProbe) assigned.push("conpty-probe");
31 return assigned;
32 }
33
34 export function inventoryFromJSON(output) {
35 const names = new Map();
36 for (const line of output.split(/\r?\n/).filter(Boolean)) {
37 const event = JSON.parse(line);
38 const name = event.Output?.trim();
39 if (event.Action === "output" && /^(Test|Example|Fuzz)\S*$/u.test(name ?? "")) {
40 names.set(`${event.Package}/${name}`, name);
41 }
42 }
43 if (!names.size) throw new Error("Go returned no desktop test inventory");
44 return names;
45 }
46
47 export function verifyInventory(inventory, requireProbe = process.platform === "win32") {
48 const counts = Object.fromEntries([...groups, "conpty-probe"].map(group => [group, 0]));
49 for (const [key, name] of inventory) {
50 const assigned = owners(name);
51 if (assigned.length !== 1) throw new Error(`${key} belongs to ${assigned.length} test groups`);
52 counts[assigned[0]]++;
53 }
54 for (const group of groups) {
55 if (!counts[group]) throw new Error(`Empty desktop Windows test group: ${group}`);
56 }
57 if (requireProbe && counts["conpty-probe"] !== 1) throw new Error("Missing or duplicated native ConPTY probe");
58 return counts;
59 }
60
61 export function testArgs(group, race = false) {
62 if (!groups.includes(group)) throw new Error(`Unknown desktop Windows test group: ${group}`);
63 const { run, skip } = filters[group];
64 // go's default alarm is 10m; the desktop race sweep already exceeded it and
65 // the unpartitioned suite needs ~25m locally. Give every group the headroom.
66 return ["test", ...(race ? ["-race"] : []), "-timeout=25m", ...(run ? ["-run", run] : []), ...(skip ? ["-skip", skip] : []), "./..."];
67 }
68
69 function main(group, mode) {
70 if (mode && mode !== "--race") throw new Error(`Unknown test mode: ${mode}`);
71 const race = mode === "--race";
72 const selected = group === "--all" ? groups : group === "--verify" ? [] : [group];
73 const commands = selected.map(name => testArgs(name, race));
74 // Ask Go for the current platform's inventory, including build-tagged tests,
75 // examples and fuzz seeds. JSON is used only for listing, not test execution.
76 const listed = spawnSync("go", ["test", ...(race ? ["-race"] : []), "-list", ".", "-json", "./..."], { encoding: "utf8", maxBuffer: 16 << 20 });
77 if (listed.error) throw listed.error;
78 if (listed.status !== 0) {
79 process.stderr.write(listed.stdout + listed.stderr);
80 return listed.status ?? 1;
81 }
82 console.log("Desktop test partition:", verifyInventory(inventoryFromJSON(listed.stdout)));
83 for (const args of commands) {
84 console.log(`go ${args.join(" ")}`);
85 const result = spawnSync("go", args, { stdio: "inherit" });
86 if (result.error) throw result.error;
87 if (result.status !== 0) return result.status ?? 1;
88 }
89 return 0;
90 }
91
92 if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
93 process.exitCode = main(process.argv[2], process.argv[3]);
94 }
95
95 lines Plain Text