@@ -11,6 +11,7 @@ var findCacheDir = require('find-cache-dir');
11
11
var debounce = require ( 'lodash.debounce' ) ;
12
12
var ms = require ( 'ms' ) ;
13
13
var AvaFiles = require ( 'ava-files' ) ;
14
+ var getPort = require ( 'get-port' ) ;
14
15
var AvaError = require ( './lib/ava-error' ) ;
15
16
var fork = require ( './lib/fork' ) ;
16
17
var CachingPrecompiler = require ( './lib/caching-precompiler' ) ;
@@ -46,7 +47,7 @@ function Api(options) {
46
47
util . inherits ( Api , EventEmitter ) ;
47
48
module . exports = Api ;
48
49
49
- Api . prototype . _runFile = function ( file , runStatus ) {
50
+ Api . prototype . _runFile = function ( file , runStatus , execArgv ) {
50
51
var hash = this . precompiler . precompileFile ( file ) ;
51
52
var precompiled = { } ;
52
53
precompiled [ file ] = hash ;
@@ -55,7 +56,7 @@ Api.prototype._runFile = function (file, runStatus) {
55
56
precompiled : precompiled
56
57
} ) ;
57
58
58
- var emitter = fork ( file , options ) ;
59
+ var emitter = fork ( file , options , execArgv ) ;
59
60
60
61
runStatus . observeFork ( emitter ) ;
61
62
@@ -133,6 +134,36 @@ Api.prototype._run = function (files, _options) {
133
134
return overwatch ;
134
135
} ;
135
136
137
+ Api . prototype . computeForkExecArgs = function ( files ) {
138
+ var execArgv = this . options . testOnlyExecArgv || process . execArgv ;
139
+ var debugArgIndex = - 1 ;
140
+ execArgv . some ( function ( arg , index ) {
141
+ if ( arg === '--debug' || arg === '--debug-brk' || arg . indexOf ( '--debug-brk=' ) === 0 || arg . indexOf ( '--debug=' ) === 0 ) {
142
+ debugArgIndex = index ;
143
+ return true ;
144
+ }
145
+ return false ;
146
+ } ) ;
147
+
148
+ if ( debugArgIndex === - 1 ) {
149
+ return Promise . resolve ( [ ] ) ;
150
+ }
151
+
152
+ return Promise . map ( files , getPort )
153
+ . then ( function ( ports ) {
154
+ return ports . map ( function ( port ) {
155
+ var forkExecArgv = execArgv . slice ( ) ;
156
+ var flagName = '--debug' ;
157
+ var oldValue = forkExecArgv [ debugArgIndex ] ;
158
+ if ( oldValue . indexOf ( 'brk' ) > 0 ) {
159
+ flagName += '-brk' ;
160
+ }
161
+ forkExecArgv [ debugArgIndex ] = flagName + '=' + port ;
162
+ return forkExecArgv ;
163
+ } ) ;
164
+ } ) ;
165
+ } ;
166
+
136
167
Api . prototype . _runNoPool = function ( files , runStatus ) {
137
168
var self = this ;
138
169
var tests = new Array ( self . fileCount ) ;
@@ -144,94 +175,97 @@ Api.prototype._runNoPool = function (files, runStatus) {
144
175
} ) ;
145
176
} ) ;
146
177
147
- return new Promise ( function ( resolve ) {
148
- function run ( ) {
149
- if ( self . options . match . length > 0 && ! runStatus . hasExclusive ) {
150
- runStatus . handleExceptions ( {
151
- exception : new AvaError ( 'Couldn\'t find any matching tests' ) ,
152
- file : undefined
153
- } ) ;
178
+ return self . computeForkExecArgs ( files )
179
+ . then ( function ( execArgvList ) {
180
+ return new Promise ( function ( resolve ) {
181
+ function run ( ) {
182
+ if ( self . options . match . length > 0 && ! runStatus . hasExclusive ) {
183
+ runStatus . handleExceptions ( {
184
+ exception : new AvaError ( 'Couldn\'t find any matching tests' ) ,
185
+ file : undefined
186
+ } ) ;
187
+
188
+ resolve ( [ ] ) ;
189
+ return ;
190
+ }
154
191
155
- resolve ( [ ] ) ;
156
- return ;
157
- }
158
-
159
- var method = self . options . serial ? 'mapSeries' : 'map' ;
160
- var options = {
161
- runOnlyExclusive : runStatus . hasExclusive
162
- } ;
163
-
164
- resolve ( Promise [ method ] ( files , function ( file , index ) {
165
- return tests [ index ] . run ( options ) . catch ( function ( err ) {
166
- // The test failed catastrophically. Flag it up as an
167
- // exception, then return an empty result. Other tests may
168
- // continue to run.
169
- runStatus . handleExceptions ( {
170
- exception : err ,
171
- file : path . relative ( '.' , file )
172
- } ) ;
192
+ var method = self . options . serial ? 'mapSeries' : 'map' ;
193
+ var options = {
194
+ runOnlyExclusive : runStatus . hasExclusive
195
+ } ;
173
196
174
- return getBlankResults ( ) ;
175
- } ) ;
176
- } ) ) ;
177
- }
197
+ resolve ( Promise [ method ] ( files , function ( file , index ) {
198
+ return tests [ index ] . run ( options ) . catch ( function ( err ) {
199
+ // The test failed catastrophically. Flag it up as an
200
+ // exception, then return an empty result. Other tests may
201
+ // continue to run.
202
+ runStatus . handleExceptions ( {
203
+ exception : err ,
204
+ file : path . relative ( '.' , file )
205
+ } ) ;
206
+
207
+ return getBlankResults ( ) ;
208
+ } ) ;
209
+ } ) ) ;
210
+ }
178
211
179
- // receive test count from all files and then run the tests
180
- var unreportedFiles = self . fileCount ;
181
- var bailed = false ;
212
+ // receive test count from all files and then run the tests
213
+ var unreportedFiles = self . fileCount ;
214
+ var bailed = false ;
182
215
183
- files . every ( function ( file , index ) {
184
- var tried = false ;
216
+ files . every ( function ( file , index ) {
217
+ var tried = false ;
185
218
186
- function tryRun ( ) {
187
- if ( ! tried && ! bailed ) {
188
- tried = true ;
189
- unreportedFiles -- ;
219
+ function tryRun ( ) {
220
+ if ( ! tried && ! bailed ) {
221
+ tried = true ;
222
+ unreportedFiles -- ;
190
223
191
- if ( unreportedFiles === 0 ) {
192
- run ( ) ;
224
+ if ( unreportedFiles === 0 ) {
225
+ run ( ) ;
226
+ }
227
+ }
193
228
}
194
- }
195
- }
196
229
197
- try {
198
- var test = tests [ index ] = self . _runFile ( file , runStatus ) ;
230
+ try {
231
+ var test = tests [ index ] = self . _runFile ( file , runStatus , execArgvList [ index ] ) ;
199
232
200
- test . on ( 'stats' , tryRun ) ;
201
- test . catch ( tryRun ) ;
233
+ test . on ( 'stats' , tryRun ) ;
234
+ test . catch ( tryRun ) ;
202
235
203
- return true ;
204
- } catch ( err ) {
205
- bailed = true ;
236
+ return true ;
237
+ } catch ( err ) {
238
+ bailed = true ;
206
239
207
- runStatus . handleExceptions ( {
208
- exception : err ,
209
- file : path . relative ( '.' , file )
210
- } ) ;
240
+ runStatus . handleExceptions ( {
241
+ exception : err ,
242
+ file : path . relative ( '.' , file )
243
+ } ) ;
211
244
212
- resolve ( [ ] ) ;
245
+ resolve ( [ ] ) ;
213
246
214
- return false ;
215
- }
216
- } ) ;
217
- } ) . then ( function ( results ) {
218
- if ( results . length === 0 ) {
219
- // No tests ran, make sure to tear down the child processes.
220
- tests . forEach ( function ( test ) {
221
- test . send ( 'teardown' ) ;
222
- } ) ;
223
- }
247
+ return false ;
248
+ }
249
+ } ) ;
250
+ } ) . then ( function ( results ) {
251
+ if ( results . length === 0 ) {
252
+ // No tests ran, make sure to tear down the child processes.
253
+ tests . forEach ( function ( test ) {
254
+ test . send ( 'teardown' ) ;
255
+ } ) ;
256
+ }
224
257
225
- return results ;
226
- } ) . then ( function ( results ) {
227
- // cancel debounced _onTimeout() from firing
228
- if ( self . options . timeout ) {
229
- runStatus . _restartTimer . cancel ( ) ;
230
- }
258
+ return results ;
259
+ } ) . then ( function ( results ) {
260
+ // cancel debounced _onTimeout() from firing
261
+ if ( self . options . timeout ) {
262
+ runStatus . _restartTimer . cancel ( ) ;
263
+ }
231
264
232
- runStatus . processResults ( results ) ;
233
- return runStatus ;
234
- } ) ;
265
+ runStatus . processResults ( results ) ;
266
+ return runStatus ;
267
+ } ) ;
268
+ } ) ;
235
269
} ;
236
270
237
271
function getBlankResults ( ) {
@@ -259,57 +293,60 @@ Api.prototype._runLimitedPool = function (files, runStatus, concurrency) {
259
293
} ) ;
260
294
} ) ;
261
295
262
- return Promise . map ( files , function ( file ) {
263
- var handleException = function ( err ) {
264
- runStatus . handleExceptions ( {
265
- exception : err ,
266
- file : path . relative ( '.' , file )
267
- } ) ;
268
- } ;
269
-
270
- try {
271
- var test = tests [ file ] = self . _runFile ( file , runStatus ) ;
272
-
273
- return new Promise ( function ( resolve , reject ) {
274
- var runner = function ( ) {
275
- var options = {
276
- // If we're looking for matches, run every single test process in exclusive-only mode
277
- runOnlyExclusive : self . options . match . length > 0
296
+ return self . computeForkExecArgs ( files )
297
+ . then ( function ( execArgvList ) {
298
+ return Promise . map ( files , function ( file , index ) {
299
+ var handleException = function ( err ) {
300
+ runStatus . handleExceptions ( {
301
+ exception : err ,
302
+ file : path . relative ( '.' , file )
303
+ } ) ;
278
304
} ;
279
- test . run ( options )
280
- . then ( resolve )
281
- . catch ( reject ) ;
282
- } ;
283
-
284
- test . on ( 'stats' , runner ) ;
285
- test . on ( 'exit' , function ( ) {
286
- delete tests [ file ] ;
287
- } ) ;
288
- test . catch ( runner ) ;
289
- } ) . catch ( handleException ) ;
290
- } catch ( err ) {
291
- handleException ( err ) ;
292
- }
293
- } , { concurrency : concurrency } )
294
- . then ( function ( results ) {
295
- // Filter out undefined results (usually result of caught exceptions)
296
- results = results . filter ( Boolean ) ;
297
-
298
- // cancel debounced _onTimeout() from firing
299
- if ( self . options . timeout ) {
300
- runStatus . _restartTimer . cancel ( ) ;
301
- }
302
-
303
- if ( self . options . match . length > 0 && ! runStatus . hasExclusive ) {
304
- // Ensure results are empty
305
- results = [ ] ;
306
- runStatus . handleExceptions ( {
307
- exception : new AvaError ( 'Couldn\'t find any matching tests' ) ,
308
- file : undefined
309
- } ) ;
310
- }
311
305
312
- runStatus . processResults ( results ) ;
313
- return runStatus ;
314
- } ) ;
306
+ try {
307
+ var test = tests [ file ] = self . _runFile ( file , runStatus , execArgvList [ index ] ) ;
308
+
309
+ return new Promise ( function ( resolve , reject ) {
310
+ var runner = function ( ) {
311
+ var options = {
312
+ // If we're looking for matches, run every single test process in exclusive-only mode
313
+ runOnlyExclusive : self . options . match . length > 0
314
+ } ;
315
+ test . run ( options )
316
+ . then ( resolve )
317
+ . catch ( reject ) ;
318
+ } ;
319
+
320
+ test . on ( 'stats' , runner ) ;
321
+ test . on ( 'exit' , function ( ) {
322
+ delete tests [ file ] ;
323
+ } ) ;
324
+ test . catch ( runner ) ;
325
+ } ) . catch ( handleException ) ;
326
+ } catch ( err ) {
327
+ handleException ( err ) ;
328
+ }
329
+ } , { concurrency : concurrency } )
330
+ . then ( function ( results ) {
331
+ // Filter out undefined results (usually result of caught exceptions)
332
+ results = results . filter ( Boolean ) ;
333
+
334
+ // cancel debounced _onTimeout() from firing
335
+ if ( self . options . timeout ) {
336
+ runStatus . _restartTimer . cancel ( ) ;
337
+ }
338
+
339
+ if ( self . options . match . length > 0 && ! runStatus . hasExclusive ) {
340
+ // Ensure results are empty
341
+ results = [ ] ;
342
+ runStatus . handleExceptions ( {
343
+ exception : new AvaError ( 'Couldn\'t find any matching tests' ) ,
344
+ file : undefined
345
+ } ) ;
346
+ }
347
+
348
+ runStatus . processResults ( results ) ;
349
+ return runStatus ;
350
+ } ) ;
351
+ } ) ;
315
352
} ;
0 commit comments