Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
4.2 kB · 103 lines
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104// Runs a list of CTS queries against the suite's own standalone runner in a// single Chromium instance, reusing one page (navigating it fresh for each// query) rather than relaunching the browser per query. Mirrors run-shard.sh:// one JSON result (or error) file per query under OUT_DIR, a shard.log, and a// done.txt of finished queries so a rerun on the same OUT_DIR skips what// already finished.//// Usage: node browser-run-queries.cjs <dev-server-base-url> <out-dir> <queries-file>const fs = require('fs');const path = require('path');const { chromium } = require('playwright');
async function main() { const [, , baseUrl, outDir, queriesFile] = process.argv; if (!baseUrl || !outDir || !queriesFile) { console.error('usage: browser-run-queries.cjs <dev-server-base-url> <out-dir> <queries-file>'); process.exit(1); } fs.mkdirSync(outDir, { recursive: true }); const logPath = path.join(outDir, 'shard.log'); const donePath = path.join(outDir, 'done.txt'); const log = msg => fs.appendFileSync(logPath, msg + '\n');
const done = new Set( fs.existsSync(donePath) ? fs.readFileSync(donePath, 'utf8').split('\n').filter(Boolean) : [] );
const queries = fs .readFileSync(queriesFile, 'utf8') .split('\n') .map(l => l.trim()) .filter(l => l && !l.startsWith('#'));
const launchArgs = { headless: true, args: [ '--enable-unsafe-webgpu', '--enable-features=Vulkan', '--use-angle=vulkan', '--use-gl=angle', '--use-vulkan=native', '--ignore-gpu-blocklist', ], }; let browser = await chromium.launch(launchArgs); try { let page = await browser.newPage(); for (const query of queries) { if (done.has(query)) continue; const fname = query.replace(/[^A-Za-z0-9_.-]/g, '_'); // A hung browser instance (navigation never returns, even though the // dev server itself answers instantly) leaves every later query on // this shard stuck the same way, so on a timeout the browser is // closed and relaunched before the query is retried once. Only a // timeout that survives the relaunch is recorded as done. for (let attempt = 1; attempt <= 2; attempt++) { log(`=== ${new Date().toISOString()} ${query} (attempt ${attempt}) ===`); try { const url = `${baseUrl}/standalone/browser-headless.html?q=${encodeURIComponent(query)}`; await page.goto(url, { timeout: 60000 }); // waitForFunction(pageFunction, arg, options) -- the timeout goes in // the third argument, not the second, or it silently falls back to // Playwright's 30s default and queries with many cases time out. await page.waitForFunction(() => window.__ctsDone === true, undefined, { timeout: 600000 }); const result = await page.evaluate(() => ({ json: window.__ctsResultJSON, error: window.__ctsError, })); if (result.json) { fs.writeFileSync(path.join(outDir, `${fname}.json`), result.json); log(`ok for ${query}`); } else { fs.writeFileSync(path.join(outDir, `${fname}.error.txt`), result.error || '(no error message)'); log(`error for ${query}: ${result.error}`); } fs.appendFileSync(donePath, query + '\n'); break; } catch (e) { log(`exception for ${query}: ${e}`); const isTimeout = /Timeout/i.test(String((e && e.message) || e)); if (isTimeout && attempt === 1) { log(`relaunching browser after timeout on ${query}`); await browser.close().catch(() => {}); browser = await chromium.launch(launchArgs); page = await browser.newPage(); continue; } fs.writeFileSync(path.join(outDir, `${fname}.error.txt`), String((e && e.stack) || e)); fs.appendFileSync(donePath, query + '\n'); break; } } } } finally { await browser.close(); } log(`=== shard done ${new Date().toISOString()} ===`);}
main().catch(e => { console.error(e); process.exit(1);});