test: share repeated boundary preambles to restore the jscpd gate (#2691)
Squash merge of https://github.com/morluto/rea/pull/2691. Co-authored-by: NIU-123370 <191000457+NIU-123370@users.noreply.github.com>
This commit is contained in:
parent
782cc3b060
commit
8b1549a264
|
|
@ -143,3 +143,13 @@ export const completeReconstructionCoverageData = () => {
|
|||
],
|
||||
});
|
||||
};
|
||||
|
||||
/** Complete workspace with its first verifier result and boundary narrowed once. */
|
||||
export const completeReconstructionCoverageFixture = () => {
|
||||
const workspace = completeReconstructionCoverageData();
|
||||
const result = workspace.verifier_results[0];
|
||||
const boundary = workspace.boundaries[0];
|
||||
if (result === undefined || boundary === undefined)
|
||||
throw new Error("Expected complete reconstruction coverage fixture");
|
||||
return { workspace, result, boundary };
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { describe, expect, it } from "vitest";
|
|||
|
||||
import {
|
||||
completeReconstructionCoverageData,
|
||||
completeReconstructionCoverageFixture,
|
||||
RECONSTRUCTION_COVERAGE_NOW,
|
||||
reconstructionCoverageEvidenceId,
|
||||
} from "./reconstructionCoverage.fixture.js";
|
||||
|
|
@ -288,11 +289,8 @@ describe("reconstruction coverage verifier selection", () => {
|
|||
|
||||
describe("reconstruction coverage conflicting latest verifier observations", () => {
|
||||
it("keeps conflicting tied assessments unknown regardless of input order", () => {
|
||||
const workspace = completeReconstructionCoverageData();
|
||||
const result = workspace.verifier_results[0];
|
||||
const boundary = workspace.boundaries[0];
|
||||
if (result === undefined || boundary === undefined)
|
||||
throw new Error("Expected complete reconstruction coverage fixture");
|
||||
const { workspace, result, boundary } =
|
||||
completeReconstructionCoverageFixture();
|
||||
const failed = {
|
||||
...result,
|
||||
status: "fail" as const,
|
||||
|
|
@ -338,11 +336,8 @@ describe("reconstruction coverage conflicting latest verifier observations", ()
|
|||
|
||||
describe("reconstruction coverage equivalent latest verifier observations", () => {
|
||||
it("coalesces equivalent equal-instant observations and retains all evidence", () => {
|
||||
const workspace = completeReconstructionCoverageData();
|
||||
const result = workspace.verifier_results[0];
|
||||
const boundary = workspace.boundaries[0];
|
||||
if (result === undefined || boundary === undefined)
|
||||
throw new Error("Expected complete reconstruction coverage fixture");
|
||||
const { workspace, result, boundary } =
|
||||
completeReconstructionCoverageFixture();
|
||||
const first = {
|
||||
...result,
|
||||
observed_at: "2026-07-16T11:00:00.123456789012345678900Z",
|
||||
|
|
@ -388,11 +383,8 @@ describe("reconstruction coverage equivalent latest verifier observations", () =
|
|||
|
||||
describe("reconstruction coverage verifier timestamp selection", () => {
|
||||
it("lets a later unambiguous observation supersede an older tie", () => {
|
||||
const workspace = completeReconstructionCoverageData();
|
||||
const result = workspace.verifier_results[0];
|
||||
const boundary = workspace.boundaries[0];
|
||||
if (result === undefined || boundary === undefined)
|
||||
throw new Error("Expected complete reconstruction coverage fixture");
|
||||
const { workspace, result, boundary } =
|
||||
completeReconstructionCoverageFixture();
|
||||
const failed = { ...result, status: "fail" as const };
|
||||
const latestPass = {
|
||||
...result,
|
||||
|
|
@ -412,50 +404,14 @@ describe("reconstruction coverage verifier timestamp selection", () => {
|
|||
).toMatchObject({ status: "ready", reasons: [] });
|
||||
});
|
||||
|
||||
it("orders offset-bearing verifier timestamps chronologically", () => {
|
||||
const workspace = completeReconstructionCoverageData();
|
||||
const result = workspace.verifier_results[0];
|
||||
if (result === undefined)
|
||||
throw new Error("Expected fixture verifier result");
|
||||
const semantic = workspace;
|
||||
const changed = createReconstructionCoverageData({
|
||||
...semantic,
|
||||
verifier_results: [
|
||||
{ ...result, observed_at: "2026-07-16T08:00:00.000Z" },
|
||||
{
|
||||
...result,
|
||||
observed_at: "2026-07-16T04:00:00.000-05:00",
|
||||
status: "fail",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
expect(
|
||||
evaluateReconstructionClosure(
|
||||
changed,
|
||||
"replacement.cli",
|
||||
RECONSTRUCTION_COVERAGE_NOW,
|
||||
),
|
||||
).toMatchObject({
|
||||
status: "failed",
|
||||
reasons: [expect.objectContaining({ code: "verifier-failed" })],
|
||||
});
|
||||
});
|
||||
|
||||
it("selects the later result when timestamps differ below millisecond precision", () => {
|
||||
const workspace = completeReconstructionCoverageData();
|
||||
const result = workspace.verifier_results[0];
|
||||
if (result === undefined)
|
||||
throw new Error("Expected fixture verifier result");
|
||||
/** Evaluate a workspace whose newest verifier observation fails the closure. */
|
||||
const expectNewestObservationFails = (passedAt: string, failedAt: string) => {
|
||||
const { workspace, result } = completeReconstructionCoverageFixture();
|
||||
const changed = createReconstructionCoverageData({
|
||||
...workspace,
|
||||
verifier_results: [
|
||||
{ ...result, observed_at: "2026-07-16T11:00:00.1231Z" },
|
||||
{
|
||||
...result,
|
||||
observed_at: "2026-07-16T11:00:00.1239Z",
|
||||
status: "fail",
|
||||
},
|
||||
{ ...result, observed_at: passedAt },
|
||||
{ ...result, observed_at: failedAt, status: "fail" },
|
||||
],
|
||||
});
|
||||
|
||||
|
|
@ -469,15 +425,26 @@ describe("reconstruction coverage verifier timestamp selection", () => {
|
|||
status: "failed",
|
||||
reasons: [expect.objectContaining({ code: "verifier-failed" })],
|
||||
});
|
||||
};
|
||||
|
||||
it("orders offset-bearing verifier timestamps chronologically", () => {
|
||||
expectNewestObservationFails(
|
||||
"2026-07-16T08:00:00.000Z",
|
||||
"2026-07-16T04:00:00.000-05:00",
|
||||
);
|
||||
});
|
||||
|
||||
it("selects the later result when timestamps differ below millisecond precision", () => {
|
||||
expectNewestObservationFails(
|
||||
"2026-07-16T11:00:00.1231Z",
|
||||
"2026-07-16T11:00:00.1239Z",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("reconstruction coverage verifier future timestamps", () => {
|
||||
it("treats an observation beyond millisecond-precision now as future", () => {
|
||||
const workspace = completeReconstructionCoverageData();
|
||||
const result = workspace.verifier_results[0];
|
||||
if (result === undefined)
|
||||
throw new Error("Expected fixture verifier result");
|
||||
const { workspace, result } = completeReconstructionCoverageFixture();
|
||||
const changed = createReconstructionCoverageData({
|
||||
...workspace,
|
||||
verifier_results: [
|
||||
|
|
@ -505,10 +472,7 @@ describe("reconstruction coverage verifier future timestamps", () => {
|
|||
});
|
||||
|
||||
it("rejects verifier observations from the future", () => {
|
||||
const workspace = completeReconstructionCoverageData();
|
||||
const result = workspace.verifier_results[0];
|
||||
if (result === undefined)
|
||||
throw new Error("Expected fixture verifier result");
|
||||
const { workspace, result } = completeReconstructionCoverageFixture();
|
||||
const semantic = workspace;
|
||||
const changed = createReconstructionCoverageData({
|
||||
...semantic,
|
||||
|
|
|
|||
|
|
@ -35,6 +35,28 @@ const validPng = Buffer.from(
|
|||
"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+jv4sAAAAASUVORK5CYII=",
|
||||
"base64",
|
||||
);
|
||||
|
||||
/** Screenshot payload as the native helper reports one PNG buffer. */
|
||||
const screenshotOf = (bytes: Buffer) => ({
|
||||
mime_type: "image/png",
|
||||
base64: bytes.toString("base64"),
|
||||
sha256: createHash("sha256").update(bytes).digest("hex"),
|
||||
width: bytes.readUInt32BE(16),
|
||||
height: bytes.readUInt32BE(20),
|
||||
});
|
||||
|
||||
/** Observe the fixture snapshot carrying one screenshot payload. */
|
||||
const observeWithScreenshot = (screenshot: Record<string, unknown>) =>
|
||||
observeNativeUi(
|
||||
target,
|
||||
"observe_native_ui",
|
||||
{ ...scope, screenshot: true },
|
||||
{
|
||||
environment: {},
|
||||
invoke: async () => ({ ok: true, result: { ...snapshot, screenshot } }),
|
||||
},
|
||||
);
|
||||
|
||||
it.each([
|
||||
{ offset: 8, value: 12 },
|
||||
{ offset: 16, value: 0x8000_0000 },
|
||||
|
|
@ -44,49 +66,16 @@ it.each([
|
|||
async ({ offset, value }) => {
|
||||
const bytes = Buffer.from(validPng);
|
||||
bytes.writeUInt32BE(value, offset);
|
||||
const screenshot = {
|
||||
mime_type: "image/png",
|
||||
base64: bytes.toString("base64"),
|
||||
sha256: createHash("sha256").update(bytes).digest("hex"),
|
||||
width: bytes.readUInt32BE(16),
|
||||
height: bytes.readUInt32BE(20),
|
||||
};
|
||||
const result = await observeNativeUi(
|
||||
target,
|
||||
"observe_native_ui",
|
||||
{ ...scope, screenshot: true },
|
||||
{
|
||||
environment: {},
|
||||
invoke: async () => ({
|
||||
ok: true,
|
||||
result: { ...snapshot, screenshot },
|
||||
}),
|
||||
},
|
||||
);
|
||||
const result = await observeWithScreenshot(screenshotOf(bytes));
|
||||
expect(result.ok).toBe(false);
|
||||
},
|
||||
);
|
||||
describe("native UI screenshot validation", () => {
|
||||
it("rejects malformed or mismatched screenshot bytes from the helper", async () => {
|
||||
const screenshot = {
|
||||
mime_type: "image/png",
|
||||
base64: validPng.toString("base64"),
|
||||
const result = await observeWithScreenshot({
|
||||
...screenshotOf(validPng),
|
||||
sha256: "0".repeat(64),
|
||||
width: 1,
|
||||
height: 1,
|
||||
};
|
||||
const result = await observeNativeUi(
|
||||
target,
|
||||
"observe_native_ui",
|
||||
{ ...scope, screenshot: true },
|
||||
{
|
||||
environment: {},
|
||||
invoke: async () => ({
|
||||
ok: true,
|
||||
result: { ...snapshot, screenshot },
|
||||
}),
|
||||
},
|
||||
);
|
||||
});
|
||||
expect(result.ok).toBe(false);
|
||||
});
|
||||
|
||||
|
|
@ -97,26 +86,10 @@ describe("native UI screenshot validation", () => {
|
|||
])(
|
||||
"rejects invalid screenshot field variants from the helper",
|
||||
async (change) => {
|
||||
const screenshot = {
|
||||
mime_type: "image/png",
|
||||
base64: validPng.toString("base64"),
|
||||
sha256: createHash("sha256").update(validPng).digest("hex"),
|
||||
width: 1,
|
||||
height: 1,
|
||||
const result = await observeWithScreenshot({
|
||||
...screenshotOf(validPng),
|
||||
...change,
|
||||
};
|
||||
const result = await observeNativeUi(
|
||||
target,
|
||||
"observe_native_ui",
|
||||
{ ...scope, screenshot: true },
|
||||
{
|
||||
environment: {},
|
||||
invoke: async () => ({
|
||||
ok: true,
|
||||
result: { ...snapshot, screenshot },
|
||||
}),
|
||||
},
|
||||
);
|
||||
});
|
||||
expect(result.ok).toBe(false);
|
||||
},
|
||||
);
|
||||
|
|
@ -126,49 +99,12 @@ describe("native UI screenshot validation", () => {
|
|||
const type = bytes.subarray(12, 16);
|
||||
type[0] = (type[0] ?? 0) | 0x80;
|
||||
expect(type.toString("ascii")).toBe("IHDR");
|
||||
const screenshot = {
|
||||
mime_type: "image/png",
|
||||
base64: bytes.toString("base64"),
|
||||
sha256: createHash("sha256").update(bytes).digest("hex"),
|
||||
width: 1,
|
||||
height: 1,
|
||||
};
|
||||
const result = await observeNativeUi(
|
||||
target,
|
||||
"observe_native_ui",
|
||||
{ ...scope, screenshot: true },
|
||||
{
|
||||
environment: {},
|
||||
invoke: async () => ({
|
||||
ok: true,
|
||||
result: { ...snapshot, screenshot },
|
||||
}),
|
||||
},
|
||||
);
|
||||
const result = await observeWithScreenshot(screenshotOf(bytes));
|
||||
expect(result.ok).toBe(false);
|
||||
});
|
||||
|
||||
it("accepts a self-consistent PNG screenshot from the helper", async () => {
|
||||
const bytes = validPng;
|
||||
const screenshot = {
|
||||
mime_type: "image/png",
|
||||
base64: bytes.toString("base64"),
|
||||
sha256: createHash("sha256").update(bytes).digest("hex"),
|
||||
width: 1,
|
||||
height: 1,
|
||||
};
|
||||
const result = await observeNativeUi(
|
||||
target,
|
||||
"observe_native_ui",
|
||||
{ ...scope, screenshot: true },
|
||||
{
|
||||
environment: {},
|
||||
invoke: async () => ({
|
||||
ok: true,
|
||||
result: { ...snapshot, screenshot },
|
||||
}),
|
||||
},
|
||||
);
|
||||
const result = await observeWithScreenshot(screenshotOf(validPng));
|
||||
expect(result.ok).toBe(true);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -188,8 +188,12 @@ it("closes the service and retains an unexpected producer rejection", async () =
|
|||
});
|
||||
});
|
||||
|
||||
it("rejects an oversized selector budget before the CLI invokes its service", async () => {
|
||||
const cli = Cli.create("capture-selector-test", { sync: false });
|
||||
/** Serve one inspection request whose service must never be reached. */
|
||||
const rejectBeforeService = async (
|
||||
name: string,
|
||||
args: string[],
|
||||
): Promise<string> => {
|
||||
const cli = Cli.create(name, { sync: false });
|
||||
let called = false;
|
||||
registerCaptureCommands(
|
||||
cli,
|
||||
|
|
@ -207,66 +211,41 @@ it("rejects an oversized selector budget before the CLI invokes its service", as
|
|||
},
|
||||
);
|
||||
let stdout = "";
|
||||
await cli.serve(
|
||||
[
|
||||
"inspect-packet-capture",
|
||||
"recording.pcap",
|
||||
"--fields",
|
||||
"x".repeat(8192),
|
||||
"--display_filter",
|
||||
"界".repeat(8192),
|
||||
"--format",
|
||||
"json",
|
||||
],
|
||||
{
|
||||
stdout: (text) => {
|
||||
stdout += text;
|
||||
},
|
||||
exit: () => {},
|
||||
await cli.serve(args, {
|
||||
stdout: (text) => {
|
||||
stdout += text;
|
||||
},
|
||||
);
|
||||
exit: () => {},
|
||||
});
|
||||
expect(called).toBe(false);
|
||||
return stdout;
|
||||
};
|
||||
|
||||
it("rejects an oversized selector budget before the CLI invokes its service", async () => {
|
||||
const stdout = await rejectBeforeService("capture-selector-test", [
|
||||
"inspect-packet-capture",
|
||||
"recording.pcap",
|
||||
"--fields",
|
||||
"x".repeat(8192),
|
||||
"--display_filter",
|
||||
"界".repeat(8192),
|
||||
"--format",
|
||||
"json",
|
||||
]);
|
||||
expect(stdout).toContain("32 KiB");
|
||||
});
|
||||
|
||||
it("rejects conflicting output options before the CLI invokes its service", async () => {
|
||||
const cli = Cli.create("capture-window-test", { sync: false });
|
||||
let called = false;
|
||||
registerCaptureCommands(
|
||||
cli,
|
||||
silentLogger,
|
||||
{},
|
||||
{
|
||||
inspectFields: async () => {
|
||||
throw new Error("Unexpected field discovery call");
|
||||
},
|
||||
inspect: async () => {
|
||||
called = true;
|
||||
throw new Error("Must not inspect");
|
||||
},
|
||||
close: async () => {},
|
||||
},
|
||||
);
|
||||
let stdout = "";
|
||||
await cli.serve(
|
||||
[
|
||||
"inspect-packet-capture",
|
||||
"recording.pcap",
|
||||
"--fields",
|
||||
"ip.addr",
|
||||
"--all_matches",
|
||||
"--match_limit",
|
||||
"20",
|
||||
"--format",
|
||||
"json",
|
||||
],
|
||||
{
|
||||
stdout: (text) => {
|
||||
stdout += text;
|
||||
},
|
||||
exit: () => {},
|
||||
},
|
||||
);
|
||||
expect(called).toBe(false);
|
||||
const stdout = await rejectBeforeService("capture-window-test", [
|
||||
"inspect-packet-capture",
|
||||
"recording.pcap",
|
||||
"--fields",
|
||||
"ip.addr",
|
||||
"--all_matches",
|
||||
"--match_limit",
|
||||
"20",
|
||||
"--format",
|
||||
"json",
|
||||
]);
|
||||
expect(stdout).toContain("mutually exclusive");
|
||||
});
|
||||
|
|
|
|||
|
|
@ -209,13 +209,7 @@ describe("installer TTY fallback", { timeout: 20_000 }, () => {
|
|||
cwd: process.cwd(),
|
||||
env: {
|
||||
...process.env,
|
||||
HOME: fixture.home,
|
||||
TMPDIR: fixture.temporary,
|
||||
PATH: `${fixture.bin}:/usr/bin:/bin`,
|
||||
FAKE_NPM_LOG: fixture.npmLog,
|
||||
FAKE_REA_LOG: fixture.reaLog,
|
||||
FAKE_REA_SOURCE: join(fixture.bin, "rea-source"),
|
||||
FAKE_NPM_PREFIX: join(fixture.home, ".npm-global"),
|
||||
...installerEnvironment(fixture),
|
||||
TERM: "xterm-256color",
|
||||
},
|
||||
name: "xterm-256color",
|
||||
|
|
@ -581,6 +575,19 @@ const executable = async (path: string, source: string): Promise<void> => {
|
|||
await chmod(path, 0o755);
|
||||
};
|
||||
|
||||
/** Fixture-owned installer environment shared by the exec, pipe and PTY runs. */
|
||||
const installerEnvironment = (
|
||||
fixture: InstallerFixture,
|
||||
): Record<string, string> => ({
|
||||
HOME: fixture.home,
|
||||
TMPDIR: fixture.temporary,
|
||||
PATH: `${fixture.bin}:/usr/bin:/bin`,
|
||||
FAKE_NPM_LOG: fixture.npmLog,
|
||||
FAKE_REA_LOG: fixture.reaLog,
|
||||
FAKE_REA_SOURCE: join(fixture.bin, "rea-source"),
|
||||
FAKE_NPM_PREFIX: join(fixture.home, ".npm-global"),
|
||||
});
|
||||
|
||||
const runInstaller = async (
|
||||
fixture: InstallerFixture,
|
||||
args: readonly string[] = [],
|
||||
|
|
@ -590,13 +597,7 @@ const runInstaller = async (
|
|||
execFileAsync("/bin/bash", [script, ...args], {
|
||||
env: {
|
||||
...process.env,
|
||||
HOME: fixture.home,
|
||||
TMPDIR: fixture.temporary,
|
||||
PATH: `${fixture.bin}:/usr/bin:/bin`,
|
||||
FAKE_NPM_LOG: fixture.npmLog,
|
||||
FAKE_REA_LOG: fixture.reaLog,
|
||||
FAKE_REA_SOURCE: join(fixture.bin, "rea-source"),
|
||||
FAKE_NPM_PREFIX: join(fixture.home, ".npm-global"),
|
||||
...installerEnvironment(fixture),
|
||||
...overrides,
|
||||
},
|
||||
});
|
||||
|
|
@ -618,13 +619,7 @@ const runPipedInstaller = async (
|
|||
new Promise((resolve, reject) => {
|
||||
const child = spawn("/bin/bash", ["-s", "--", ...args], {
|
||||
env: {
|
||||
HOME: fixture.home,
|
||||
TMPDIR: fixture.temporary,
|
||||
PATH: `${fixture.bin}:/usr/bin:/bin`,
|
||||
FAKE_NPM_LOG: fixture.npmLog,
|
||||
FAKE_REA_LOG: fixture.reaLog,
|
||||
FAKE_REA_SOURCE: join(fixture.bin, "rea-source"),
|
||||
FAKE_NPM_PREFIX: join(fixture.home, ".npm-global"),
|
||||
...installerEnvironment(fixture),
|
||||
...overrides,
|
||||
},
|
||||
stdio: ["pipe", "pipe", "pipe"],
|
||||
|
|
|
|||
|
|
@ -54,6 +54,42 @@ const holdReadHandle = (path: string, reason: string) => {
|
|||
};
|
||||
};
|
||||
|
||||
/** Linux setup host with its VS Code client configuration directory prepared. */
|
||||
const preparedVsCodeSetupHost = async (prefix: string) => {
|
||||
const home = await createTestTempDirectory(prefix);
|
||||
const host = systemSetupHost(
|
||||
{ platform: "linux", homeDirectory: home } as DoctorHost,
|
||||
{ HOME: home, XDG_CONFIG_HOME: join(home, "xdg") },
|
||||
);
|
||||
const client = (await host.supportedClients()).find(
|
||||
({ name }) => name === "vscode",
|
||||
);
|
||||
if (client === undefined) throw new Error("VS Code setup client missing");
|
||||
await mkdir(dirname(client.configPath), { recursive: true });
|
||||
return { home, host, client };
|
||||
};
|
||||
|
||||
/** Release the held read handle and show host cleanup reuses it as a third attempt. */
|
||||
const expectCloseReclaimsHandle = async (
|
||||
host: { close?: () => Promise<string | undefined> },
|
||||
closeAttempts: readonly object[],
|
||||
release: () => void,
|
||||
) => {
|
||||
release();
|
||||
expect(await host.close?.()).toBeUndefined();
|
||||
expect(closeAttempts).toHaveLength(3);
|
||||
expect(closeAttempts[2]).toBe(closeAttempts[0]);
|
||||
};
|
||||
|
||||
/** Give up on the assertion path: release the handle and let cleanup close it. */
|
||||
const cleanupHeldHandle = async (
|
||||
host: { close?: () => Promise<string | undefined> },
|
||||
release: () => void,
|
||||
) => {
|
||||
release();
|
||||
await host.close?.();
|
||||
};
|
||||
|
||||
it("retains invalid UTF-8 diagnostics and the uninstall read owner when close fails", async () => {
|
||||
const home = await createTestTempDirectory("rea-uninstall-utf8-close-");
|
||||
const path = join(home, "client.json");
|
||||
|
|
@ -77,13 +113,9 @@ it("retains invalid UTF-8 diagnostics and the uninstall read owner when close fa
|
|||
});
|
||||
expect(await readFile(path)).toEqual(original);
|
||||
expect(closeAttempts).toHaveLength(2);
|
||||
release();
|
||||
expect(await host.close?.()).toBeUndefined();
|
||||
expect(closeAttempts).toHaveLength(3);
|
||||
expect(closeAttempts[2]).toBe(closeAttempts[0]);
|
||||
await expectCloseReclaimsHandle(host, closeAttempts, release);
|
||||
} finally {
|
||||
release();
|
||||
await host.close?.();
|
||||
await cleanupHeldHandle(host, release);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -126,13 +158,9 @@ describe("ZCode fallback cleanup ownership", () => {
|
|||
await expect(readFile(client.configPath)).rejects.toMatchObject({
|
||||
code: "ENOENT",
|
||||
});
|
||||
release();
|
||||
expect(await host.close?.()).toBeUndefined();
|
||||
expect(closeAttempts).toHaveLength(3);
|
||||
expect(closeAttempts[2]).toBe(closeAttempts[0]);
|
||||
await expectCloseReclaimsHandle(host, closeAttempts, release);
|
||||
} finally {
|
||||
release();
|
||||
await host.close?.();
|
||||
await cleanupHeldHandle(host, release);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
|
@ -145,20 +173,9 @@ describe("setup client configuration cleanup ownership", () => {
|
|||
] as const)(
|
||||
"stops configuration and retains the %s read owner until host close",
|
||||
async (encoding, original) => {
|
||||
const home = await createTestTempDirectory("rea-setup-config-close-");
|
||||
const environment = {
|
||||
HOME: home,
|
||||
XDG_CONFIG_HOME: join(home, "xdg"),
|
||||
};
|
||||
const host = systemSetupHost(
|
||||
{ platform: "linux", homeDirectory: home } as DoctorHost,
|
||||
environment,
|
||||
const { host, client } = await preparedVsCodeSetupHost(
|
||||
"rea-setup-config-close-",
|
||||
);
|
||||
const client = (await host.supportedClients()).find(
|
||||
({ name }) => name === "vscode",
|
||||
);
|
||||
if (client === undefined) throw new Error("VS Code setup client missing");
|
||||
await mkdir(dirname(client.configPath), { recursive: true });
|
||||
await writeFile(client.configPath, original);
|
||||
|
||||
const { closeAttempts, release } = holdReadHandle(
|
||||
|
|
@ -210,32 +227,17 @@ describe("setup client configuration cleanup ownership", () => {
|
|||
expect(closeAttempts[0]).toBe(closeAttempts[1]);
|
||||
expect(await readFile(client.configPath)).toEqual(original);
|
||||
|
||||
release();
|
||||
expect(await host.close?.()).toBeUndefined();
|
||||
expect(closeAttempts).toHaveLength(3);
|
||||
expect(closeAttempts[2]).toBe(closeAttempts[0]);
|
||||
await expectCloseReclaimsHandle(host, closeAttempts, release);
|
||||
} finally {
|
||||
release();
|
||||
await host.close?.();
|
||||
await cleanupHeldHandle(host, release);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
it("waits for an admitted configuration read and rejects later admissions", async () => {
|
||||
const home = await createTestTempDirectory("rea-setup-config-inflight-");
|
||||
const environment = {
|
||||
HOME: home,
|
||||
XDG_CONFIG_HOME: join(home, "xdg"),
|
||||
};
|
||||
const host = systemSetupHost(
|
||||
{ platform: "linux", homeDirectory: home } as DoctorHost,
|
||||
environment,
|
||||
const { host, client } = await preparedVsCodeSetupHost(
|
||||
"rea-setup-config-inflight-",
|
||||
);
|
||||
const client = (await host.supportedClients()).find(
|
||||
({ name }) => name === "vscode",
|
||||
);
|
||||
if (client === undefined) throw new Error("VS Code setup client missing");
|
||||
await mkdir(dirname(client.configPath), { recursive: true });
|
||||
await writeFile(client.configPath, '{"servers": {}}\n');
|
||||
|
||||
let beginRead!: () => void;
|
||||
|
|
|
|||
Loading…
Reference in New Issue