@@ -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' ) ;
@@ -459,7 +467,7 @@ function run(options) {
459467 if ( options === null || typeof options !== 'object' ) {
460468 options = kEmptyObject ;
461469 }
462- let { testNamePatterns } = options ;
470+ let { testNamePatterns, shard } = options ;
463471 const { concurrency, timeout, signal, files, inspectPort, watch, setup } = options ;
464472
465473 if ( files != null ) {
@@ -468,6 +476,22 @@ function run(options) {
468476 if ( watch != null ) {
469477 validateBoolean ( watch , 'options.watch' ) ;
470478 }
479+ if ( shard != null ) {
480+ validateObject ( shard , 'options.shard' ) ;
481+ // Avoid re-evaluating the shard object in case it's a getter
482+ shard = { __proto__ : null , index : shard . index , total : shard . total } ;
483+
484+ validateInteger ( shard . total , 'options.shard.total' , 1 ) ;
485+ validateInteger ( shard . index , 'options.shard.index' ) ;
486+
487+ if ( shard . index <= 0 || shard . total < shard . index ) {
488+ throw new ERR_OUT_OF_RANGE ( 'options.shard.index' , `>= 1 && <= ${ shard . total } ("options.shard.total")` , shard . index ) ;
489+ }
490+
491+ if ( watch ) {
492+ throw new ERR_INVALID_ARG_VALUE ( 'options.shard' , watch , 'shards not supported with watch mode' ) ;
493+ }
494+ }
471495 if ( setup != null ) {
472496 validateFunction ( setup , 'options.setup' ) ;
473497 }
@@ -489,7 +513,11 @@ function run(options) {
489513 }
490514
491515 const root = createTestTree ( { concurrency, timeout, signal } ) ;
492- const testFiles = files ?? createTestFileList ( ) ;
516+ let testFiles = files ?? createTestFileList ( ) ;
517+
518+ if ( shard ) {
519+ testFiles = ArrayPrototypeFilter ( testFiles , ( _ , index ) => index % shard . total === shard . index - 1 ) ;
520+ }
493521
494522 let postRun = ( ) => root . postRun ( ) ;
495523 let filesWatcher ;
0 commit comments