Shim test: run from a staged copy and prove the download happened

The three fail-closed cases cleared IMPECCABLE_BIN and pointed
IMPECCABLE_HOME at a temp dir, but locate() prefers an installed
@impeccable/cli-<os>-<arch> before the cache or a download. Those
platform packages ship with every engine release and are a merge
prerequisite, so as soon as one is installed under the repo the cases
would resolve it and go green without fetching anything. Confirmed by
hand: with a platform package staged in node_modules, running the shim
against an unreachable download base still exits 0 from the package.

The shim now runs from a throwaway copy at <tmp>/cli/bin/cli.js beside a
copy of the repo's package.json, with no node_modules on the lookup path
above it, so require.resolve of the platform package fails the way it
does on a machine without the optional dependency. Production code is
unchanged; there is no test-only branch in the shim.

The fixture server also records every request now, and each download case
asserts the asset and sidecar URLs were actually requested, so a future
lookup shortcut fails loudly instead of passing on an untested path. A
sixth case installs a fake platform package next to the staged shim and
asserts the shim prefers it with the server untouched, which pins the
precedence the other cases depend on being absent.

Co-Authored-By: Claude Code <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vau2X53xGTjjTCXWMVBoNY
This commit is contained in:
Paul Bakaus
2026-09-03 20:22:36 -07:00
co-authored by Claude Code
parent f32d374ac7
commit 3a857af9ea
+83 -21
View File
@@ -8,8 +8,18 @@
* be fetched, is empty, or disagrees with the payload refuses the download and
* leaves nothing in the cache dir.
*
* Every case runs the real shim against a throwaway HTTP server, with
* IMPECCABLE_HOME pointed at a temp dir so the user's cache is never touched.
* Two things keep these cases honest about which lookup arm they exercise.
* First, the shim runs from a staged copy (`<tmp>/cli/bin/cli.js` beside a
* copy of the repo's package.json) with no node_modules anywhere under it, so
* `require.resolve('@impeccable/cli-<os>-<arch>')` fails the way it does on a
* machine without the optional dependency. Those platform packages are a
* release prerequisite, so a test run from the repo would otherwise start
* resolving them and pass without ever reaching the download. Second, the
* fixture server records every request, and each download case asserts the
* asset was actually fetched, so a future lookup shortcut fails loudly instead
* of going green on an untested path. The last case installs a fake platform
* package next to the staged shim and pins the precedence the other cases
* depend on being absent.
*/
import assert from 'node:assert/strict';
import { spawn } from 'node:child_process';
@@ -19,15 +29,17 @@ import http from 'node:http';
import os from 'node:os';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { after, before, describe, it } from 'node:test';
import { after, before, beforeEach, describe, it } from 'node:test';
const REPO = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
const SHIM = path.join(REPO, 'cli', 'bin', 'cli.js');
const VERSION = JSON.parse(fs.readFileSync(path.join(REPO, 'package.json'), 'utf8'))
const PKG_PATH = path.join(REPO, 'package.json');
const VERSION = JSON.parse(fs.readFileSync(PKG_PATH, 'utf8'))
.optionalDependencies['@impeccable/cli-darwin-arm64'];
const TARGET = `${{ darwin: 'darwin', linux: 'linux', win32: 'windows' }[process.platform] || process.platform}`
+ `-${{ arm64: 'arm64', x64: 'x64' }[process.arch] || process.arch}`;
const PLATFORM_PKG = `@impeccable/cli-${TARGET}`;
const ASSET = `impeccable-${TARGET}${process.platform === 'win32' ? '.exe' : ''}`;
const ASSET_PATH = `/engine-v${VERSION}/${ASSET}`;
// A stand-in engine binary: a script that prints its argv so a successful
// download is observable end to end.
@@ -36,12 +48,15 @@ const DIGEST = createHash('sha256').update(PAYLOAD).digest('hex');
/** What the server answers for `<asset>.sha256` on the next request. */
let sidecar = { status: 200, body: `${DIGEST} ${ASSET}\n` };
/** Every path the server was asked for since the last test started. */
let requests = [];
let server;
let base;
before(async () => {
server = http.createServer((req, res) => {
if (req.url.endsWith('.sha256')) {
requests.push(req.url);
if (req.url === `${ASSET_PATH}.sha256`) {
if (sidecar.status !== 200) {
res.writeHead(sidecar.status);
res.end('');
@@ -51,7 +66,7 @@ before(async () => {
res.end(sidecar.body);
return;
}
if (req.url.endsWith(ASSET)) {
if (req.url === ASSET_PATH) {
res.writeHead(200, { 'content-type': 'application/octet-stream' });
res.end(PAYLOAD);
return;
@@ -65,14 +80,29 @@ before(async () => {
after(() => new Promise((resolve) => server.close(resolve)));
beforeEach(() => { requests = []; });
/**
* Run the shim and collect its output. Async on purpose: the fixture server
* lives in this process, so a synchronous spawn would block the event loop
* and the child's fetch would never be answered.
* A throwaway copy of the shim at `<tmp>/cli/bin/cli.js`, with the repo's
* package.json where the shim reads it from (`../../package.json`) and no
* node_modules on the lookup path above it.
*/
function run(args, env) {
function stageShim() {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'impeccable-shim-'));
fs.mkdirSync(path.join(dir, 'cli', 'bin'), { recursive: true });
fs.copyFileSync(PKG_PATH, path.join(dir, 'package.json'));
fs.copyFileSync(path.join(REPO, 'cli', 'bin', 'cli.js'), path.join(dir, 'cli', 'bin', 'cli.js'));
return { dir, shim: path.join(dir, 'cli', 'bin', 'cli.js') };
}
/**
* Run a staged shim and collect its output. Async on purpose: the fixture
* server lives in this process, so a synchronous spawn would block the event
* loop and the child's fetch would never be answered.
*/
function run(shim, args, env) {
return new Promise((resolve) => {
const child = spawn(process.execPath, [SHIM, ...args], { env });
const child = spawn(process.execPath, [shim, ...args], { env });
let stdout = '';
let stderr = '';
child.stdout.on('data', (d) => { stdout += d; });
@@ -81,12 +111,12 @@ function run(args, env) {
});
}
/** Run the shim with a fresh cache dir. Returns the result plus that dir. */
/** Stage a shim and run it with its own cache dir. */
async function runShim(args = ['engine-probe']) {
const home = fs.mkdtempSync(path.join(os.tmpdir(), 'impeccable-shim-'));
const env = { ...process.env, IMPECCABLE_HOME: home, IMPECCABLE_DOWNLOAD_BASE: base };
const { dir, shim } = stageShim();
const env = { ...process.env, IMPECCABLE_HOME: dir, IMPECCABLE_DOWNLOAD_BASE: base };
delete env.IMPECCABLE_BIN;
return { ...(await run(args, env)), home };
return { ...(await run(shim, args, env)), home: dir };
}
/** Everything under the cache dir, so a refusal can be shown to leave no trace. */
@@ -111,6 +141,7 @@ describe('npm shim download verification', { skip: process.platform === 'win32'
const res = await runShim(['hello']);
assert.equal(res.status, 0, res.stderr);
assert.match(res.stdout, /fake-engine hello/);
assert.deepEqual(requests, [ASSET_PATH, `${ASSET_PATH}.sha256`]);
assert.deepEqual(cacheEntries(res.home), [path.join(VERSION, 'impeccable')]);
});
@@ -120,6 +151,7 @@ describe('npm shim download verification', { skip: process.platform === 'win32'
assert.equal(res.status, 127);
assert.match(res.stderr, /sidecar unavailable or empty/);
assert.match(res.stderr, /refusing the unverified download/);
assert.deepEqual(requests, [ASSET_PATH, `${ASSET_PATH}.sha256`]);
assert.deepEqual(cacheEntries(res.home), []);
});
@@ -129,6 +161,7 @@ describe('npm shim download verification', { skip: process.platform === 'win32'
assert.equal(res.status, 127);
assert.match(res.stderr, /sidecar unavailable or empty/);
assert.match(res.stderr, /refusing the unverified download/);
assert.deepEqual(requests, [ASSET_PATH, `${ASSET_PATH}.sha256`]);
assert.deepEqual(cacheEntries(res.home), []);
});
@@ -137,19 +170,48 @@ describe('npm shim download verification', { skip: process.platform === 'win32'
const res = await runShim();
assert.equal(res.status, 127);
assert.match(res.stderr, /checksum mismatch downloading/);
assert.deepEqual(requests, [ASSET_PATH, `${ASSET_PATH}.sha256`]);
assert.deepEqual(cacheEntries(res.home), []);
});
it('prefers IMPECCABLE_BIN and never downloads', async () => {
sidecar = { status: 404, body: '' };
const home = fs.mkdtempSync(path.join(os.tmpdir(), 'impeccable-shim-'));
const bin = path.join(home, 'preinstalled');
const { dir, shim } = stageShim();
const bin = path.join(dir, 'preinstalled');
fs.writeFileSync(bin, '#!/bin/sh\necho "preinstalled $*"\n', { mode: 0o755 });
const res = await run(['hi'], {
...process.env, IMPECCABLE_HOME: home, IMPECCABLE_DOWNLOAD_BASE: base, IMPECCABLE_BIN: bin,
const res = await run(shim, ['hi'], {
...process.env, IMPECCABLE_HOME: dir, IMPECCABLE_DOWNLOAD_BASE: base, IMPECCABLE_BIN: bin,
});
assert.equal(res.status, 0, res.stderr);
assert.match(res.stdout, /preinstalled hi/);
assert.deepEqual(cacheEntries(home), []);
assert.deepEqual(requests, []);
assert.deepEqual(cacheEntries(dir), []);
});
// The precedence the four cases above depend on being absent: with the
// optional dependency installed, the shim never reaches the cache or the
// download. Those packages ship with every engine release, so a shim run
// from a tree that has them takes this arm instead.
it('prefers an installed platform package and never downloads', async () => {
sidecar = { status: 404, body: '' };
const { dir, shim } = stageShim();
const pkgDir = path.join(dir, 'node_modules', PLATFORM_PKG);
fs.mkdirSync(path.join(pkgDir, 'bin'), { recursive: true });
fs.writeFileSync(
path.join(pkgDir, 'package.json'),
`${JSON.stringify({ name: PLATFORM_PKG, version: VERSION }, null, 2)}\n`,
);
fs.writeFileSync(
path.join(pkgDir, 'bin', 'impeccable'),
'#!/bin/sh\necho "from-platform-package $*"\n',
{ mode: 0o755 },
);
const env = { ...process.env, IMPECCABLE_HOME: dir, IMPECCABLE_DOWNLOAD_BASE: base };
delete env.IMPECCABLE_BIN;
const res = await run(shim, ['hi'], env);
assert.equal(res.status, 0, res.stderr);
assert.match(res.stdout, /from-platform-package hi/);
assert.deepEqual(requests, []);
assert.deepEqual(cacheEntries(dir), []);
});
});