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', '--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