返回 DeepSeek-Reasonix
graphics-recovery-smoke.mjs
根目录 / desktop / electron / scripts / graphics-recovery-smoke.mjs
1 import assert from "node:assert/strict";
2 import { execFileSync } from "node:child_process";
3 import { createRequire } from "node:module";
4 import { mkdtempSync, readFileSync, rmSync } from "node:fs";
5 import { tmpdir } from "node:os";
6 import { dirname, join, resolve } from "node:path";
7 import { fileURLToPath } from "node:url";
8 import { build } from "esbuild";
9
10 const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
11 const temp = mkdtempSync(join(tmpdir(), "reasonix-graphics-smoke-"));
12 const entry = join(temp, "main.cjs");
13 const native = process.argv.includes("--native-dialog");
14 const electron = createRequire(import.meta.url)("electron");
15 await build({ entryPoints: [join(root, "scripts/fixtures/graphics-recovery-main.ts")], outfile: entry, bundle: true, platform: "node", format: "cjs", external: ["electron"] });
16 function launch(profile, mode, args = []) {
17 const env = { ...process.env, REASONIX_RECOVERY_TEST_HOME: profile, REASONIX_RECOVERY_TEST_MODE: mode, REASONIX_RECOVERY_NATIVE_DIALOG: native ? "1" : "0" };
18 delete env.ELECTRON_RUN_AS_NODE;
19 execFileSync(electron, [entry, ...args], { env, stdio: "inherit", timeout: native ? 190_000 : 30_000, killSignal: "SIGKILL" });
20 return JSON.parse(readFileSync(join(profile, "result.json"), "utf8"));
21 }
22 try {
23 const profile = join(temp, "gpu");
24 const recovery = launch(profile, native ? "native" : "gpu");
25 assert.equal(recovery.phase, "completed");
26 assert.equal(recovery.relaunchArgs.includes("--reasonix-graphics-recovery"), recovery.actual);
27 assert.ok(recovery.events.indexOf("service-shutdown") < recovery.events.indexOf("close-allowed"));
28 if (native) console.log("PASS native recovery and draft-loss confirmation dialogs");
29 else {
30 assert.equal(recovery.prompts.length, 2);
31 assert.equal(recovery.prompts[0].buttons[0].includes("compatibility"), recovery.actual);
32 assert.match(recovery.prompts[1].title, /Draft not saved/);
33 const software = launch(profile, "software", ["--reasonix-graphics-recovery"]);
34 assert.equal(software.startup, false); assert.equal(software.actual, false);
35 assert.equal(software.argv.includes("--reasonix-graphics-recovery"), false);
36 assert.equal(launch(profile, "plain").startup, true);
37 console.log("PASS GPU events → confirmed draft loss → ordered restart → actual software rendering → next launch restores preference");
38 const renderer = launch(join(temp, "renderer"), "renderer");
39 assert.equal(renderer.reloads, 2);
40 assert.equal(renderer.prompts[0].buttons[0], "Restart / 重启");
41 console.log("PASS real renderer termination reloads once, then presents recovery without misattributing GPU");
42 launch(profile, "keep", ["--reasonix-graphics-recovery"]);
43 assert.equal(JSON.parse(readFileSync(join(profile, "graphics.json"), "utf8")).hardwareAcceleration, false);
44 assert.equal(launch(profile, "plain").startup, false);
45 console.log("PASS explicit keep-disabled choice persists across a fresh launch");
46 const pendingProfile = join(temp, "pending");
47 assert.equal(launch(pendingProfile, "record").prompts.length, 0);
48 assert.equal(launch(pendingProfile, "previous").prompts.length, 1);
49 assert.equal(launch(pendingProfile, "plain").prompts.length, 0);
50 console.log("PASS explicit GPU evidence offers recovery on the next launch and acknowledgement stops repetition");
51 for (const mode of ["during-dialog", "during-keep"]) {
52 const racingProfile = join(temp, mode);
53 launch(racingProfile, mode, mode === "during-keep" ? ["--reasonix-graphics-recovery"] : []);
54 assert.equal(JSON.parse(readFileSync(join(racingProfile, "graphics-fault.json"), "utf8")).pending, true);
55 assert.equal(launch(racingProfile, "previous").prompts.length, 1);
56 }
57 console.log("PASS both native notice paths preserve GPU failures that arrive during the dialog");
58 }
59 } finally {
60 rmSync(temp, { recursive: true, force: true });
61 }
62
62 lines Plain Text