|
1 |
| -import fs from 'fs/promises'; |
2 |
| -import { spawn } from 'child_process'; |
3 |
| -import { tmpdir } from 'os'; |
| 1 | +import fs from "fs/promises"; |
| 2 | +import { spawn } from "child_process"; |
| 3 | +import { tmpdir } from "os"; |
4 | 4 |
|
5 | 5 | const spawnCapture = async (cmd: string, args: string[]) => {
|
6 |
| - const child = spawn(cmd, args); |
| 6 | + const child = spawn(cmd, args); |
7 | 7 |
|
8 |
| - let error; |
9 |
| - child.on('error', (err) => { error = err }); |
| 8 | + let stdout = ""; |
| 9 | + let stderr = ""; |
10 | 10 |
|
11 |
| - let status = -1; |
12 |
| - let signal = undefined; |
13 |
| - child.on('exit', (code, sig) => { |
14 |
| - status = code ?? -1; |
15 |
| - signal = sig; // 'SIGILL' when there is a panic. |
16 |
| - }); |
| 11 | + child.stdout.on("data", (data) => { |
| 12 | + stdout += data.toString(); |
| 13 | + }); |
17 | 14 |
|
18 |
| - let stdout = ''; |
19 |
| - child.stdout.on('data', (data) => { |
20 |
| - stdout += data.toString(); |
21 |
| - }); |
| 15 | + child.stderr.on("data", (data) => { |
| 16 | + stderr += data.toString(); |
| 17 | + }); |
22 | 18 |
|
23 |
| - let stderr = ''; |
24 |
| - child.stderr.on('data', (data) => { |
25 |
| - stderr += data.toString(); |
| 19 | + const [status, signal] = await new Promise< |
| 20 | + [number | null, NodeJS.Signals | null] |
| 21 | + >((resolve) => { |
| 22 | + child.on("close", (code, sig) => { |
| 23 | + resolve([code ?? -1, sig]); |
26 | 24 | });
|
| 25 | + }); |
27 | 26 |
|
28 |
| - await new Promise((resolve) => child.on('exit', resolve)); |
29 |
| - |
30 |
| - return { |
31 |
| - stdout: stdout ?? '', |
32 |
| - stderr: stderr ?? '', |
33 |
| - status, |
34 |
| - signal, |
35 |
| - error |
36 |
| - } |
37 |
| -} |
38 |
| - |
39 |
| -const compile = async (filename: string, outputFilename: string) => { |
40 |
| - return await spawnCapture( |
41 |
| - process.argv0, |
42 |
| - ['compile', filename, outputFilename]); |
43 |
| -} |
44 |
| - |
45 |
| -const run = async (filename: string) => { |
46 |
| - return await spawnCapture( |
47 |
| - process.argv0, |
48 |
| - [filename]); |
49 |
| -} |
50 |
| - |
51 |
| -describe('llrt compile', async () => { |
52 |
| - const tmpDir = await fs.mkdtemp(`${tmpdir}/llrt-test-compile`); |
53 |
| - const cases = [{ |
54 |
| - name: 'empty', filename: 'fixtures/empty.js', expected: { stdout: '', stderr: '', status: 0 }, |
55 |
| - }, { |
56 |
| - name: 'console.log', filename: 'fixtures/hello.js', expected: { stdout: 'hello world!\n', status: 0 }, |
57 |
| - }, { |
58 |
| - name: 'throws', filename: 'fixtures/throw.js', expected: { stdout: '', stderr: 'Error: 42\n', status: 1 }, |
59 |
| - }]; |
60 |
| - |
61 |
| - cases.forEach(async c => { |
62 |
| - it(`can compile and run ${c.name}`, async () => { |
63 |
| - const tmpOutput = `${tmpDir}/${c.name}.lrt`; |
64 |
| - // compile. |
65 |
| - { |
66 |
| - const child = await compile(c.filename, tmpOutput); |
67 |
| - if (c.expected.compileError && typeof c.expected.stderr !== 'undefined') { |
68 |
| - if (c.expected.stderr instanceof RegExp) { |
69 |
| - assert.match(child.stderr, c.expected.stderr) |
70 |
| - } else { |
71 |
| - assert.strictEqual(child.stderr, c.expected.stderr) |
72 |
| - }; |
73 |
| - } |
74 |
| - if (c.expected.signal) { |
75 |
| - assert.strictEqual(child.signal, c.expected.signal); |
76 |
| - } |
77 |
| - if (c.expected.compileError) { |
78 |
| - return; |
79 |
| - } |
80 |
| - } |
81 |
| - |
82 |
| - // run. |
83 |
| - { |
84 |
| - const child = await run(tmpOutput); |
85 |
| - if (typeof c.expected.stdout !== 'undefined') { |
86 |
| - assert.strictEqual(child.stdout, c.expected.stdout); |
87 |
| - } |
88 |
| - |
89 |
| - if (typeof c.expected.stderr !== 'undefined') { |
90 |
| - if (c.expected.stderr instanceof RegExp) { |
91 |
| - assert.match(child.stderr, c.expected.stderr) |
92 |
| - } else { |
93 |
| - assert.strictEqual(child.stderr, c.expected.stderr) |
94 |
| - }; |
95 |
| - } |
96 |
| - |
97 |
| - if (typeof c.expected.status !== 'undefined') { |
98 |
| - assert.strictEqual(child.status, c.expected.status); |
99 |
| - } |
100 |
| - } |
101 |
| - }) |
102 |
| - }); |
| 27 | + return { stdout, stderr, status, signal }; |
| 28 | +}; |
| 29 | + |
| 30 | +const compile = async (filename: string, outputFilename: string) => |
| 31 | + await spawnCapture(process.argv0, ["compile", filename, outputFilename]); |
| 32 | + |
| 33 | +const run = async (filename: string) => |
| 34 | + await spawnCapture(process.argv0, [filename]); |
| 35 | + |
| 36 | +describe("llrt compile", async () => { |
| 37 | + const tmpDir = await fs.mkdtemp(`${tmpdir()}/llrt-test-compile`); |
| 38 | + |
| 39 | + it("can compile and run empty", async () => { |
| 40 | + const tmpOutput = `${tmpDir}/empty.lrt`; |
| 41 | + |
| 42 | + const compileResult = await compile("fixtures/empty.js", tmpOutput); |
| 43 | + |
| 44 | + assert.strictEqual(compileResult.stderr, ""); |
| 45 | + assert.strictEqual(compileResult.signal, undefined); |
| 46 | + |
| 47 | + const runResult = await run(tmpOutput); |
| 48 | + |
| 49 | + assert.strictEqual(runResult.stdout, ""); |
| 50 | + assert.strictEqual(runResult.stderr, ""); |
| 51 | + assert.strictEqual(runResult.status, 0); |
| 52 | + }); |
| 53 | + |
| 54 | + it("can compile and run console.log", async () => { |
| 55 | + const tmpOutput = `${tmpDir}/console.log.lrt`; |
| 56 | + |
| 57 | + const compileResult = await compile("fixtures/hello.js", tmpOutput); |
| 58 | + |
| 59 | + assert.strictEqual(compileResult.stderr, ""); |
| 60 | + assert.strictEqual(compileResult.signal, undefined); |
| 61 | + |
| 62 | + const runResult = await run(tmpOutput); |
| 63 | + |
| 64 | + assert.strictEqual(runResult.stdout, "hello world!\n"); |
| 65 | + assert.strictEqual(runResult.stderr, ""); |
| 66 | + assert.strictEqual(runResult.status, 0); |
| 67 | + }); |
| 68 | + |
| 69 | + it.only("can compile and run throws", async () => { |
| 70 | + const tmpOutput = `${tmpDir}/throws.lrt`; |
| 71 | + |
| 72 | + const compileResult = await compile("fixtures/throw.js", tmpOutput); |
| 73 | + |
| 74 | + assert.strictEqual(compileResult.stderr, ""); |
| 75 | + assert.strictEqual(compileResult.signal, undefined); |
| 76 | + |
| 77 | + const runResult = await run(tmpOutput); |
| 78 | + |
| 79 | + assert.strictEqual(runResult.stdout, ""); |
| 80 | + assert.strictEqual(runResult.stderr, "Error: 42\n"); |
| 81 | + assert.strictEqual(runResult.status, 1); |
| 82 | + }); |
103 | 83 |
|
104 |
| - afterAll(async () => { |
105 |
| - await fs.rmdir(tmpDir, { recursive: true }); |
106 |
| - }) |
| 84 | + afterAll(async () => { |
| 85 | + await fs.rmdir(tmpDir, { recursive: true }); |
| 86 | + }); |
107 | 87 | });
|
0 commit comments