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' ) ;
@@ -54,6 +63,9 @@ const kFilterArgs = ['--test', '--experimental-test-coverage', '--watch'];
54
63
const kFilterArgValues = [ '--test-reporter' , '--test-reporter-destination' ] ;
55
64
const kDiagnosticsFilterArgs = [ 'tests' , 'pass' , 'fail' , 'cancelled' , 'skipped' , 'todo' , 'duration_ms' ] ;
56
65
66
+ const kCanceledTests = new SafeSet ( )
67
+ . add ( kCancelledByParent ) . add ( kAborted ) . add ( kTestTimeoutFailure ) ;
68
+
57
69
// TODO(cjihrig): Replace this with recursive readdir once it lands.
58
70
function processPath ( path , testFiles , options ) {
59
71
const stats = statSync ( path ) ;
@@ -132,6 +144,11 @@ function getRunArgs({ path, inspectPort }) {
132
144
133
145
class FileTest extends Test {
134
146
#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
+ }
135
152
#checkNestedComment( { comment } ) {
136
153
const firstSpaceIndex = StringPrototypeIndexOf ( comment , ' ' ) ;
137
154
if ( firstSpaceIndex === - 1 ) return false ;
@@ -140,8 +157,6 @@ class FileTest extends Test {
140
157
ArrayPrototypeIncludes ( kDiagnosticsFilterArgs , StringPrototypeSlice ( comment , 0 , firstSpaceIndex ) ) ;
141
158
}
142
159
#handleReportItem( { kind, node, comments, nesting = 0 } ) {
143
- nesting += 1 ;
144
-
145
160
if ( comments ) {
146
161
ArrayPrototypeForEach ( comments , ( comment ) => this . reporter . diagnostic ( nesting , this . name , comment ) ) ;
147
162
}
@@ -152,17 +167,20 @@ class FileTest extends Test {
152
167
break ;
153
168
154
169
case TokenKind . TAP_PLAN :
170
+ if ( nesting === 0 && this . #skipReporting( ) ) {
171
+ break ;
172
+ }
155
173
this . reporter . plan ( nesting , this . name , node . end - node . start + 1 ) ;
156
174
break ;
157
175
158
176
case TokenKind . TAP_SUBTEST_POINT :
159
177
this . reporter . start ( nesting , this . name , node . name ) ;
160
178
break ;
161
179
162
- case TokenKind . TAP_TEST_POINT :
163
- // eslint-disable-next-line no-case-declarations
180
+ case TokenKind . TAP_TEST_POINT : {
181
+
164
182
const { todo, skip, pass } = node . status ;
165
- // eslint-disable-next-line no-case-declarations
183
+
166
184
let directive ;
167
185
168
186
if ( skip ) {
@@ -173,29 +191,22 @@ class FileTest extends Test {
173
191
directive = kEmptyObject ;
174
192
}
175
193
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 ;
194
204
}
195
205
break ;
196
206
207
+ }
197
208
case TokenKind . COMMENT :
198
- if ( nesting === 1 && this . #checkNestedComment( node ) ) {
209
+ if ( nesting === 0 && this . #checkNestedComment( node ) ) {
199
210
// Ignore file top level diagnostics
200
211
break ;
201
212
}
@@ -215,10 +226,24 @@ class FileTest extends Test {
215
226
this . reportStarted ( ) ;
216
227
this . #handleReportItem( ast ) ;
217
228
}
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 ( ) { }
218
238
report ( ) {
219
- this . reportStarted ( ) ;
239
+ const skipReporting = this . #skipReporting( ) ;
240
+ if ( ! skipReporting ) {
241
+ super . reportStarted ( ) ;
242
+ }
220
243
ArrayPrototypeForEach ( this . #buffer, ( ast ) => this . #handleReportItem( ast ) ) ;
221
- super . report ( ) ;
244
+ if ( ! skipReporting ) {
245
+ super . report ( ) ;
246
+ }
222
247
}
223
248
}
224
249
@@ -273,16 +298,14 @@ function runTestFile(path, root, inspectPort, filesWatcher) {
273
298
subtest . addToReport ( ast ) ;
274
299
} ) ;
275
300
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 } ) ;
280
302
281
303
runningProcesses . delete ( path ) ;
282
304
runningSubtests . delete ( path ) ;
283
305
if ( code !== 0 || signal !== null ) {
284
306
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 ) , {
286
309
__proto__ : null ,
287
310
exitCode : code ,
288
311
signal : signal ,
0 commit comments