Skip to content

Commit 42128b1

Browse files
naugturerights
authored andcommitted
test(ses): hermes test runner and multiple tests
1 parent cdfdd17 commit 42128b1

File tree

9 files changed

+358
-82
lines changed

9 files changed

+358
-82
lines changed

packages/ses/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@
8989
"prepare": "npm run clean && npm run build",
9090
"qt": "ava",
9191
"test": "tsd && ava",
92-
"test:hermes": "./scripts/hermes-test.sh",
92+
"test:hermes": "node ./scripts/hermes-test.js ./test/hermes/*",
9393
"test:xs": "xst dist/ses.umd.js test/_lockdown-safe.js && node scripts/generate-test-xs.js && xst tmp/test-xs.js && rm -rf tmp",
9494
"postpack": "git clean -fX \"*.d.ts*\" \"*.d.cts*\" \"*.d.mts*\" \"*.tsbuildinfo\""
9595
},
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
#!/usr/bin/env node
2+
/* global process */
3+
4+
import { existsSync, writeFileSync, mkdtempSync, readFileSync } from 'node:fs';
5+
import path from 'node:path';
6+
import { execSync } from 'node:child_process';
7+
import os from 'node:os';
8+
9+
// Utility function to determine OS-specific directory and create Hermes runner
10+
function createHermesRunner() {
11+
const platform = os.platform();
12+
let osDir;
13+
14+
switch (platform) {
15+
case 'linux':
16+
osDir = 'linux64-bin';
17+
break;
18+
case 'darwin':
19+
osDir = 'osx-bin';
20+
break;
21+
case 'win32':
22+
osDir = 'win64-bin';
23+
break;
24+
default:
25+
throw new Error(`Unsupported OS: ${platform}`);
26+
}
27+
28+
const hermesc = path.join(
29+
'..',
30+
'..',
31+
'node_modules',
32+
'hermes-engine-cli',
33+
osDir,
34+
'hermesc',
35+
);
36+
const hermes = path.join(
37+
'..',
38+
'..',
39+
'node_modules',
40+
'hermes-engine-cli',
41+
osDir,
42+
'hermes',
43+
);
44+
45+
// Add .exe extension for Windows
46+
const hermescPath = platform === 'win32' ? `${hermesc}.exe` : hermesc;
47+
const hermesPath = platform === 'win32' ? `${hermes}.exe` : hermes;
48+
49+
return {
50+
version: () => {
51+
execSync(`"${hermesPath}" --version`, {
52+
stdio: 'inherit',
53+
});
54+
},
55+
run: jsFile => {
56+
const hbcFile = jsFile.replace(/\.js$/, '.hbc');
57+
58+
// Compile
59+
try {
60+
execSync(
61+
`"${hermescPath}" "${jsFile}" -emit-binary -out "${hbcFile}"`,
62+
{
63+
stdio: 'pipe', // Capture output to detect compilation errors
64+
},
65+
);
66+
} catch (error) {
67+
throw new Error(`Compilation error: ${error.message}`);
68+
}
69+
70+
// Execute
71+
execSync(`"${hermesPath}" -b "${hbcFile}"`, {
72+
stdio: 'inherit',
73+
});
74+
},
75+
};
76+
}
77+
78+
const hermesPrefixSES = readFileSync(
79+
path.join(import.meta.dirname, '..', 'dist', 'ses-hermes.cjs'),
80+
'utf8',
81+
);
82+
const tempDir = mkdtempSync(path.join(os.tmpdir(), 'hermes-test-'));
83+
84+
const prepareTestFile = testFile => {
85+
const testName = path.basename(testFile);
86+
const distFile = path.join(tempDir, `${testName}`);
87+
88+
const testContent = readFileSync(testFile, 'utf8');
89+
// Combine the code in a way that line numbers are preserved and therefore helpful
90+
const combined = `${testContent}
91+
;;;;
92+
${hermesPrefixSES}
93+
;;;;
94+
95+
var TEST;
96+
function test(name, fn) {
97+
TEST={fn, name}
98+
}
99+
try {
100+
TEST.fn()
101+
} catch(e) {
102+
print(e.message)
103+
print(' ✗ '+TEST.name)
104+
throw e
105+
}
106+
print(' ✓ '+TEST.name)
107+
108+
;;;;
109+
`;
110+
writeFileSync(distFile, combined);
111+
return distFile;
112+
};
113+
114+
function run() {
115+
const testFiles = process.argv.slice(2);
116+
117+
if (testFiles.length === 0) {
118+
console.error('Usage: hermes-test.js <test-file1> <test-file2> ...');
119+
process.exit(2);
120+
}
121+
122+
// Validate that all test files exist
123+
testFiles.forEach(file => {
124+
if (!existsSync(file)) {
125+
console.error(`Error: Test file not found: ${file}`);
126+
process.exit(3);
127+
}
128+
});
129+
130+
const hermes = createHermesRunner();
131+
let passed = 0;
132+
let failed = 0;
133+
134+
hermes.version();
135+
136+
// Run each test in a separate clean environment
137+
testFiles.forEach(testFile => {
138+
console.log(`\n[RUN] ${testFile}`);
139+
140+
try {
141+
hermes.run(prepareTestFile(testFile));
142+
passed += 1;
143+
} catch (error) {
144+
failed += 1;
145+
}
146+
});
147+
148+
// Summary
149+
console.log(` -
150+
151+
${passed} tests passed`);
152+
153+
if (failed > 0) {
154+
console.log(` ${failed} tests failed`);
155+
process.exit(1);
156+
}
157+
}
158+
159+
run();

