@@ -324,13 +324,14 @@ class WPTTestSpec {
324324 this . filename = filename ;
325325 this . variant = variant ;
326326 this . globalScope = globalScope ;
327+ this . rules = [ ...new Set ( rules ) ] ;
327328
328329 this . requires = new Set ( ) ;
329330 this . failedTests = [ ] ;
330331 this . flakyTests = [ ] ;
331332 this . skipReasons = [ ] ;
332333 this . skippedTests = [ ] ;
333- for ( const item of rules ) {
334+ for ( const item of this . rules ) {
334335 if ( item . requires . length ) {
335336 for ( const req of item . requires ) {
336337 this . requires . add ( req ) ;
@@ -648,6 +649,31 @@ const limit = (concurrency) => {
648649 return execute ;
649650} ;
650651
652+ function getUnexpectedPasses ( queue , results ) {
653+ const specsByRule = new Map ( ) ;
654+ for ( const spec of queue ) {
655+ for ( const rule of spec . rules ) {
656+ if ( Array . isArray ( rule . fail ?. expected ) ) {
657+ const specs = specsByRule . get ( rule ) || [ ] ;
658+ specs . push ( spec ) ;
659+ specsByRule . set ( rule , specs ) ;
660+ }
661+ }
662+ }
663+
664+ const unexpectedPasses = [ ] ;
665+ for ( const [ rule , specs ] of specsByRule ) {
666+ for ( const expectedToFail of rule . fail . expected ) {
667+ const failed = specs . some ( ( spec ) =>
668+ results [ spec . getStatusKey ( ) ] ?. fail ?. expected ?. includes ( expectedToFail ) ) ;
669+ if ( ! failed ) {
670+ unexpectedPasses . push ( `${ rule . key } :${ expectedToFail } ` ) ;
671+ }
672+ }
673+ }
674+ return unexpectedPasses ;
675+ }
676+
651677class WPTRunner {
652678 constructor ( path , { concurrency = os . availableParallelism ( ) - 1 || 1 } = { } ) {
653679 // RISC-V has very limited virtual address space in the currently common
@@ -907,32 +933,7 @@ class WPTRunner {
907933 }
908934 }
909935
910- const unexpectedPasses = [ ] ;
911- for ( const specs of queue ) {
912- const key = specs . getStatusKey ( ) ;
913-
914- // File has no expected failures
915- if ( ! specs . failedTests . length ) {
916- continue ;
917- }
918-
919- // File was (maybe even conditionally) skipped
920- if ( this . results [ key ] ?. skip ) {
921- continue ;
922- }
923-
924- // Full check: every expected to fail test is present
925- const _unexpectedPasses = specs . failedTests . filter ( ( expectedToFail ) => {
926- if ( specs . flakyTests . includes ( expectedToFail ) ) {
927- return false ;
928- }
929- return this . results [ key ] ?. fail ?. expected ?. includes ( expectedToFail ) !== true ;
930- } ) ;
931- if ( _unexpectedPasses . length ) {
932- unexpectedPasses . push ( ..._unexpectedPasses . map ( ( name ) => `${ key } :${ name } ` ) ) ;
933- continue ;
934- }
935- }
936+ const unexpectedPasses = getUnexpectedPasses ( queue , this . results ) ;
936937
937938 // Write the report on clean exit. The report is also written
938939 // incrementally after each spec completes (see completionCallback)
@@ -1171,6 +1172,7 @@ class WPTRunner {
11711172}
11721173
11731174module . exports = {
1175+ getUnexpectedPasses,
11741176 harness : harnessMock ,
11751177 ResourceLoader,
11761178 WPTTestSpec,
0 commit comments