@@ -39,10 +39,18 @@ const console = require('internal/console/global');
3939const {
4040 codes : {
4141 ERR_INVALID_ARG_TYPE ,
42+ ERR_INVALID_ARG_VALUE ,
4243 ERR_TEST_FAILURE ,
44+ ERR_OUT_OF_RANGE ,
4345 } ,
4446} = require ( 'internal/errors' ) ;
45- const { validateArray, validateBoolean, validateFunction } = require ( 'internal/validators' ) ;
47+ const {
48+ validateArray,
49+ validateBoolean,
50+ validateFunction,
51+ validateObject,
52+ validateInteger,
53+ } = require ( 'internal/validators' ) ;
4654const { getInspectPort, isUsingInspector, isInspectorMessage } = require ( 'internal/util/inspector' ) ;
4755const { isRegExp } = require ( 'internal/util/types' ) ;
4856const { kEmptyObject } = require ( 'internal/util' ) ;
@@ -460,7 +468,7 @@ function run(options) {
460468 if ( options === null || typeof options !== 'object' ) {
461469 options = kEmptyObject ;
462470 }
463- let { testNamePatterns } = options ;
471+ let { testNamePatterns, shard } = options ;
464472 const { concurrency, timeout, signal, files, inspectPort, watch, setup } = options ;
465473
466474 if ( files != null ) {
@@ -469,6 +477,22 @@ function run(options) {
469477 if ( watch != null ) {
470478 validateBoolean ( watch , 'options.watch' ) ;
471479 }
480+ if ( shard != null ) {
481+ validateObject ( shard , 'options.shard' ) ;
482+ // Avoid re-evaluating the shard object in case it's a getter
483+ shard = { __proto__ : null , index : shard . index , total : shard . total } ;
484+
485+ validateInteger ( shard . total , 'options.shard.total' , 1 ) ;
486+ validateInteger ( shard . index , 'options.shard.index' ) ;
487+
488+ if ( shard . index <= 0 || shard . total < shard . index ) {
489+ throw new ERR_OUT_OF_RANGE ( 'options.shard.index' , `>= 1 && <= ${ shard . total } ("options.shard.total")` , shard . index ) ;
490+ }
491+
492+ if ( watch ) {
493+ throw new ERR_INVALID_ARG_VALUE ( 'options.shard' , watch , 'shards not supported with watch mode' ) ;
494+ }
495+ }
472496 if ( setup != null ) {
473497 validateFunction ( setup , 'options.setup' ) ;
474498 }
@@ -490,7 +514,11 @@ function run(options) {
490514 }
491515
492516 const root = createTestTree ( { concurrency, timeout, signal } ) ;
493- const testFiles = files ?? createTestFileList ( ) ;
517+ let testFiles = files ?? createTestFileList ( ) ;
518+
519+ if ( shard ) {
520+ testFiles = ArrayPrototypeFilter ( testFiles , ( _ , index ) => index % shard . total === shard . index - 1 ) ;
521+ }
494522
495523 let postRun = ( ) => root . postRun ( ) ;
496524 let filesWatcher ;
0 commit comments