1
1
'use strict' ;
2
2
const {
3
3
ArrayFrom,
4
- ArrayPrototypeConcat,
5
4
ArrayPrototypeFilter,
6
5
ArrayPrototypeIncludes,
7
6
ArrayPrototypeJoin,
7
+ ArrayPrototypePop,
8
+ ArrayPrototypePush,
8
9
ArrayPrototypeSlice,
9
10
ArrayPrototypeSort,
10
11
ObjectAssign,
11
12
PromisePrototypeThen,
13
+ RegExpPrototypeSymbolSplit,
12
14
SafePromiseAll,
13
15
SafeSet,
16
+ StringPrototypeEndsWith,
14
17
} = primordials ;
15
18
19
+ const { Buffer } = require ( 'buffer' ) ;
16
20
const { spawn } = require ( 'child_process' ) ;
17
21
const { readdirSync, statSync } = require ( 'fs' ) ;
18
22
const console = require ( 'internal/console/global' ) ;
@@ -22,6 +26,7 @@ const {
22
26
} ,
23
27
} = require ( 'internal/errors' ) ;
24
28
const { validateArray } = require ( 'internal/validators' ) ;
29
+ const { getInspectPort, isUsingInspector, isInspectorMessage } = require ( 'internal/util/inspector' ) ;
25
30
const { kEmptyObject } = require ( 'internal/util' ) ;
26
31
const { createTestTree } = require ( 'internal/test_runner/harness' ) ;
27
32
const { kSubtestsFailed, Test } = require ( 'internal/test_runner/test' ) ;
@@ -100,25 +105,59 @@ function filterExecArgv(arg) {
100
105
return ! ArrayPrototypeIncludes ( kFilterArgs , arg ) ;
101
106
}
102
107
103
- function runTestFile ( path , root ) {
108
+ function getRunArgs ( { path, inspectPort } ) {
109
+ const argv = ArrayPrototypeFilter ( process . execArgv , filterExecArgv ) ;
110
+ if ( isUsingInspector ( ) ) {
111
+ ArrayPrototypePush ( argv , `--inspect-port=${ getInspectPort ( inspectPort ) } ` ) ;
112
+ }
113
+ ArrayPrototypePush ( argv , path ) ;
114
+ return argv ;
115
+ }
116
+
117
+ function makeStderrCallback ( callback ) {
118
+ if ( ! isUsingInspector ( ) ) {
119
+ return callback ;
120
+ }
121
+ let buffer = Buffer . alloc ( 0 ) ;
122
+ return ( data ) => {
123
+ callback ( data ) ;
124
+ const newData = Buffer . concat ( [ buffer , data ] ) ;
125
+ const str = newData . toString ( 'utf8' ) ;
126
+ let lines = str ;
127
+ if ( StringPrototypeEndsWith ( lines , '\n' ) ) {
128
+ buffer = Buffer . alloc ( 0 ) ;
129
+ } else {
130
+ lines = RegExpPrototypeSymbolSplit ( / \r ? \n / , str ) ;
131
+ buffer = Buffer . from ( ArrayPrototypePop ( lines ) , 'utf8' ) ;
132
+ lines = ArrayPrototypeJoin ( lines , '\n' ) ;
133
+ }
134
+ if ( isInspectorMessage ( lines ) ) {
135
+ process . stderr . write ( lines ) ;
136
+ }
137
+ } ;
138
+ }
139
+
140
+ function runTestFile ( path , root , inspectPort ) {
104
141
const subtest = root . createSubtest ( Test , path , async ( t ) => {
105
- const args = ArrayPrototypeConcat (
106
- ArrayPrototypeFilter ( process . execArgv , filterExecArgv ) ,
107
- path ) ;
142
+ const args = getRunArgs ( { path, inspectPort } ) ;
108
143
109
144
const child = spawn ( process . execPath , args , { signal : t . signal , encoding : 'utf8' } ) ;
110
145
// TODO(cjihrig): Implement a TAP parser to read the child's stdout
111
146
// instead of just displaying it all if the child fails.
112
147
let err ;
148
+ let stderr = '' ;
113
149
114
150
child . on ( 'error' , ( error ) => {
115
151
err = error ;
116
152
} ) ;
117
153
118
- const { 0 : { 0 : code , 1 : signal } , 1 : stdout , 2 : stderr } = await SafePromiseAll ( [
154
+ child . stderr . on ( 'data' , makeStderrCallback ( ( data ) => {
155
+ stderr += data ;
156
+ } ) ) ;
157
+
158
+ const { 0 : { 0 : code , 1 : signal } , 1 : stdout } = await SafePromiseAll ( [
119
159
once ( child , 'exit' , { signal : t . signal } ) ,
120
160
child . stdout . toArray ( { signal : t . signal } ) ,
121
- child . stderr . toArray ( { signal : t . signal } ) ,
122
161
] ) ;
123
162
124
163
if ( code !== 0 || signal !== null ) {
@@ -128,7 +167,7 @@ function runTestFile(path, root) {
128
167
exitCode : code ,
129
168
signal : signal ,
130
169
stdout : ArrayPrototypeJoin ( stdout , '' ) ,
131
- stderr : ArrayPrototypeJoin ( stderr , '' ) ,
170
+ stderr,
132
171
// The stack will not be useful since the failures came from tests
133
172
// in a child process.
134
173
stack : undefined ,
@@ -145,7 +184,7 @@ function run(options) {
145
184
if ( options === null || typeof options !== 'object' ) {
146
185
options = kEmptyObject ;
147
186
}
148
- const { concurrency, timeout, signal, files } = options ;
187
+ const { concurrency, timeout, signal, files, inspectPort } = options ;
149
188
150
189
if ( files != null ) {
151
190
validateArray ( files , 'options.files' ) ;
@@ -154,7 +193,7 @@ function run(options) {
154
193
const root = createTestTree ( { concurrency, timeout, signal } ) ;
155
194
const testFiles = files ?? createTestFileList ( ) ;
156
195
157
- PromisePrototypeThen ( SafePromiseAll ( testFiles , ( path ) => runTestFile ( path , root ) ) ,
196
+ PromisePrototypeThen ( SafePromiseAll ( testFiles , ( path ) => runTestFile ( path , root , inspectPort ) ) ,
158
197
( ) => root . postRun ( ) ) ;
159
198
160
199
return root . reporter ;
0 commit comments