summaryrefslogtreecommitdiff
path: root/tools/wpt/utils.ts
diff options
context:
space:
mode:
Diffstat (limited to 'tools/wpt/utils.ts')
-rw-r--r--tools/wpt/utils.ts168
1 files changed, 168 insertions, 0 deletions
diff --git a/tools/wpt/utils.ts b/tools/wpt/utils.ts
new file mode 100644
index 000000000..3efd252b4
--- /dev/null
+++ b/tools/wpt/utils.ts
@@ -0,0 +1,168 @@
+/// FLAGS
+
+import { parse } from "https://deno.land/std@0.84.0/flags/mod.ts";
+import { join, ROOT_PATH } from "../util.js";
+
+export const {
+ json,
+ quiet,
+ release,
+ ["--"]: rest,
+ ["auto-config"]: autoConfig,
+} = parse(Deno.args, {
+ "--": true,
+ boolean: ["quiet", "release", "no-interactive"],
+ string: ["json"],
+});
+
+/// PAGE ROOT
+
+/// WPT TEST MANIFEST
+
+export interface Manifest {
+ items: {
+ testharness: ManifestFolder;
+ };
+}
+export interface ManifestFolder {
+ [key: string]: ManifestFolder | ManifestTest;
+}
+export type ManifestTest = [
+ hash: string,
+ ...variations: ManifestTestVariation[],
+];
+export type ManifestTestVariation = [
+ path: string,
+ options: ManifestTestOptions,
+];
+export interface ManifestTestOptions {
+ name?: string;
+}
+
+const MANIFEST_PATH = join(ROOT_PATH, "./tools/wpt/manifest.json");
+
+export async function updateManifest() {
+ const proc = runPy(
+ ["wpt", "manifest", "--tests-root", ".", "-p", MANIFEST_PATH],
+ {},
+ );
+ const status = await proc.status();
+ assert(status.success, "updating wpt manifest should succeed");
+}
+
+export function getManifest(): Manifest {
+ const manifestText = Deno.readTextFileSync(MANIFEST_PATH);
+ return JSON.parse(manifestText);
+}
+
+/// WPT TEST EXPECTATIONS
+
+const EXPECTATION_PATH = join(ROOT_PATH, "./tools/wpt/expectation.json");
+
+export interface Expectation {
+ [key: string]: Expectation | boolean | string[];
+}
+
+export function getExpectation(): Expectation {
+ const expectationText = Deno.readTextFileSync(EXPECTATION_PATH);
+ return JSON.parse(expectationText);
+}
+
+export function saveExpectation(expectation: Expectation) {
+ Deno.writeTextFileSync(
+ EXPECTATION_PATH,
+ JSON.stringify(expectation, undefined, " "),
+ );
+}
+
+export function generateTestExpectations(filter: string[]) {
+ const manifest = getManifest();
+
+ function walk(folder: ManifestFolder, prefix: string): Expectation {
+ const expectation: Expectation = {};
+ for (const key in folder) {
+ const path = `${prefix}/${key}`;
+ const entry = folder[key];
+ if (Array.isArray(entry)) {
+ if (!filter.find((filter) => path.startsWith(filter))) continue;
+ if (key.endsWith(".js")) {
+ expectation[key] = false;
+ }
+ } else {
+ if (!filter.find((filter) => `${path}/`.startsWith(filter))) continue;
+ expectation[key] = walk(entry, path);
+ }
+ }
+ for (const key in expectation) {
+ const entry = expectation[key];
+ if (typeof entry === "object") {
+ if (Object.keys(expectation[key]).length === 0) {
+ delete expectation[key];
+ }
+ }
+ }
+ return expectation;
+ }
+
+ return walk(manifest.items.testharness, "");
+}
+
+export function getExpectFailForCase(
+ expectation: boolean | string[],
+ caseName: string,
+): boolean {
+ if (typeof expectation == "boolean") {
+ return !expectation;
+ }
+ return expectation.includes(caseName);
+}
+
+/// UTILS
+
+class AssertionError extends Error {
+ name = "AssertionError";
+ constructor(message: string) {
+ super(message);
+ }
+}
+
+export function assert(condition: unknown, message: string): asserts condition {
+ if (!condition) {
+ throw new AssertionError(message);
+ }
+}
+
+export function runPy(
+ args: string[],
+ options: Omit<Omit<Deno.RunOptions, "cmd">, "cwd">,
+): Deno.Process {
+ const cmd = Deno.build.os == "windows" ? "python.exe" : "python3";
+ return Deno.run({
+ cmd: [cmd, ...args],
+ cwd: join(ROOT_PATH, "./test_util/wpt/"),
+ ...options,
+ });
+}
+
+export async function checkPy3Available() {
+ const proc = runPy(["--version"], { stdout: "piped" });
+ const status = await proc.status();
+ assert(status.success, "failed to run python --version");
+ const output = new TextDecoder().decode(await proc.output());
+ assert(
+ output.includes("Python 3."),
+ `The ${
+ Deno.build.os == "windows" ? "python.exe" : "python3"
+ } in your path is not is not Python 3.`,
+ );
+}
+
+export async function cargoBuild() {
+ const proc = Deno.run({
+ cmd: ["cargo", "build", ...(release ? ["--release"] : [])],
+ cwd: ROOT_PATH,
+ });
+ const status = await proc.status();
+ proc.close();
+ assert(status.success, "cargo build failed");
+}