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' ) ;
@@ -55,6 +64,9 @@ const kFilterArgs = ['--test', '--experimental-test-coverage', '--watch'];
5564const kFilterArgValues = [ '--test-reporter' , '--test-reporter-destination' ] ;
5665const kDiagnosticsFilterArgs = [ 'tests' , 'pass' , 'fail' , 'cancelled' , 'skipped' , 'todo' , 'duration_ms' ] ;
5766
67+ const kCanceledTests = new SafeSet ( )
68+ . add ( kCancelledByParent ) . add ( kAborted ) . add ( kTestTimeoutFailure ) ;
69+
5870// TODO(cjihrig): Replace this with recursive readdir once it lands.
5971function processPath ( path , testFiles , options ) {
6072 const stats = statSync ( path ) ;
@@ -133,6 +145,11 @@ function getRunArgs({ path, inspectPort }) {
133145
134146class FileTest extends Test {
135147 #buffer = [ ] ;
148+ #counters = { __proto__ : null , all : 0 , failed : 0 , passed : 0 , cancelled : 0 , skipped : 0 , todo : 0 , totalFailed : 0 } ;
149+ failedSubtests = false ;
150+ #skipReporting( ) {
151+ return this . #counters. all > 0 && ( ! this . error || this . error . failureType === kSubtestsFailed ) ;
152+ }
136153 #checkNestedComment( { comment } ) {
137154 const firstSpaceIndex = StringPrototypeIndexOf ( comment , ' ' ) ;
138155 if ( firstSpaceIndex === - 1 ) return false ;
@@ -141,8 +158,6 @@ class FileTest extends Test {
141158 ArrayPrototypeIncludes ( kDiagnosticsFilterArgs , StringPrototypeSlice ( comment , 0 , firstSpaceIndex ) ) ;
142159 }
143160 #handleReportItem( { kind, node, comments, nesting = 0 } ) {
144- nesting += 1 ;
145-
146161 if ( comments ) {
147162 ArrayPrototypeForEach ( comments , ( comment ) => this . reporter . diagnostic ( nesting , this . name , comment ) ) ;
148163 }
@@ -153,17 +168,20 @@ class FileTest extends Test {
153168 break ;
154169
155170 case TokenKind . TAP_PLAN :
171+ if ( nesting === 0 && this . #skipReporting( ) ) {
172+ break ;
173+ }
156174 this . reporter . plan ( nesting , this . name , node . end - node . start + 1 ) ;
157175 break ;
158176
159177 case TokenKind . TAP_SUBTEST_POINT :
160178 this . reporter . start ( nesting , this . name , node . name ) ;
161179 break ;
162180
163- case TokenKind . TAP_TEST_POINT :
164- // eslint-disable-next-line no-case-declarations
181+ case TokenKind . TAP_TEST_POINT : {
182+
165183 const { todo, skip, pass } = node . status ;
166- // eslint-disable-next-line no-case-declarations
184+
167185 let directive ;
168186
169187 if ( skip ) {
@@ -174,29 +192,22 @@ class FileTest extends Test {
174192 directive = kEmptyObject ;
175193 }
176194
177- if ( pass ) {
178- this . reporter . ok (
179- nesting ,
180- this . name ,
181- node . id ,
182- node . description ,
183- YAMLToJs ( node . diagnostics ) ,
184- directive ,
185- ) ;
186- } else {
187- this . reporter . fail (
188- nesting ,
189- this . name ,
190- node . id ,
191- node . description ,
192- YAMLToJs ( node . diagnostics ) ,
193- directive ,
194- ) ;
195+ const diagnostics = YAMLToJs ( node . diagnostics ) ;
196+ const cancelled = kCanceledTests . has ( diagnostics . error ?. failureType ) ;
197+ const testNumber = nesting === 0 ? ( Number ( node . id ) + this . testNumber - 1 ) : node . id ;
198+ const method = pass ? 'ok' : 'fail' ;
199+ this . reporter [ method ] ( nesting , this . name , testNumber , node . description , diagnostics , directive ) ;
200+ if ( nesting === 0 ) {
201+ FunctionPrototypeCall ( super . countSubtest ,
202+ { finished : true , skipped : skip , isTodo : todo , passed : pass , cancelled } ,
203+ this . #counters) ;
204+ this . failedSubtests ||= ! pass ;
195205 }
196206 break ;
197207
208+ }
198209 case TokenKind . COMMENT :
199- if ( nesting === 1 && this . #checkNestedComment( node ) ) {
210+ if ( nesting === 0 && this . #checkNestedComment( node ) ) {
200211 // Ignore file top level diagnostics
201212 break ;
202213 }
@@ -216,10 +227,24 @@ class FileTest extends Test {
216227 this . reportStarted ( ) ;
217228 this . #handleReportItem( ast ) ;
218229 }
230+ countSubtest ( counters ) {
231+ if ( this . #counters. all === 0 ) {
232+ return super . countSubtest ( counters ) ;
233+ }
234+ ArrayPrototypeForEach ( ObjectKeys ( counters ) , ( key ) => {
235+ counters [ key ] += this . #counters[ key ] ;
236+ } ) ;
237+ }
238+ reportStarted ( ) { }
219239 report ( ) {
220- this . reportStarted ( ) ;
240+ const skipReporting = this . #skipReporting( ) ;
241+ if ( ! skipReporting ) {
242+ super . reportStarted ( ) ;
243+ }
221244 ArrayPrototypeForEach ( this . #buffer, ( ast ) => this . #handleReportItem( ast ) ) ;
222- super . report ( ) ;
245+ if ( ! skipReporting ) {
246+ super . report ( ) ;
247+ }
223248 }
224249}
225250
@@ -274,16 +299,14 @@ function runTestFile(path, root, inspectPort, filesWatcher) {
274299 subtest . addToReport ( ast ) ;
275300 } ) ;
276301
277- const { 0 : { 0 : code , 1 : signal } } = await SafePromiseAll ( [
278- once ( child , 'exit' , { signal : t . signal } ) ,
279- child . stdout . toArray ( { signal : t . signal } ) ,
280- ] ) ;
302+ const { 0 : code , 1 : signal } = await once ( child , 'exit' , { signal : t . signal } ) ;
281303
282304 runningProcesses . delete ( path ) ;
283305 runningSubtests . delete ( path ) ;
284306 if ( code !== 0 || signal !== null ) {
285307 if ( ! err ) {
286- err = ObjectAssign ( new ERR_TEST_FAILURE ( 'test failed' , kSubtestsFailed ) , {
308+ const failureType = subtest . failedSubtests ? kSubtestsFailed : kTestCodeFailure ;
309+ err = ObjectAssign ( new ERR_TEST_FAILURE ( 'test failed' , failureType ) , {
287310 __proto__ : null ,
288311 exitCode : code ,
289312 signal : signal ,
0 commit comments