|
1 | 1 | 'use strict';
|
2 |
| -const { |
3 |
| - ArrayFrom, |
4 |
| - ArrayPrototypeFilter, |
5 |
| - ArrayPrototypeIncludes, |
6 |
| - ArrayPrototypeJoin, |
7 |
| - ArrayPrototypePush, |
8 |
| - ArrayPrototypeSlice, |
9 |
| - ArrayPrototypeSort, |
10 |
| - SafePromiseAll, |
11 |
| - SafeSet, |
12 |
| -} = primordials; |
13 | 2 | const {
|
14 | 3 | prepareMainThreadExecution,
|
15 | 4 | markBootstrapComplete
|
16 | 5 | } = require('internal/process/pre_execution');
|
17 |
| -const { spawn } = require('child_process'); |
18 |
| -const { readdirSync, statSync } = require('fs'); |
19 |
| -const console = require('internal/console/global'); |
20 |
| -const { |
21 |
| - codes: { |
22 |
| - ERR_TEST_FAILURE, |
23 |
| - }, |
24 |
| -} = require('internal/errors'); |
25 |
| -const { test } = require('internal/test_runner/harness'); |
26 |
| -const { kSubtestsFailed } = require('internal/test_runner/test'); |
27 |
| -const { |
28 |
| - isSupportedFileType, |
29 |
| - doesPathMatchFilter, |
30 |
| -} = require('internal/test_runner/utils'); |
31 |
| -const { basename, join, resolve } = require('path'); |
32 |
| -const { once } = require('events'); |
33 |
| -const kFilterArgs = ['--test']; |
| 6 | +const { run } = require('internal/test_runner/runner'); |
34 | 7 |
|
35 | 8 | prepareMainThreadExecution(false);
|
36 | 9 | markBootstrapComplete();
|
37 | 10 |
|
38 |
| -// TODO(cjihrig): Replace this with recursive readdir once it lands. |
39 |
| -function processPath(path, testFiles, options) { |
40 |
| - const stats = statSync(path); |
41 |
| - |
42 |
| - if (stats.isFile()) { |
43 |
| - if (options.userSupplied || |
44 |
| - (options.underTestDir && isSupportedFileType(path)) || |
45 |
| - doesPathMatchFilter(path)) { |
46 |
| - testFiles.add(path); |
47 |
| - } |
48 |
| - } else if (stats.isDirectory()) { |
49 |
| - const name = basename(path); |
50 |
| - |
51 |
| - if (!options.userSupplied && name === 'node_modules') { |
52 |
| - return; |
53 |
| - } |
54 |
| - |
55 |
| - // 'test' directories get special treatment. Recursively add all .js, |
56 |
| - // .cjs, and .mjs files in the 'test' directory. |
57 |
| - const isTestDir = name === 'test'; |
58 |
| - const { underTestDir } = options; |
59 |
| - const entries = readdirSync(path); |
60 |
| - |
61 |
| - if (isTestDir) { |
62 |
| - options.underTestDir = true; |
63 |
| - } |
64 |
| - |
65 |
| - options.userSupplied = false; |
66 |
| - |
67 |
| - for (let i = 0; i < entries.length; i++) { |
68 |
| - processPath(join(path, entries[i]), testFiles, options); |
69 |
| - } |
70 |
| - |
71 |
| - options.underTestDir = underTestDir; |
72 |
| - } |
73 |
| -} |
74 |
| - |
75 |
| -function createTestFileList() { |
76 |
| - const cwd = process.cwd(); |
77 |
| - const hasUserSuppliedPaths = process.argv.length > 1; |
78 |
| - const testPaths = hasUserSuppliedPaths ? |
79 |
| - ArrayPrototypeSlice(process.argv, 1) : [cwd]; |
80 |
| - const testFiles = new SafeSet(); |
81 |
| - |
82 |
| - try { |
83 |
| - for (let i = 0; i < testPaths.length; i++) { |
84 |
| - const absolutePath = resolve(testPaths[i]); |
85 |
| - |
86 |
| - processPath(absolutePath, testFiles, { userSupplied: true }); |
87 |
| - } |
88 |
| - } catch (err) { |
89 |
| - if (err?.code === 'ENOENT') { |
90 |
| - console.error(`Could not find '${err.path}'`); |
91 |
| - process.exit(1); |
92 |
| - } |
93 |
| - |
94 |
| - throw err; |
95 |
| - } |
96 |
| - |
97 |
| - return ArrayPrototypeSort(ArrayFrom(testFiles)); |
98 |
| -} |
99 |
| - |
100 |
| -function filterExecArgv(arg) { |
101 |
| - return !ArrayPrototypeIncludes(kFilterArgs, arg); |
102 |
| -} |
103 |
| - |
104 |
| -function runTestFile(path) { |
105 |
| - return test(path, async (t) => { |
106 |
| - const args = ArrayPrototypeFilter(process.execArgv, filterExecArgv); |
107 |
| - ArrayPrototypePush(args, path); |
108 |
| - |
109 |
| - const child = spawn(process.execPath, args, { signal: t.signal, encoding: 'utf8' }); |
110 |
| - // TODO(cjihrig): Implement a TAP parser to read the child's stdout |
111 |
| - // instead of just displaying it all if the child fails. |
112 |
| - let err; |
113 |
| - |
114 |
| - child.on('error', (error) => { |
115 |
| - err = error; |
116 |
| - }); |
117 |
| - |
118 |
| - const { 0: { 0: code, 1: signal }, 1: stdout, 2: stderr } = await SafePromiseAll([ |
119 |
| - once(child, 'exit', { signal: t.signal }), |
120 |
| - child.stdout.toArray({ signal: t.signal }), |
121 |
| - child.stderr.toArray({ signal: t.signal }), |
122 |
| - ]); |
123 |
| - |
124 |
| - if (code !== 0 || signal !== null) { |
125 |
| - if (!err) { |
126 |
| - err = new ERR_TEST_FAILURE('test failed', kSubtestsFailed); |
127 |
| - err.exitCode = code; |
128 |
| - err.signal = signal; |
129 |
| - err.stdout = ArrayPrototypeJoin(stdout, ''); |
130 |
| - err.stderr = ArrayPrototypeJoin(stderr, ''); |
131 |
| - // The stack will not be useful since the failures came from tests |
132 |
| - // in a child process. |
133 |
| - err.stack = undefined; |
134 |
| - } |
135 |
| - |
136 |
| - throw err; |
137 |
| - } |
138 |
| - }); |
139 |
| -} |
140 |
| - |
141 |
| -(async function main() { |
142 |
| - const testFiles = createTestFileList(); |
143 |
| - |
144 |
| - for (let i = 0; i < testFiles.length; i++) { |
145 |
| - runTestFile(testFiles[i]); |
146 |
| - } |
147 |
| -})(); |
| 11 | +const tapStream = run(); |
| 12 | +tapStream.pipe(process.stdout); |
| 13 | +tapStream.once('test:fail', () => { |
| 14 | + process.exitCode = 1; |
| 15 | +}); |
0 commit comments