1
1
import { deepStrictEqual } from 'node:assert'
2
2
import { EventEmitter , once } from 'node:events'
3
- import { readdirSync , readFileSync , statSync } from 'node:fs'
3
+ import { readdirSync , readFileSync , statSync , writeFileSync } from 'node:fs'
4
4
import { basename , isAbsolute , join , resolve } from 'node:path'
5
5
import { fileURLToPath } from 'node:url'
6
6
import { Worker } from 'node:worker_threads'
7
7
import { parseMeta , handlePipes , normalizeName , colors } from './util.mjs'
8
8
9
+ const { WPT_REPORT } = process . env
9
10
const basePath = fileURLToPath ( join ( import . meta. url , '../../..' ) )
10
11
const testPath = join ( basePath , 'tests' )
11
12
const statusPath = join ( basePath , 'status' )
12
13
14
+ // https://github.com/web-platform-tests/wpt/blob/b24eedd/resources/testharness.js#L3705
15
+ function sanitizeUnpairedSurrogates ( str ) {
16
+ return str . replace (
17
+ / ( [ \ud800 - \udbff ] + ) (? ! [ \udc00 - \udfff ] ) | ( ^ | [ ^ \ud800 - \udbff ] ) ( [ \udc00 - \udfff ] + ) / g,
18
+ function ( _ , low , prefix , high ) {
19
+ let output = prefix || '' // Prefix may be undefined
20
+ const string = low || high // Only one of these alternates can match
21
+ for ( let i = 0 ; i < string . length ; i ++ ) {
22
+ output += codeUnitStr ( string [ i ] )
23
+ }
24
+ return output
25
+ } )
26
+ }
27
+
28
+ function codeUnitStr ( char ) {
29
+ return 'U+' + char . charCodeAt ( 0 ) . toString ( 16 )
30
+ }
31
+
13
32
export class WPTRunner extends EventEmitter {
14
33
/** @type {string } */
15
34
#folderName
@@ -134,13 +153,29 @@ export class WPTRunner extends EventEmitter {
134
153
}
135
154
} )
136
155
156
+ let result , report
157
+ if ( WPT_REPORT ) {
158
+ report = JSON . parse ( readFileSync ( WPT_REPORT ) )
159
+
160
+ const fileUrl = new URL ( `/${ this . #folderName} ${ test . slice ( this . #folderPath. length ) } ` , 'http://wpt' )
161
+ fileUrl . pathname = fileUrl . pathname . replace ( / \. j s $ / , '.html' )
162
+ fileUrl . search = variant
163
+
164
+ result = {
165
+ test : fileUrl . href . slice ( fileUrl . origin . length ) ,
166
+ subtests : [ ] ,
167
+ status : 'OK'
168
+ }
169
+ report . results . push ( result )
170
+ }
171
+
137
172
activeWorkers . add ( worker )
138
173
// These values come directly from the web-platform-tests
139
174
const timeout = meta . timeout === 'long' ? 60_000 : 10_000
140
175
141
176
worker . on ( 'message' , ( message ) => {
142
177
if ( message . type === 'result' ) {
143
- this . handleIndividualTestCompletion ( message , basename ( test ) )
178
+ this . handleIndividualTestCompletion ( message , basename ( test ) , result )
144
179
} else if ( message . type === 'completion' ) {
145
180
this . handleTestCompletion ( worker )
146
181
}
@@ -155,9 +190,14 @@ export class WPTRunner extends EventEmitter {
155
190
156
191
console . log ( '=' . repeat ( 96 ) )
157
192
console . log ( colors ( `[${ finishedFiles } /${ total } ] PASSED - ${ test } ` , 'green' ) )
193
+ if ( variant ) console . log ( 'Variant:' , variant )
158
194
console . log ( `Test took ${ ( performance . now ( ) - start ) . toFixed ( 2 ) } ms` )
159
195
console . log ( '=' . repeat ( 96 ) )
160
196
197
+ if ( result ?. subtests . length > 0 ) {
198
+ writeFileSync ( WPT_REPORT , JSON . stringify ( report ) )
199
+ }
200
+
161
201
finishedFiles ++
162
202
} catch ( e ) {
163
203
console . log ( `${ test } timed out after ${ timeout } ms` )
@@ -172,7 +212,7 @@ export class WPTRunner extends EventEmitter {
172
212
/**
173
213
* Called after a test has succeeded or failed.
174
214
*/
175
- handleIndividualTestCompletion ( message , fileName ) {
215
+ handleIndividualTestCompletion ( message , fileName , wptResult ) {
176
216
const { fail, allowUnexpectedFailures, flaky } = this . #status[ fileName ] ?? this . #status
177
217
178
218
if ( message . type === 'result' ) {
@@ -181,6 +221,12 @@ export class WPTRunner extends EventEmitter {
181
221
if ( message . result . status === 1 ) {
182
222
this . #stats. failed += 1
183
223
224
+ wptResult ?. subtests . push ( {
225
+ status : 'FAIL' ,
226
+ name : sanitizeUnpairedSurrogates ( message . result . name ) ,
227
+ message : sanitizeUnpairedSurrogates ( message . result . message )
228
+ } )
229
+
184
230
const name = normalizeName ( message . result . name )
185
231
186
232
if ( flaky ?. includes ( name ) ) {
@@ -196,6 +242,10 @@ export class WPTRunner extends EventEmitter {
196
242
console . error ( message . result )
197
243
}
198
244
} else {
245
+ wptResult ?. subtests . push ( {
246
+ status : 'PASS' ,
247
+ name : sanitizeUnpairedSurrogates ( message . result . name )
248
+ } )
199
249
this . #stats. success += 1
200
250
}
201
251
}
0 commit comments