packages/ses/scripts/hermes-test.sh

Lines changed: 0 additions & 53 deletions
This file was deleted.

packages/ses/test/_hermes-smoke.js

Lines changed: 0 additions & 28 deletions
This file was deleted.

packages/ses/test/hermes/1smoke.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/* eslint-disable no-eval */
2+
/* global test */
3+
4+
test('smoke: lockdown works', () => {
5+
lockdown({ evalTaming: 'unsafe-eval' });
6+
7+
assert(typeof eval === 'function', 'eval is not a function');
8+
assert(
9+
eval.toString() === 'function eval() { [native code] }',
10+
'eval is not a native code function',
11+
);
12+
// @ts-expect-error expects string
13+
assert(eval(42) === 42, 'eval is not functional');
14+
assert(
15+
eval('42') === 42,
16+
'eval called with string argument is not functional',
17+
);
18+
assert(
19+
// eslint-disable-next-line no-new-func
20+
Function('return 42')() === 42,
21+
'Function constructor is not functional',
22+
);
23+
});
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/* global test */
2+
test('error taming unsafe-debug', () => {
3+
lockdown({
4+
evalTaming: 'unsafe-eval',
5+
errorTaming: 'unsafe-debug',
6+
overrideTaming: 'severe',
7+
reporting: 'none',
8+
});
9+
10+
try {
11+
throw Error('test');
12+
} catch (e) {
13+
assert(
14+
!e.stack.includes('at [object CallSite]'),
15+
`stack censorship broken:
16+
----
17+
${e.stack}
18+
----
19+
`,
20+
);
21+
}
22+
});
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// tip: use this to trip up platform detection
2+
// Error.captureStackTrace = null
3+
4+
/* global test */
5+
test('error taming unsafe', () => {
6+
lockdown({
7+
evalTaming: 'unsafe-eval',
8+
errorTaming: 'unsafe',
9+
overrideTaming: 'severe',
10+
reporting: 'none',
11+
});
12+
13+
try {
14+
throw Error('test');
15+
} catch (e) {
16+
assert(
17+
!e.stack.includes('at [object CallSite]'),
18+
`stack censorship broken:
19+
----
20+
${e.stack}
21+
----
22+
`,
23+
);
24+
}
25+
});

0 commit comments

Comments
 (0)