|
1 |
| -// https://github.com/nodejs/node/blob/2fd4c013c221653da2a7921d08fe1aa96aaba504/lib/internal/main/test_runner.js |
| 1 | +// https://github.com/nodejs/node/blob/59527de13d39327eb3dfa8dedc92241eb40066d5/lib/internal/main/test_runner.js |
2 | 2 | 'use strict'
|
3 |
| -const { |
4 |
| - ArrayFrom, |
5 |
| - ArrayPrototypeFilter, |
6 |
| - ArrayPrototypeIncludes, |
7 |
| - ArrayPrototypeJoin, |
8 |
| - ArrayPrototypePush, |
9 |
| - ArrayPrototypeSlice, |
10 |
| - ArrayPrototypeSort, |
11 |
| - SafePromiseAll, |
12 |
| - SafeSet |
13 |
| -} = require('#internal/per_context/primordials') |
14 | 3 | const {
|
15 | 4 | prepareMainThreadExecution
|
16 |
| -} = require('#internal/bootstrap/pre_execution') |
17 |
| -const { spawn } = require('child_process') |
18 |
| -const { readdirSync, statSync } = require('fs') |
19 |
| -const { |
20 |
| - codes: { |
21 |
| - ERR_TEST_FAILURE |
22 |
| - } |
23 |
| -} = require('#internal/errors') |
24 |
| -const { toArray } = require('#internal/streams/operators').promiseReturningOperators |
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'] |
| 5 | +} = require('#internal/process/pre_execution') |
| 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) |
80 |
| - : [cwd] |
81 |
| - const testFiles = new SafeSet() |
82 |
| - |
83 |
| - try { |
84 |
| - for (let i = 0; i < testPaths.length; i++) { |
85 |
| - const absolutePath = resolve(testPaths[i]) |
86 |
| - |
87 |
| - processPath(absolutePath, testFiles, { userSupplied: true }) |
88 |
| - } |
89 |
| - } catch (err) { |
90 |
| - if (err?.code === 'ENOENT') { |
91 |
| - console.error(`Could not find '${err.path}'`) |
92 |
| - process.exit(1) |
93 |
| - } |
94 |
| - |
95 |
| - throw err |
96 |
| - } |
97 |
| - |
98 |
| - return ArrayPrototypeSort(ArrayFrom(testFiles)) |
99 |
| -} |
100 |
| - |
101 |
| -function filterExecArgv (arg) { |
102 |
| - return !ArrayPrototypeIncludes(kFilterArgs, arg) |
103 |
| -} |
104 |
| - |
105 |
| -function runTestFile (path) { |
106 |
| - return test(path, async (t) => { |
107 |
| - const args = ArrayPrototypeFilter(process.execArgv, filterExecArgv) |
108 |
| - ArrayPrototypePush(args, path) |
109 |
| - |
110 |
| - const child = spawn(process.execPath, args, { signal: t.signal, encoding: 'utf8' }) |
111 |
| - // TODO(cjihrig): Implement a TAP parser to read the child's stdout |
112 |
| - // instead of just displaying it all if the child fails. |
113 |
| - let err |
114 |
| - |
115 |
| - child.on('error', (error) => { |
116 |
| - err = error |
117 |
| - }) |
118 |
| - |
119 |
| - const { 0: { 0: code, 1: signal }, 1: stdout, 2: stderr } = await SafePromiseAll([ |
120 |
| - once(child, 'exit', { signal: t.signal }), |
121 |
| - toArray.call(child.stdout, { signal: t.signal }), |
122 |
| - toArray.call(child.stderr, { signal: t.signal }) |
123 |
| - ]) |
124 |
| - |
125 |
| - if (code !== 0 || signal !== null) { |
126 |
| - if (!err) { |
127 |
| - err = new ERR_TEST_FAILURE('test failed', kSubtestsFailed) |
128 |
| - err.exitCode = code |
129 |
| - err.signal = signal |
130 |
| - err.stdout = ArrayPrototypeJoin(stdout, '') |
131 |
| - err.stderr = ArrayPrototypeJoin(stderr, '') |
132 |
| - // The stack will not be useful since the failures came from tests |
133 |
| - // in a child process. |
134 |
| - err.stack = undefined |
135 |
| - } |
136 |
| - |
137 |
| - throw err |
138 |
| - } |
139 |
| - }) |
140 |
| -} |
141 |
| - |
142 |
| -;(async function main () { |
143 |
| - const testFiles = createTestFileList() |
144 |
| - |
145 |
| - for (let i = 0; i < testFiles.length; i++) { |
146 |
| - runTestFile(testFiles[i]) |
147 |
| - } |
148 |
| -})() |
| 11 | +const tapStream = run() |
| 12 | +tapStream.pipe(process.stdout) |
| 13 | +tapStream.once('test:fail', () => { |
| 14 | + process.exitCode = 1 |
| 15 | +}) |
0 commit comments