Skip to content

Commit 3d6dab6

Browse files
committed
test(wpt): add results to an existing WPT Report
1 parent 324f3e3 commit 3d6dab6

File tree

4 files changed

+93
-7
lines changed

4 files changed

+93
-7
lines changed

test/wpt/runner/runner/runner.mjs

+75-4
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
@@ -33,6 +51,12 @@ export class WPTRunner extends EventEmitter {
3351

3452
#uncaughtExceptions = []
3553

54+
/** @type {boolean} */
55+
#appendReport
56+
57+
/** @type {string} */
58+
#reportPath
59+
3660
#stats = {
3761
completed: 0,
3862
failed: 0,
@@ -41,7 +65,7 @@ export class WPTRunner extends EventEmitter {
4165
skipped: 0
4266
}
4367

44-
constructor (folder, url) {
68+
constructor (folder, url, { appendReport = false, reportPath } = {}) {
4569
super()
4670

4771
this.#folderName = folder
@@ -52,6 +76,19 @@ export class WPTRunner extends EventEmitter {
5276
(file) => file.endsWith('.any.js')
5377
)
5478
)
79+
80+
if (appendReport) {
81+
if (!reportPath) {
82+
throw new TypeError('reportPath must be provided when appendReport is true')
83+
}
84+
if (!existsSync(reportPath)) {
85+
throw new TypeError('reportPath is invalid')
86+
}
87+
}
88+
89+
this.#appendReport = appendReport
90+
this.#reportPath = reportPath
91+
5592
this.#status = JSON.parse(readFileSync(join(statusPath, `${folder}.status.json`)))
5693
this.#url = url
5794

@@ -148,13 +185,29 @@ export class WPTRunner extends EventEmitter {
148185
}
149186
})
150187

188+
let result, report
189+
if (this.#appendReport) {
190+
report = JSON.parse(readFileSync(this.#reportPath))
191+
192+
const fileUrl = new URL(`/${this.#folderName}${test.slice(this.#folderPath.length)}`, 'http://wpt')
193+
fileUrl.pathname = fileUrl.pathname.replace(/\.js$/, '.html')
194+
fileUrl.search = variant
195+
196+
result = {
197+
test: fileUrl.href.slice(fileUrl.origin.length),
198+
subtests: [],
199+
status: 'OK'
200+
}
201+
report.results.push(result)
202+
}
203+
151204
activeWorkers.add(worker)
152205
// These values come directly from the web-platform-tests
153206
const timeout = meta.timeout === 'long' ? 60_000 : 10_000
154207

155208
worker.on('message', (message) => {
156209
if (message.type === 'result') {
157-
this.handleIndividualTestCompletion(message, status, test)
210+
this.handleIndividualTestCompletion(message, status, test, meta, result)
158211
} else if (message.type === 'completion') {
159212
this.handleTestCompletion(worker)
160213
} else if (message.type === 'error') {
@@ -174,6 +227,10 @@ export class WPTRunner extends EventEmitter {
174227
console.log(`Test took ${(performance.now() - start).toFixed(2)}ms`)
175228
console.log('='.repeat(96))
176229

230+
if (result?.subtests.length > 0) {
231+
writeFileSync(this.#reportPath, JSON.stringify(report))
232+
}
233+
177234
finishedFiles++
178235
activeWorkers.delete(worker)
179236
} catch (e) {
@@ -192,15 +249,25 @@ export class WPTRunner extends EventEmitter {
192249
/**
193250
* Called after a test has succeeded or failed.
194251
*/
195-
handleIndividualTestCompletion (message, status, path) {
252+
handleIndividualTestCompletion (message, status, path, meta, wptResult) {
196253
const { file, topLevel } = status
197254

198255
if (message.type === 'result') {
199256
this.#stats.completed += 1
200257

258+
if (/^Untitled( \d+)?$/.test(message.result.name)) {
259+
message.result.name = `${meta.title}${message.result.name.slice(8)}`
260+
}
261+
201262
if (message.result.status === 1) {
202263
this.#stats.failed += 1
203264

265+
wptResult?.subtests.push({
266+
status: 'FAIL',
267+
name: sanitizeUnpairedSurrogates(message.result.name),
268+
message: sanitizeUnpairedSurrogates(message.result.message)
269+
})
270+
204271
const name = normalizeName(message.result.name)
205272

206273
if (file.flaky?.includes(name)) {
@@ -219,6 +286,10 @@ export class WPTRunner extends EventEmitter {
219286
console.error(message.result)
220287
}
221288
} else {
289+
wptResult?.subtests.push({
290+
status: 'PASS',
291+
name: sanitizeUnpairedSurrogates(message.result.name)
292+
})
222293
this.#stats.success += 1
223294
}
224295
}

test/wpt/start-fetch.mjs

+6-1
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

+6-1
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

+6-1
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)