@@ -58,39 +58,60 @@ function codeUnitStr(char) {
58
58
return 'U+' + char . charCodeAt ( 0 ) . toString ( 16 ) ;
59
59
}
60
60
61
+ class ReportResult {
62
+ constructor ( name ) {
63
+ this . test = name ;
64
+ this . status = 'OK' ;
65
+ this . subtests = [ ] ;
66
+ }
67
+
68
+ addSubtest ( name , status , message ) {
69
+ const subtest = {
70
+ status,
71
+ // https://github.com/web-platform-tests/wpt/blob/b24eedd/resources/testharness.js#L3722
72
+ name : sanitizeUnpairedSurrogates ( name ) ,
73
+ } ;
74
+ if ( message ) {
75
+ // https://github.com/web-platform-tests/wpt/blob/b24eedd/resources/testharness.js#L4506
76
+ subtest . message = sanitizeUnpairedSurrogates ( message ) ;
77
+ }
78
+ this . subtests . push ( subtest ) ;
79
+ return subtest ;
80
+ }
81
+
82
+ finish ( status ) {
83
+ this . status = status ?? 'OK' ;
84
+ }
85
+ }
86
+
87
+ // Generates a report that can be uploaded to wpt.fyi.
88
+ // Checkout https://github.com/web-platform-tests/wpt.fyi/tree/main/api#results-creation
89
+ // for more details.
61
90
class WPTReport {
62
91
constructor ( path ) {
63
92
this . filename = `report-${ path . replaceAll ( '/' , '-' ) } .json` ;
64
- this . results = [ ] ;
93
+ /** @type {Map<string, ReportResult> } */
94
+ this . results = new Map ( ) ;
65
95
this . time_start = Date . now ( ) ;
66
96
}
67
97
68
- addResult ( name , status ) {
69
- const result = {
70
- test : name ,
71
- status,
72
- subtests : [ ] ,
73
- addSubtest ( name , status , message ) {
74
- const subtest = {
75
- status,
76
- // https://github.com/web-platform-tests/wpt/blob/b24eedd/resources/testharness.js#L3722
77
- name : sanitizeUnpairedSurrogates ( name ) ,
78
- } ;
79
- if ( message ) {
80
- // https://github.com/web-platform-tests/wpt/blob/b24eedd/resources/testharness.js#L4506
81
- subtest . message = sanitizeUnpairedSurrogates ( message ) ;
82
- }
83
- this . subtests . push ( subtest ) ;
84
- return subtest ;
85
- } ,
86
- } ;
87
- this . results . push ( result ) ;
98
+ /**
99
+ * Get or create a ReportResult for a test spec.
100
+ * @param {WPTTestSpec } spec
101
+ */
102
+ getResult ( spec ) {
103
+ const name = `/${ spec . getRelativePath ( ) } ${ spec . variant } ` ;
104
+ if ( this . results . has ( name ) ) {
105
+ return this . results . get ( name ) ;
106
+ }
107
+ const result = new ReportResult ( name ) ;
108
+ this . results . set ( name , result ) ;
88
109
return result ;
89
110
}
90
111
91
112
write ( ) {
92
113
this . time_end = Date . now ( ) ;
93
- this . results = this . results . filter ( ( result ) => {
114
+ const results = Array . from ( this . results . values ( ) ) . filter ( ( result ) => {
94
115
return result . status === 'SKIP' || result . subtests . length !== 0 ;
95
116
} ) . map ( ( result ) => {
96
117
const url = new URL ( result . test , 'http://wpt' ) ;
@@ -110,7 +131,12 @@ class WPTReport {
110
131
os : getOs ( ) ,
111
132
} ;
112
133
113
- fs . writeFileSync ( `out/wpt/${ this . filename } ` , JSON . stringify ( this ) ) ;
134
+ fs . writeFileSync ( `out/wpt/${ this . filename } ` , JSON . stringify ( {
135
+ time_start : this . time_start ,
136
+ time_end : this . time_end ,
137
+ run_info : this . run_info ,
138
+ results : results ,
139
+ } ) ) ;
114
140
}
115
141
}
116
142
@@ -642,14 +668,13 @@ class WPTRunner {
642
668
this . inProgress . add ( spec ) ;
643
669
this . workers . set ( spec , worker ) ;
644
670
645
- let reportResult ;
671
+ const reportResult = this . report ?. getResult ( spec ) ;
646
672
worker . on ( 'message' , ( message ) => {
647
673
switch ( message . type ) {
648
674
case 'result' :
649
- reportResult ||= this . report ?. addResult ( `/${ relativePath } ${ spec . variant } ` , 'OK' ) ;
650
675
return this . resultCallback ( spec , message . result , reportResult ) ;
651
676
case 'completion' :
652
- return this . completionCallback ( spec , message . status ) ;
677
+ return this . completionCallback ( spec , message . status , reportResult ) ;
653
678
default :
654
679
throw new Error ( `Unexpected message from worker: ${ message . type } ` ) ;
655
680
}
@@ -661,6 +686,7 @@ class WPTRunner {
661
686
// This can happen normally, for example in timers tests.
662
687
return ;
663
688
}
689
+ // Generate a subtest failure for visibility.
664
690
this . fail (
665
691
spec ,
666
692
{
@@ -670,7 +696,10 @@ class WPTRunner {
670
696
stack : inspect ( err ) ,
671
697
} ,
672
698
kUncaught ,
699
+ reportResult ,
673
700
) ;
701
+ // Mark the whole test as failed in wpt.fyi report.
702
+ reportResult ?. finish ( 'ERROR' ) ;
674
703
this . inProgress . delete ( spec ) ;
675
704
} ) ;
676
705
@@ -681,6 +710,9 @@ class WPTRunner {
681
710
process . on ( 'exit' , ( ) => {
682
711
for ( const spec of this . inProgress ) {
683
712
this . fail ( spec , { name : 'Incomplete' } , kIncomplete ) ;
713
+ // Mark the whole test as failed in wpt.fyi report.
714
+ const reportResult = this . report ?. getResult ( spec ) ;
715
+ reportResult . finish ( 'ERROR' ) ;
684
716
}
685
717
inspect . defaultOptions . depth = Infinity ;
686
718
// Sorts the rules to have consistent output
@@ -780,6 +812,7 @@ class WPTRunner {
780
812
* in one test file).
781
813
* @param {WPTTestSpec } spec
782
814
* @param {Test } test The Test object returned by WPT harness
815
+ * @param {ReportResult } reportResult The report result object
783
816
*/
784
817
resultCallback ( spec , test , reportResult ) {
785
818
const status = this . getTestStatus ( test . status ) ;
@@ -794,13 +827,17 @@ class WPTRunner {
794
827
* Report the status of each WPT test (one per file)
795
828
* @param {WPTTestSpec } spec
796
829
* @param {object } harnessStatus - The status object returned by WPT harness.
830
+ * @param {ReportResult } reportResult The report result object
797
831
*/
798
- completionCallback ( spec , harnessStatus ) {
832
+ completionCallback ( spec , harnessStatus , reportResult ) {
799
833
const status = this . getTestStatus ( harnessStatus . status ) ;
800
834
801
835
// Treat it like a test case failure
802
836
if ( status === kTimeout ) {
803
- this . fail ( spec , { name : 'WPT testharness timeout' } , kTimeout ) ;
837
+ this . fail ( spec , { name : 'WPT testharness timeout' } , kTimeout , reportResult ) ;
838
+ reportResult ?. finish ( 'TIMEOUT' ) ;
839
+ } else {
840
+ reportResult ?. finish ( ) ;
804
841
}
805
842
this . inProgress . delete ( spec ) ;
806
843
// Always force termination of the worker. Some tests allocate resources
0 commit comments