8
8
ArrayPrototypeSlice,
9
9
ArrayPrototypeSome,
10
10
ArrayPrototypeSort,
11
+ FunctionPrototypeCall,
12
+ Number,
11
13
ObjectAssign,
14
+ ObjectKeys,
12
15
PromisePrototypeThen,
13
- SafePromiseAll,
14
16
SafePromiseAllReturnVoid,
15
17
SafePromiseAllSettledReturnVoid,
16
18
SafeMap,
@@ -35,7 +37,14 @@ const { validateArray, validateBoolean } = require('internal/validators');
35
37
const { getInspectPort, isUsingInspector, isInspectorMessage } = require ( 'internal/util/inspector' ) ;
36
38
const { kEmptyObject } = require ( 'internal/util' ) ;
37
39
const { 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' ) ;
39
48
const { TapParser } = require ( 'internal/test_runner/tap_parser' ) ;
40
49
const { YAMLToJs } = require ( 'internal/test_runner/yaml_to_js' ) ;
41
50
const { TokenKind } = require ( 'internal/test_runner/tap_lexer' ) ;
@@ -55,6 +64,9 @@ const kFilterArgs = ['--test', '--experimental-test-coverage', '--watch'];
55
64
const kFilterArgValues = [ '--test-reporter' , '--test-reporter-destination' ] ;
56
65
const kDiagnosticsFilterArgs = [ 'tests' , 'pass' , 'fail' , 'cancelled' , 'skipped' , 'todo' , 'duration_ms' ] ;
57
66
67
+ const kCanceledTests = new SafeSet ( )
68
+ . add ( kCancelledByParent ) . add ( kAborted ) . add ( kTestTimeoutFailure ) ;
69
+
58
70
// TODO(cjihrig): Replace this with recursive readdir once it lands.
59
71
function processPath ( path , testFiles , options ) {
60
72
const stats = statSync ( path ) ;
@@ -133,6 +145,11 @@ function getRunArgs({ path, inspectPort }) {
133
145
134
146
class FileTest extends Test {
135
147
#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
+ }
136
153
#checkNestedComment( { comment } ) {
137
154
const firstSpaceIndex = StringPrototypeIndexOf ( comment , ' ' ) ;
138
155
if ( firstSpaceIndex === - 1 ) return false ;
@@ -141,8 +158,6 @@ class FileTest extends Test {
141
158
ArrayPrototypeIncludes ( kDiagnosticsFilterArgs , StringPrototypeSlice ( comment , 0 , firstSpaceIndex ) ) ;
142
159
}
143
160
#handleReportItem( { kind, node, comments, nesting = 0 } ) {
144
- nesting += 1 ;
145
-
146
161
if ( comments ) {
147
162
ArrayPrototypeForEach ( comments , ( comment ) => this . reporter . diagnostic ( nesting , this . name , comment ) ) ;
148
163
}
@@ -153,17 +168,20 @@ class FileTest extends Test {
153
168
break ;
154
169
155
170
case TokenKind . TAP_PLAN :
171
+ if ( nesting === 0 && this . #skipReporting( ) ) {
172
+ break ;
173
+ }
156
174
this . reporter . plan ( nesting , this . name , node . end - node . start + 1 ) ;
157
175
break ;
158
176
159
177
case TokenKind . TAP_SUBTEST_POINT :
160
178
this . reporter . start ( nesting , this . name , node . name ) ;
161
179
break ;
162
180
163
- case TokenKind . TAP_TEST_POINT :
164
- // eslint-disable-next-line no-case-declarations
181
+ case TokenKind . TAP_TEST_POINT : {
182
+
165
183
const { todo, skip, pass } = node . status ;
166
- // eslint-disable-next-line no-case-declarations
184
+
167
185
let directive ;
168
186
169
187
if ( skip ) {
@@ -174,29 +192,22 @@ class FileTest extends Test {
174
192
directive = kEmptyObject ;
175
193
}
176
194
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 ;
195
205
}
196
206
break ;
197
207
208
+ }
198
209
case TokenKind . COMMENT :
199
- if ( nesting === 1 && this . #checkNestedComment( node ) ) {
210
+ if ( nesting === 0 && this . #checkNestedComment( node ) ) {
200
211
// Ignore file top level diagnostics
201
212
break ;
202
213
}
@@ -216,10 +227,24 @@ class FileTest extends Test {
216
227
this . reportStarted ( ) ;
217
228
this . #handleReportItem( ast ) ;
218
229
}
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 ( ) { }
219
239
report ( ) {
220
- this . reportStarted ( ) ;
240
+ const skipReporting = this . #skipReporting( ) ;
241
+ if ( ! skipReporting ) {
242
+ super . reportStarted ( ) ;
243
+ }
221
244
ArrayPrototypeForEach ( this . #buffer, ( ast ) => this . #handleReportItem( ast ) ) ;
222
- super . report ( ) ;
245
+ if ( ! skipReporting ) {
246
+ super . report ( ) ;
247
+ }
223
248
}
224
249
}
225
250
@@ -274,16 +299,14 @@ function runTestFile(path, root, inspectPort, filesWatcher) {
274
299
subtest . addToReport ( ast ) ;
275
300
} ) ;
276
301
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 } ) ;
281
303
282
304
runningProcesses . delete ( path ) ;
283
305
runningSubtests . delete ( path ) ;
284
306
if ( code !== 0 || signal !== null ) {
285
307
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 ) , {
287
310
__proto__ : null ,
288
311
exitCode : code ,
289
312
signal : signal ,
0 commit comments