@@ -5,6 +5,7 @@ const fixtures = require('../common/fixtures');
55const fs = require ( 'fs' ) ;
66const fsPromises = fs . promises ;
77const path = require ( 'path' ) ;
8+ const events = require ( 'events' ) ;
89const { inspect } = require ( 'util' ) ;
910const { Worker } = require ( 'worker_threads' ) ;
1011
@@ -152,21 +153,30 @@ class WPTTestSpec {
152153 this . filename = filename ;
153154
154155 this . requires = new Set ( ) ;
155- this . failReasons = [ ] ;
156+ this . failedTests = [ ] ;
157+ this . flakyTests = [ ] ;
156158 this . skipReasons = [ ] ;
157159 for ( const item of rules ) {
158160 if ( item . requires . length ) {
159161 for ( const req of item . requires ) {
160162 this . requires . add ( req ) ;
161163 }
162164 }
163- if ( item . fail ) {
164- this . failReasons . push ( item . fail ) ;
165+ if ( Array . isArray ( item . fail ?. expected ) ) {
166+ this . failedTests . push ( ...item . fail . expected ) ;
167+ }
168+ if ( Array . isArray ( item . fail ?. flaky ) ) {
169+ this . failedTests . push ( ...item . fail . flaky ) ;
170+ this . flakyTests . push ( ...item . fail . flaky ) ;
165171 }
166172 if ( item . skip ) {
167173 this . skipReasons . push ( item . skip ) ;
168174 }
169175 }
176+
177+ this . failedTests = [ ...new Set ( this . failedTests ) ] ;
178+ this . flakyTests = [ ...new Set ( this . flakyTests ) ] ;
179+ this . skipReasons = [ ...new Set ( this . skipReasons ) ] ;
170180 }
171181
172182 getRelativePath ( ) {
@@ -368,7 +378,7 @@ class WPTRunner {
368378
369379 // TODO(joyeecheung): work with the upstream to port more tests in .html
370380 // to .js.
371- runJsTests ( ) {
381+ async runJsTests ( ) {
372382 let queue = [ ] ;
373383
374384 // If the tests are run as `node test/wpt/test-something.js subset.any.js`,
@@ -459,6 +469,8 @@ class WPTRunner {
459469 ) ;
460470 this . inProgress . delete ( testFileName ) ;
461471 } ) ;
472+
473+ await events . once ( worker , 'exit' ) . catch ( ( ) => { } ) ;
462474 }
463475
464476 process . on ( 'exit' , ( ) => {
@@ -469,34 +481,72 @@ class WPTRunner {
469481 }
470482 }
471483 inspect . defaultOptions . depth = Infinity ;
472- console . log ( this . results ) ;
484+ // Sorts the rules to have consistent output
485+ console . log ( JSON . stringify ( Object . keys ( this . results ) . sort ( ) . reduce (
486+ ( obj , key ) => {
487+ obj [ key ] = this . results [ key ] ;
488+ return obj ;
489+ } ,
490+ { }
491+ ) , null , 2 ) ) ;
473492
474493 const failures = [ ] ;
475494 let expectedFailures = 0 ;
476495 let skipped = 0 ;
477- for ( const key of Object . keys ( this . results ) ) {
478- const item = this . results [ key ] ;
479- if ( item . fail && item . fail . unexpected ) {
496+ for ( const [ key , item ] of Object . entries ( this . results ) ) {
497+ if ( item . fail ?. unexpected ) {
480498 failures . push ( key ) ;
481499 }
482- if ( item . fail && item . fail . expected ) {
500+ if ( item . fail ? .expected ) {
483501 expectedFailures ++ ;
484502 }
485503 if ( item . skip ) {
486504 skipped ++ ;
487505 }
488506 }
507+
508+ const unexpectedPasses = [ ] ;
509+ for ( const [ key , specMap ] of this . specMap ) {
510+ // File has no expected failures
511+ if ( ! specMap . failedTests . length ) {
512+ continue ;
513+ }
514+
515+ // File was (maybe even conditionally) skipped
516+ if ( this . results [ key ] ?. skip ) {
517+ continue ;
518+ }
519+
520+ // Full check: every expected to fail test is present
521+ if ( specMap . failedTests . some ( ( expectedToFail ) => {
522+ if ( specMap . flakyTests . includes ( expectedToFail ) ) {
523+ return false ;
524+ }
525+ return this . results [ key ] ?. fail ?. expected ?. includes ( expectedToFail ) !== true ;
526+ } ) ) {
527+ unexpectedPasses . push ( key ) ;
528+ continue ;
529+ }
530+ }
531+
489532 const ran = total - skipped ;
490533 const passed = ran - expectedFailures - failures . length ;
491534 console . log ( `Ran ${ ran } /${ total } tests, ${ skipped } skipped,` ,
492535 `${ passed } passed, ${ expectedFailures } expected failures,` ,
493- `${ failures . length } unexpected failures` ) ;
536+ `${ failures . length } unexpected failures,` ,
537+ `${ unexpectedPasses . length } unexpected passes` ) ;
494538 if ( failures . length > 0 ) {
495539 const file = path . join ( 'test' , 'wpt' , 'status' , `${ this . path } .json` ) ;
496540 throw new Error (
497541 `Found ${ failures . length } unexpected failures. ` +
498542 `Consider updating ${ file } for these files:\n${ failures . join ( '\n' ) } ` ) ;
499543 }
544+ if ( unexpectedPasses . length > 0 ) {
545+ const file = path . join ( 'test' , 'wpt' , 'status' , `${ this . path } .json` ) ;
546+ throw new Error (
547+ `Found ${ unexpectedPasses . length } unexpected passes. ` +
548+ `Consider updating ${ file } for these files:\n${ unexpectedPasses . join ( '\n' ) } ` ) ;
549+ }
500550 } ) ;
501551 }
502552
@@ -577,8 +627,9 @@ class WPTRunner {
577627 if ( ! result [ item . status ] [ key ] ) {
578628 result [ item . status ] [ key ] = [ ] ;
579629 }
580- if ( result [ item . status ] [ key ] . indexOf ( item . reason ) === - 1 ) {
581- result [ item . status ] [ key ] . push ( item . reason ) ;
630+ const hasName = result [ item . status ] [ key ] . includes ( item . name ) ;
631+ if ( ! hasName ) {
632+ result [ item . status ] [ key ] . push ( item . name ) ;
582633 }
583634 }
584635 }
@@ -589,10 +640,10 @@ class WPTRunner {
589640
590641 fail ( filename , test , status ) {
591642 const spec = this . specMap . get ( filename ) ;
592- const expected = ! ! ( spec . failReasons . length ) ;
643+ const expected = spec . failedTests . includes ( test . name ) ;
593644 if ( expected ) {
594645 console . log ( `[EXPECTED_FAILURE][${ status . toUpperCase ( ) } ] ${ test . name } ` ) ;
595- console . log ( spec . failReasons . join ( '; ' ) ) ;
646+ console . log ( test . message || status ) ;
596647 } else {
597648 console . log ( `[UNEXPECTED_FAILURE][${ status . toUpperCase ( ) } ] ${ test . name } ` ) ;
598649 }
@@ -604,6 +655,7 @@ class WPTRunner {
604655 ` ${ require . main . filename } ${ filename } ` ;
605656 console . log ( `Command: ${ command } \n` ) ;
606657 this . addTestResult ( filename , {
658+ name : test . name ,
607659 expected,
608660 status : kFail ,
609661 reason : test . message || status
0 commit comments