88 ArrayPrototypeSlice,
99 ArrayPrototypeSome,
1010 ArrayPrototypeSort,
11+ FunctionPrototypeCall,
12+ Number,
1113 ObjectAssign,
14+ ObjectKeys,
1215 PromisePrototypeThen,
13- SafePromiseAll,
1416 SafePromiseAllReturnVoid,
1517 SafePromiseAllSettledReturnVoid,
1618 SafeMap,
@@ -35,7 +37,14 @@ const { validateArray, validateBoolean } = require('internal/validators');
3537const { getInspectPort, isUsingInspector, isInspectorMessage } = require ( 'internal/util/inspector' ) ;
3638const { kEmptyObject } = require ( 'internal/util' ) ;
3739const { createTestTree } = require ( 'internal/test_runner/harness' ) ;
38- const { kSubtestsFailed, Test } = require ( 'internal/test_runner/test' ) ;
40+ const {
41+ kAborted,
42+ kCancelledByParent,
43+ kSubtestsFailed,
44+ kTestCodeFailure,
45+ kTestTimeoutFailure,
46+ Test,
47+ } = require ( 'internal/test_runner/test' ) ;
3948const { TapParser } = require ( 'internal/test_runner/tap_parser' ) ;
4049const { YAMLToJs } = require ( 'internal/test_runner/yaml_to_js' ) ;
4150const { TokenKind } = require ( 'internal/test_runner/tap_lexer' ) ;
@@ -54,6 +63,9 @@ const kFilterArgs = ['--test', '--experimental-test-coverage', '--watch'];
5463const kFilterArgValues = [ '--test-reporter' , '--test-reporter-destination' ] ;
5564const kDiagnosticsFilterArgs = [ 'tests' , 'pass' , 'fail' , 'cancelled' , 'skipped' , 'todo' , 'duration_ms' ] ;
5665
66+ const kCanceledTests = new SafeSet ( )
67+ . add ( kCancelledByParent ) . add ( kAborted ) . add ( kTestTimeoutFailure ) ;
68+
5769// TODO(cjihrig): Replace this with recursive readdir once it lands.
5870function processPath ( path , testFiles , options ) {
5971 const stats = statSync ( path ) ;
@@ -132,6 +144,11 @@ function getRunArgs({ path, inspectPort }) {
132144
133145class FileTest extends Test {
134146 #buffer = [ ] ;
147+ #counters = { __proto__ : null , all : 0 , failed : 0 , passed : 0 , cancelled : 0 , skipped : 0 , todo : 0 , totalFailed : 0 } ;
148+ failedSubtests = false ;
149+ #skipReporting( ) {
150+ return this . #counters. all > 0 && ( ! this . error || this . error . failureType === kSubtestsFailed ) ;
151+ }
135152 #checkNestedComment( { comment } ) {
136153 const firstSpaceIndex = StringPrototypeIndexOf ( comment , ' ' ) ;
137154 if ( firstSpaceIndex === - 1 ) return false ;
@@ -140,8 +157,6 @@ class FileTest extends Test {
140157 ArrayPrototypeIncludes ( kDiagnosticsFilterArgs , StringPrototypeSlice ( comment , 0 , firstSpaceIndex ) ) ;
141158 }
142159 #handleReportItem( { kind, node, comments, nesting = 0 } ) {
143- nesting += 1 ;
144-
145160 if ( comments ) {
146161 ArrayPrototypeForEach ( comments , ( comment ) => this . reporter . diagnostic ( nesting , this . name , comment ) ) ;
147162 }
@@ -152,17 +167,20 @@ class FileTest extends Test {
152167 break ;
153168
154169 case TokenKind . TAP_PLAN :
170+ if ( nesting === 0 && this . #skipReporting( ) ) {
171+ break ;
172+ }
155173 this . reporter . plan ( nesting , this . name , node . end - node . start + 1 ) ;
156174 break ;
157175
158176 case TokenKind . TAP_SUBTEST_POINT :
159177 this . reporter . start ( nesting , this . name , node . name ) ;
160178 break ;
161179
162- case TokenKind . TAP_TEST_POINT :
163- // eslint-disable-next-line no-case-declarations
180+ case TokenKind . TAP_TEST_POINT : {
181+
164182 const { todo, skip, pass } = node . status ;
165- // eslint-disable-next-line no-case-declarations
183+
166184 let directive ;
167185
168186 if ( skip ) {
@@ -173,29 +191,22 @@ class FileTest extends Test {
173191 directive = kEmptyObject ;
174192 }
175193
176- if ( pass ) {
177- this . reporter . ok (
178- nesting ,
179- this . name ,
180- node . id ,
181- node . description ,
182- YAMLToJs ( node . diagnostics ) ,
183- directive
184- ) ;
185- } else {
186- this . reporter . fail (
187- nesting ,
188- this . name ,
189- node . id ,
190- node . description ,
191- YAMLToJs ( node . diagnostics ) ,
192- directive
193- ) ;
194+ const diagnostics = YAMLToJs ( node . diagnostics ) ;
195+ const cancelled = kCanceledTests . has ( diagnostics . error ?. failureType ) ;
196+ const testNumber = nesting === 0 ? ( Number ( node . id ) + this . testNumber - 1 ) : node . id ;
197+ const method = pass ? 'ok' : 'fail' ;
198+ this . reporter [ method ] ( nesting , this . name , testNumber , node . description , diagnostics , directive ) ;
199+ if ( nesting === 0 ) {
200+ FunctionPrototypeCall ( super . countSubtest ,
201+ { finished : true , skipped : skip , isTodo : todo , passed : pass , cancelled } ,
202+ this . #counters) ;
203+ this . failedSubtests ||= ! pass ;
194204 }
195205 break ;
196206
207+ }
197208 case TokenKind . COMMENT :
198- if ( nesting === 1 && this . #checkNestedComment( node ) ) {
209+ if ( nesting === 0 && this . #checkNestedComment( node ) ) {
199210 // Ignore file top level diagnostics
200211 break ;
201212 }
@@ -215,10 +226,24 @@ class FileTest extends Test {
215226 this . reportStarted ( ) ;
216227 this . #handleReportItem( ast ) ;
217228 }
229+ countSubtest ( counters ) {
230+ if ( this . #counters. all === 0 ) {
231+ return super . countSubtest ( counters ) ;
232+ }
233+ ArrayPrototypeForEach ( ObjectKeys ( counters ) , ( key ) => {
234+ counters [ key ] += this . #counters[ key ] ;
235+ } ) ;
236+ }
237+ reportStarted ( ) { }
218238 report ( ) {
219- this . reportStarted ( ) ;
239+ const skipReporting = this . #skipReporting( ) ;
240+ if ( ! skipReporting ) {
241+ super . reportStarted ( ) ;
242+ }
220243 ArrayPrototypeForEach ( this . #buffer, ( ast ) => this . #handleReportItem( ast ) ) ;
221- super . report ( ) ;
244+ if ( ! skipReporting ) {
245+ super . report ( ) ;
246+ }
222247 }
223248}
224249
@@ -273,16 +298,14 @@ function runTestFile(path, root, inspectPort, filesWatcher) {
273298 subtest . addToReport ( ast ) ;
274299 } ) ;
275300
276- const { 0 : { 0 : code , 1 : signal } } = await SafePromiseAll ( [
277- once ( child , 'exit' , { signal : t . signal } ) ,
278- child . stdout . toArray ( { signal : t . signal } ) ,
279- ] ) ;
301+ const { 0 : code , 1 : signal } = await once ( child , 'exit' , { signal : t . signal } ) ;
280302
281303 runningProcesses . delete ( path ) ;
282304 runningSubtests . delete ( path ) ;
283305 if ( code !== 0 || signal !== null ) {
284306 if ( ! err ) {
285- err = ObjectAssign ( new ERR_TEST_FAILURE ( 'test failed' , kSubtestsFailed ) , {
307+ const failureType = subtest . failedSubtests ? kSubtestsFailed : kTestCodeFailure ;
308+ err = ObjectAssign ( new ERR_TEST_FAILURE ( 'test failed' , failureType ) , {
286309 __proto__ : null ,
287310 exitCode : code ,
288311 signal : signal ,
0 commit comments