Fix tools/deno (#734)

This commit moves runtime specific things functions reading files into a
common/runtime/helpers/sys.ts file.
This commit is contained in:
Luca Casonato 2021-09-10 01:50:25 +02:00 committed by GitHub
parent 6b010f9073
commit d5536f89e9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 70 additions and 232 deletions

View file

@ -26,7 +26,7 @@ module.exports = function (grunt) {
},
unittest: {
cmd: 'node',
args: ['tools/run', 'unittests:*'],
args: ['tools/run_node', 'unittests:*'],
},
'build-out': {
cmd: 'node',

View file

@ -6,7 +6,7 @@ will first need to install Deno: [stable](https://deno.land#installation), or
build the main branch from source
(`cargo install --git https://github.com/denoland/deno --bin deno`).
On macOS and recent Linux, you can just run `./tools/deno` as is. On Windows and
On macOS and recent Linux, you can just run `./tools/run_deno` as is. On Windows and
older Linux releases you will need to run
`deno run --unstable --allow-read --allow-write --allow-env ./tools/deno`.
@ -14,12 +14,11 @@ older Linux releases you will need to run
```
Usage:
tools/deno [OPTIONS...] QUERIES...
tools/deno 'unittests:*' 'webgpu:buffers,*'
tools/run_deno [OPTIONS...] QUERIES...
tools/run_deno 'unittests:*' 'webgpu:buffers,*'
Options:
--verbose Print result/log of every test as it runs.
--debug Include debug messages in logging.
--print-json Print the complete result JSON in the output.
--trace Record a trace of the WebGPU operations into a ./trace directory.
--ignore-file=<file> A line delimited text file containing names of tests to skip.
--verbose Print result/log of every test as it runs.
--debug Include debug messages in logging.
--print-json Print the complete result JSON in the output.
--expectations Path to expectations file.
```

2
package-lock.json generated
View file

@ -773,6 +773,7 @@
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
"integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
"dev": true,
"hasInstallScript": true,
"optional": true,
"os": [
"darwin"
@ -4954,6 +4955,7 @@
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
"integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
"dev": true,
"hasInstallScript": true,
"optional": true,
"os": [
"darwin"

View file

@ -1,9 +1,4 @@
/* eslint no-console: "off" */
/* eslint no-process-exit: "off" */
import * as fs from 'fs';
import * as path from 'path';
import * as process from 'process';
import { DefaultTestFileLoader } from '../internal/file_loader.js';
import { prettyPrintLog } from '../internal/logging/log_message.js';
@ -13,19 +8,21 @@ import { parseQuery } from '../internal/query/parseQuery.js';
import { parseExpectationsForTestQuery } from '../internal/query/query.js';
import { assert, unreachable } from '../util/util.js';
import sys from './helper/sys.js';
function usage(rc: number): never {
console.log('Usage:');
console.log(' tools/run [OPTIONS...] QUERIES...');
console.log(" tools/run 'unittests:*' 'webgpu:buffers,*'");
console.log(` tools/run_${sys.type} [OPTIONS...] QUERIES...`);
console.log(` tools/run_${sys.type} 'unittests:*' 'webgpu:buffers,*'`);
console.log('Options:');
console.log(' --verbose Print result/log of every test as it runs.');
console.log(' --debug Include debug messages in logging.');
console.log(' --print-json Print the complete result JSON in the output.');
console.log(' --expectations Path to expectations file.');
return process.exit(rc);
return sys.exit(rc);
}
if (!fs.existsSync('src/common/runtime/cmdline.ts')) {
if (!sys.existsSync('src/common/runtime/cmdline.ts')) {
console.log('Must be run from repository root');
usage(1);
}
@ -36,8 +33,8 @@ let printJSON = false;
let loadWebGPUExpectations: Promise<unknown> | undefined = undefined;
const queries: string[] = [];
for (let i = 2; i < process.argv.length; ++i) {
const a = process.argv[i];
for (let i = 0; i < sys.args.length; ++i) {
const a = sys.args[i];
if (a.startsWith('-')) {
if (a === '--verbose') {
verbose = true;
@ -46,7 +43,7 @@ for (let i = 2; i < process.argv.length; ++i) {
} else if (a === '--print-json') {
printJSON = true;
} else if (a === '--expectations') {
const expectationsFile = path.resolve(process.cwd(), process.argv[++i]);
const expectationsFile = new URL(sys.args[++i], `file://${sys.cwd()}`).pathname;
loadWebGPUExpectations = import(expectationsFile).then(m => m.expectations);
} else {
usage(1);
@ -143,11 +140,11 @@ Skipped = ${rpt(skipped.length)}
Failed = ${rpt(failed.length)}`);
if (failed.length || warned.length) {
process.exit(1);
sys.exit(1);
}
})().catch(ex => {
console.log(ex.stack ?? ex.toString());
process.exit(1);
sys.exit(1);
});
function printResults(results: Array<[string, LiveTestCaseResult]>): void {

View file

@ -0,0 +1,46 @@
/* eslint no-process-exit: "off" */
/* eslint @typescript-eslint/no-namespace: "off" */
function node() {
const { existsSync } = require('fs');
return {
type: 'node',
existsSync,
args: process.argv.slice(2),
cwd: process.cwd,
exit: process.exit,
};
}
declare global {
namespace Deno {
function readFileSync(path: string): Uint8Array;
const args: string[];
const cwd: () => string;
function exit(code?: number): never;
}
}
function deno() {
function existsSync(path: string) {
try {
Deno.readFileSync(path);
return true;
} catch (err) {
return false;
}
}
return {
type: 'deno',
existsSync,
args: Deno.args,
cwd: Deno.cwd,
exit: Deno.exit,
};
}
const sys = typeof globalThis.process !== 'undefined' ? node() : deno();
export default sys;

View file

@ -1,209 +0,0 @@
#!/usr/bin/env -S deno run --unstable --allow-read --allow-write --allow-env --no-check
/* eslint no-console: "off" */
/* eslint no-process-exit: "off" */
import { existsSync } from "https://deno.land/std@0.90.0/fs/exists.ts";
import { resolve as pathResolve } from "https://deno.land/std@0.90.0/path/mod.ts"
import { DefaultTestFileLoader } from "../out/common/framework/file_loader.js";
import { Logger } from "../out/common/framework/logging/logger.js";
import { parseQuery } from "../out/common/framework/query/parseQuery.js";
import { compareQueries, Ordering } from '../out/common/framework/query/compare.js';
import { assert, unreachable } from "../out/common/framework/util.js";
import { parseExpectationsForTestQuery } from "../src/common/framework/query/query.js";
function usage(rc) {
console.log("Usage:");
console.log(" tools/deno [OPTIONS...] QUERIES...");
console.log(" tools/deno 'unittests:*' 'webgpu:buffers,*'");
console.log("Options:");
console.log(" --verbose Print result/log of every test as it runs.");
console.log(" --debug Include debug messages in logging.");
console.log(" --print-json Print the complete result JSON in the output.");
console.log(" --trace Record a trace of the WebGPU operations into a ./trace directory.");
console.log(" --ignore-file=<file> A line delimited text file containing names of tests to skip.");
console.log(' --expectations Path to expectations file. Must be absolute, or relative to')
return Deno.exit(rc);
}
function printResults(results) {
for (const [name, r] of results) {
console.log(`[${r.status}] ${name} (${r.timems}ms). Log:`);
if (r.logs) {
for (const l of r.logs) {
console.log(" - " + l.toJSON().replace(/\n/g, "\n "));
}
}
}
}
if (!existsSync("src/common/runtime/cmdline.ts")) {
console.log("Must be run from repository root");
usage(1);
}
if (!existsSync("out/common/runtime/cmdline.js")) {
console.log("You must run `npm run standalone` before running ./tools/deno");
usage(1);
}
// Remove the `/// <reference types="@webgpu/types" />` comment, so Deno does not
// parse it and try to import `@webgpu/types`. (Which it fails on because Deno
// uses fully specified import specifiers).
const badComment = `/// <reference types="@webgpu/types" />`;
const navigatorGpuPath = "./out/webgpu/util/navigator_gpu.js";
let navigatorGpuFile = await Deno.readTextFile(navigatorGpuPath);
navigatorGpuFile = navigatorGpuFile.replace(
badComment,
" ".repeat(badComment.length),
);
await Deno.writeTextFile(navigatorGpuPath, navigatorGpuFile);
let verbose = false;
let trace = false;
let debug = false;
let ignoreFile = undefined;
let printJSON = false;
let loadWebGPUExpectations = undefined;
const queries = [];
for (const a of Deno.args) {
if (a.startsWith("-")) {
if (a === "--verbose") {
verbose = true;
} else if (a === "--trace") {
trace = true;
} else if (a === "--debug") {
debug = true;
} else if (a === "--print-json") {
printJSON = true;
} else if (a.startsWith("--ignore-file=")) {
ignoreFile = a.slice("--ignore-file=".length);
} else if (a === '--expectations') {
const expectationsFile = pathResolve(Deno.cwd(), Deno.args[++i]);
loadWebGPUExpectations = import(expectationsFile).then(m => m.expectations);
} else {
usage(1);
}
} else {
queries.push(a);
}
}
if (queries.length === 0) {
usage(0);
}
let ignores = [];
if (ignoreFile) {
const ignoreFileText = await Deno.readTextFile(ignoreFile);
ignores = ignoreFileText.split("\n").map((line) => line.split("#")[0].trim())
.filter((l) => l.length > 0);
}
try {
const loader = new DefaultTestFileLoader();
assert(
queries.length === 1,
"currently, there must be exactly one query on the cmd line",
);
const filterQuery = parseQuery(queries[0]);
const testcases = await loader.loadCases(filterQuery);
const expectations = parseExpectationsForTestQuery(
await (loadWebGPUExpectations ?? []),
filterQuery
);
const log = new Logger(debug);
const failed = [];
const warned = [];
const skipped = [];
const ignored = [];
let total = 0;
for (const testcase of testcases) {
total++;
const name = testcase.query.toString();
if (ignores.includes(name)) {
ignored.push(name);
continue;
}
if (verbose) {
console.log(`Starting ${name}`);
}
if (trace) {
const traceDir = `./trace/${name}`;
await Deno.mkdir(traceDir, { recursive: true });
Deno.env.set("DENO_WEBGPU_TRACE", traceDir);
}
const [rec, res] = log.record(name);
await testcase.run(rec, expectations);
if (verbose) {
printResults([[name, res]]);
}
switch (res.status) {
case "pass":
break;
case "fail":
failed.push([name, res]);
break;
case "warn":
warned.push([name, res]);
break;
case "skip":
skipped.push([name, res]);
break;
default:
unreachable("unrecognized status");
}
}
assert(total > 0, "found no tests!");
// TODO: write results out somewhere (a file?)
if (printJSON) {
console.log(log.asJSON(2));
}
if (skipped.length) {
console.log("");
console.log("** Skipped **");
printResults(skipped);
}
if (warned.length) {
console.log("");
console.log("** Warnings **");
printResults(warned);
}
if (failed.length) {
console.log("");
console.log("** Failures **");
printResults(failed);
}
const passed = total - warned.length - failed.length - skipped.length;
const pct = (x) => ((100 * x) / total).toFixed(2);
const rpt = (x) => {
const xs = x.toString().padStart(1 + Math.log10(total), " ");
return `${xs} / ${total} = ${pct(x).padStart(6, " ")}%`;
};
console.log("");
console.log(`** Summary **
Passed w/o warnings = ${rpt(passed)}
Passed with warnings = ${rpt(warned.length)}
Skipped = ${rpt(skipped.length)}
Failed = ${rpt(failed.length)}
Ignored = ${rpt(ignored.length)}`);
if (failed.length || warned.length) {
Deno.exit(1);
}
} catch (ex) {
console.log(ex);
Deno.exit(1);
}

3
tools/run_deno Executable file
View file

@ -0,0 +1,3 @@
#!/usr/bin/env -S deno run --unstable --allow-read --allow-write --allow-env --allow-net=deno.land --no-check
import '../out/common/runtime/cmdline.js';