Files
Firelink/scripts/engine-workspace.node-test.js
T
NimBold f65d98bbd0 fix(ci): resolve Windows cross-drive engine workspace and strip verbatim paths
- allocate engine workspace on the repository drive when os.tmpdir() is cross-drive on Windows
- resolve RUNNER_TEMP on GitHub Actions to align workspace drive with checkout
- strip Win32 \\?\ verbatim prefixes to ensure Tauri resource normalizer compatibility
2026-09-05 10:28:31 +03:30

113 lines
3.9 KiB
JavaScript

import assert from 'node:assert/strict';
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import test from 'node:test';
import {
assertSafeTarget,
assertSafeOutputRoot,
createEngineWorkspace,
engineResourceConfig,
removeEngineWorkspace,
resolveOutputRoot,
resolveTargetTriple,
resolveWorkspaceTempBase,
stripVerbatimPrefix,
} from './engine-workspace.js';
test('target resolution accepts explicit and inline target arguments', () => {
assert.equal(
resolveTargetTriple(['--target', 'x86_64-unknown-linux-gnu'], {}, 'darwin', 'arm64'),
'x86_64-unknown-linux-gnu',
);
assert.equal(
resolveTargetTriple(['--target=x86_64-pc-windows-msvc'], {}, 'darwin', 'arm64'),
'x86_64-pc-windows-msvc',
);
});
test('target validation rejects path traversal before filesystem use', () => {
assert.throws(() => assertSafeTarget('../outside'), /Invalid target triple/);
assert.throws(
() => resolveTargetTriple(['--target', 'x86_64/../../outside'], {}, 'darwin', 'arm64'),
/Invalid target triple/,
);
});
test('engine workspaces are unique and produce an absolute Tauri resource mapping', async () => {
const first = createEngineWorkspace('aarch64-apple-darwin');
const second = createEngineWorkspace('aarch64-apple-darwin');
try {
assert.notEqual(first.workspace, second.workspace);
assert.equal(fs.statSync(first.outputRoot).isDirectory(), true);
const config = JSON.parse(engineResourceConfig(first.outputRoot));
assert.equal(
config.bundle.resources[`${path.resolve(first.outputRoot)}${path.sep}`],
'engine-dist/',
);
} finally {
await removeEngineWorkspace(first.workspace);
await removeEngineWorkspace(second.workspace);
}
});
test('staging requires an explicit private output workspace', () => {
assert.throws(() => resolveOutputRoot([], {}), /No engine output workspace/);
assert.equal(
resolveOutputRoot(['--output-root', '/tmp/firelink-engine-run'], {}).endsWith(
path.join('firelink-engine-run'),
),
true,
);
});
test('shared repository output roots and descendants are rejected', () => {
const repoRoot = path.resolve('/repo');
assert.throws(
() => assertSafeOutputRoot('/repo/src-tauri/engine-dist/target', [
repoRoot,
path.join(repoRoot, 'src-tauri'),
path.join(repoRoot, 'src-tauri', 'engine-dist'),
]),
/repository-shared engine workspace/,
);
});
test('output roots are checked after resolving symlinked parents', () => {
const temporaryRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'firelink-engine-workspace-test-'));
const sharedRoot = path.join(temporaryRoot, 'shared');
const linkedRoot = path.join(temporaryRoot, 'linked');
try {
fs.mkdirSync(path.join(sharedRoot, 'src-tauri', 'engine-dist'), { recursive: true });
fs.symlinkSync(sharedRoot, linkedRoot, 'dir');
assert.throws(
() => assertSafeOutputRoot(path.join(linkedRoot, 'src-tauri', 'engine-dist', 'target'), [
sharedRoot,
path.join(sharedRoot, 'src-tauri'),
path.join(sharedRoot, 'src-tauri', 'engine-dist'),
]),
/repository-shared engine workspace/,
);
} finally {
fs.rmSync(temporaryRoot, { recursive: true, force: true });
}
});
test('stripVerbatimPrefix removes Win32 verbatim namespaces', () => {
assert.equal(stripVerbatimPrefix('\\\\?\\D:\\a\\_temp'), 'D:\\a\\_temp');
assert.equal(stripVerbatimPrefix('D:\\a\\_temp'), 'D:\\a\\_temp');
assert.equal(stripVerbatimPrefix('/tmp/firelink'), '/tmp/firelink');
});
test('resolveWorkspaceTempBase honors FIRELINK_ENGINE_WORKSPACE_BASE override', () => {
const custom = path.resolve('/custom/engine/base');
const prev = process.env.FIRELINK_ENGINE_WORKSPACE_BASE;
process.env.FIRELINK_ENGINE_WORKSPACE_BASE = custom;
try {
assert.equal(resolveWorkspaceTempBase(), custom);
} finally {
if (prev === undefined) delete process.env.FIRELINK_ENGINE_WORKSPACE_BASE;
else process.env.FIRELINK_ENGINE_WORKSPACE_BASE = prev;
}
});