Skip to content

Commit a948e4f

Browse files
committed
test(wpt): add results to an existing WPT Report
1 parent 474f54f commit a948e4f

File tree

4 files changed

+93
-7
lines changed

4 files changed

+93
-7
lines changed

test/wpt/runner/runner/runner.mjs

Lines changed: 75 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { EventEmitter, once } from 'node:events'
2-
import { readdirSync, readFileSync, statSync } from 'node:fs'
32
import { isAbsolute, join, resolve } from 'node:path'
3+
import { existsSync, readdirSync, readFileSync, statSync, writeFileSync } from 'node:fs'
44
import { fileURLToPath } from 'node:url'
55
import { Worker } from 'node:worker_threads'
66
import { colors, handlePipes, normalizeName, parseMeta, resolveStatusPath } from './util.mjs'
@@ -9,6 +9,24 @@ const basePath = fileURLToPath(join(import.meta.url, '../../..'))
99
const testPath = join(basePath, 'tests')
1010
const statusPath = join(basePath, 'status')
1111

12+
// https://github.com/web-platform-tests/wpt/blob/b24eedd/resources/testharness.js#L3705
13+
function sanitizeUnpairedSurrogates (str) {
14+
return str.replace(
15+
/([\ud800-\udbff]+)(?![\udc00-\udfff])|(^|[^\ud800-\udbff])([\udc00-\udfff]+)/g,
16+
function (_, low, prefix, high) {
17+
let output = prefix || '' // Prefix may be undefined
18+
const string = low || high // Only one of these alternates can match
19+
for (let i = 0; i < string.length; i++) {
20+
output += codeUnitStr(string[i])
21+
}
22+
return output
23+
})
24+
}
25+
26+
function codeUnitStr (char) {
27+
return 'U+' + char.charCodeAt(0).toString(16)
28+
}
29+
1230
export class WPTRunner extends EventEmitter {
1331
/** @type {string} */
1432
#folderName
@@ -31,6 +49,12 @@ export class WPTRunner extends EventEmitter {
3149
/** Tests that have expectedly failed mapped by file name */
3250
#statusOutput = {}
3351

52+
/** @type {boolean} */
53+
#appendReport
54+
55+
/** @type {string} */
56+
#reportPath
57+
3458
#stats = {
3559
completed: 0,
3660
failed: 0,
@@ -39,7 +63,7 @@ export class WPTRunner extends EventEmitter {
3963
skipped: 0
4064
}
4165

42-
constructor (folder, url) {
66+
constructor (folder, url, { appendReport = false, reportPath } = {}) {
4367
super()
4468

4569
this.#folderName = folder
@@ -50,6 +74,19 @@ export class WPTRunner extends EventEmitter {
5074
(file) => file.endsWith('.any.js')
5175
)
5276
)
77+
78+
if (appendReport) {
79+
if (!reportPath) {
80+
throw new TypeError('reportPath must be provided when appendReport is true')
81+
}
82+
if (!existsSync(reportPath)) {
83+
throw new TypeError('reportPath is invalid')
84+
}
85+
}
86+
87+
this.#appendReport = appendReport
88+
this.#reportPath = reportPath
89+
5390
this.#status = JSON.parse(readFileSync(join(statusPath, `${folder}.status.json`)))
5491
this.#url = url
5592

@@ -139,13 +176,29 @@ export class WPTRunner extends EventEmitter {
139176
}
140177
})
141178

179+
let result, report
180+
if (this.#appendReport) {
181+
report = JSON.parse(readFileSync(this.#reportPath))
182+
183+
const fileUrl = new URL(`/${this.#folderName}${test.slice(this.#folderPath.length)}`, 'http://wpt')
184+
fileUrl.pathname = fileUrl.pathname.replace(/\.js$/, '.html')
185+
fileUrl.search = variant
186+
187+
result = {
188+
test: fileUrl.href.slice(fileUrl.origin.length),
189+
subtests: [],
190+
status: 'OK'
191+
}
192+
report.results.push(result)
193+
}
194+
142195
activeWorkers.add(worker)
143196
// These values come directly from the web-platform-tests
144197
const timeout = meta.timeout === 'long' ? 60_000 : 10_000
145198

146199
worker.on('message', (message) => {
147200
if (message.type === 'result') {
148-
this.handleIndividualTestCompletion(message, status, test)
201+
this.handleIndividualTestCompletion(message, status, test, meta, result)
149202
} else if (message.type === 'completion') {
150203
this.handleTestCompletion(worker)
151204
}
@@ -161,6 +214,10 @@ export class WPTRunner extends EventEmitter {
161214
console.log(`Test took ${(performance.now() - start).toFixed(2)}ms`)
162215
console.log('='.repeat(96))
163216

217+
if (result?.subtests.length > 0) {
218+
writeFileSync(this.#reportPath, JSON.stringify(report))
219+
}
220+
164221
finishedFiles++
165222
activeWorkers.delete(worker)
166223
} catch (e) {
@@ -179,15 +236,25 @@ export class WPTRunner extends EventEmitter {
179236
/**
180237
* Called after a test has succeeded or failed.
181238
*/
182-
handleIndividualTestCompletion (message, status, path) {
239+
handleIndividualTestCompletion (message, status, path, meta, wptResult) {
183240
const { file, topLevel } = status
184241

185242
if (message.type === 'result') {
186243
this.#stats.completed += 1
187244

245+
if (/^Untitled( \d+)?$/.test(message.result.name)) {
246+
message.result.name = `${meta.title}${message.result.name.slice(8)}`
247+
}
248+
188249
if (message.result.status === 1) {
189250
this.#stats.failed += 1
190251

252+
wptResult?.subtests.push({
253+
status: 'FAIL',
254+
name: sanitizeUnpairedSurrogates(message.result.name),
255+
message: sanitizeUnpairedSurrogates(message.result.message)
256+
})
257+
191258
const name = normalizeName(message.result.name)
192259

193260
if (file.flaky?.includes(name)) {
@@ -206,6 +273,10 @@ export class WPTRunner extends EventEmitter {
206273
console.error(message.result)
207274
}
208275
} else {
276+
wptResult?.subtests.push({
277+
status: 'PASS',
278+
name: sanitizeUnpairedSurrogates(message.result.name)
279+
})
209280
this.#stats.success += 1
210281
}
211282
}

test/wpt/start-fetch.mjs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { fileURLToPath } from 'url'
44
import { fork } from 'child_process'
55
import { on } from 'events'
66

7+
const { WPT_REPORT } = process.env
8+
79
const serverPath = fileURLToPath(join(import.meta.url, '../server/server.mjs'))
810

911
const child = fork(serverPath, [], {
@@ -14,7 +16,10 @@ child.on('exit', (code) => process.exit(code))
1416

1517
for await (const [message] of on(child, 'message')) {
1618
if (message.server) {
17-
const runner = new WPTRunner('fetch', message.server)
19+
const runner = new WPTRunner('fetch', message.server, {
20+
appendReport: !!WPT_REPORT,
21+
reportPath: WPT_REPORT
22+
})
1823
runner.run()
1924

2025
runner.once('completion', () => {

test/wpt/start-mimesniff.mjs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { fileURLToPath } from 'url'
44
import { fork } from 'child_process'
55
import { on } from 'events'
66

7+
const { WPT_REPORT } = process.env
8+
79
const serverPath = fileURLToPath(join(import.meta.url, '../server/server.mjs'))
810

911
const child = fork(serverPath, [], {
@@ -14,7 +16,10 @@ child.on('exit', (code) => process.exit(code))
1416

1517
for await (const [message] of on(child, 'message')) {
1618
if (message.server) {
17-
const runner = new WPTRunner('mimesniff', message.server)
19+
const runner = new WPTRunner('mimesniff', message.server, {
20+
appendReport: !!WPT_REPORT,
21+
reportPath: WPT_REPORT
22+
})
1823
runner.run()
1924

2025
runner.once('completion', () => {

test/wpt/start-xhr.mjs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
import { WPTRunner } from './runner/runner/runner.mjs'
22
import { once } from 'events'
33

4-
const runner = new WPTRunner('xhr/formdata', 'http://localhost:3333')
4+
const { WPT_REPORT } = process.env
5+
6+
const runner = new WPTRunner('xhr/formdata', 'http://localhost:3333', {
7+
appendReport: !!WPT_REPORT,
8+
reportPath: WPT_REPORT
9+
})
510
runner.run()
611

712
await once(runner, 'completion')

0 commit comments

Comments
 (0)