From 8b1549a264a914a1aec97d6945fc68ec8c5e1f64 Mon Sep 17 00:00:00 2001 From: The one -Niu <912906590@qq.com> Date: Tue, 13 Oct 2026 23:47:55 +0800 Subject: [PATCH] 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> --- src/domain/reconstructionCoverage.fixture.ts | 10 ++ src/domain/reconstructionCoverage.test.ts | 92 ++++--------- src/native/NativeUiObservation.test.ts | 126 +++++------------- tests/boundary/cli/captureCleanup.test.ts | 93 +++++-------- .../boundary/filesystem/installScript.test.ts | 37 +++-- .../setupClientConfigCleanupOwnership.test.ts | 90 +++++++------ 6 files changed, 167 insertions(+), 281 deletions(-) diff --git a/src/domain/reconstructionCoverage.fixture.ts b/src/domain/reconstructionCoverage.fixture.ts index 0a51546b6..2d1e37a19 100644 --- a/src/domain/reconstructionCoverage.fixture.ts +++ b/src/domain/reconstructionCoverage.fixture.ts @@ -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 }; +}; diff --git a/src/domain/reconstructionCoverage.test.ts b/src/domain/reconstructionCoverage.test.ts index ac7552571..628ad67c1 100644 --- a/src/domain/reconstructionCoverage.test.ts +++ b/src/domain/reconstructionCoverage.test.ts @@ -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, diff --git a/src/native/NativeUiObservation.test.ts b/src/native/NativeUiObservation.test.ts index 527afd8db..0d02693d8 100644 --- a/src/native/NativeUiObservation.test.ts +++ b/src/native/NativeUiObservation.test.ts @@ -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) => + 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); }); diff --git a/tests/boundary/cli/captureCleanup.test.ts b/tests/boundary/cli/captureCleanup.test.ts index 6e5882cd4..40013d6a1 100644 --- a/tests/boundary/cli/captureCleanup.test.ts +++ b/tests/boundary/cli/captureCleanup.test.ts @@ -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 => { + 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"); }); diff --git a/tests/boundary/filesystem/installScript.test.ts b/tests/boundary/filesystem/installScript.test.ts index 0f2e14730..d7e7f78a3 100644 --- a/tests/boundary/filesystem/installScript.test.ts +++ b/tests/boundary/filesystem/installScript.test.ts @@ -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 => { await chmod(path, 0o755); }; +/** Fixture-owned installer environment shared by the exec, pipe and PTY runs. */ +const installerEnvironment = ( + fixture: InstallerFixture, +): Record => ({ + 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"], diff --git a/tests/boundary/filesystem/setupClientConfigCleanupOwnership.test.ts b/tests/boundary/filesystem/setupClientConfigCleanupOwnership.test.ts index ab2b5e5a7..bf7de8819 100644 --- a/tests/boundary/filesystem/setupClientConfigCleanupOwnership.test.ts +++ b/tests/boundary/filesystem/setupClientConfigCleanupOwnership.test.ts @@ -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 }, + 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 }, + 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;