mirror of
https://github.com/denoland/deno.git
synced 2025-03-03 09:31:22 -05:00
test(cli): run unit tests using Deno.test (#10330)
Co-authored-by: Luca Casonato <lucacasonato@yahoo.com>
This commit is contained in:
parent
baf7092ea2
commit
3a03084580
6 changed files with 26 additions and 724 deletions
|
@ -33,16 +33,17 @@ fn js_unit_tests_lint() {
|
|||
#[test]
|
||||
fn js_unit_tests() {
|
||||
let _g = util::http_server();
|
||||
|
||||
let mut deno = util::deno_cmd()
|
||||
.current_dir(util::root_path())
|
||||
.arg("run")
|
||||
.arg("test")
|
||||
.arg("--unstable")
|
||||
.arg("--location=http://js-unit-tests/foo/bar")
|
||||
.arg("-A")
|
||||
.arg("cli/tests/unit/unit_test_runner.ts")
|
||||
.arg("--master")
|
||||
.arg("--verbose")
|
||||
.arg("cli/tests/unit")
|
||||
.spawn()
|
||||
.expect("failed to spawn script");
|
||||
|
||||
let status = deno.wait().expect("failed to wait for the child process");
|
||||
assert_eq!(Some(0), status.code());
|
||||
assert!(status.success());
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
Files in this directory are unit tests for Deno runtime.
|
||||
|
||||
Testing Deno runtime code requires checking API under different runtime
|
||||
permissions (ie. running with different `--allow-*` flags). To accomplish this
|
||||
all tests exercised are created using `unitTest()` function.
|
||||
permissions. To accomplish this all tests exercised are created using
|
||||
`unitTest()` function.
|
||||
|
||||
```ts
|
||||
import { unitTest } from "./test_util.ts";
|
||||
|
@ -24,51 +24,16 @@ unitTest(
|
|||
);
|
||||
```
|
||||
|
||||
`unitTest` is a wrapper function that enhances `Deno.test()` API in several
|
||||
ways:
|
||||
|
||||
- ability to conditionally skip tests using `UnitTestOptions.skip`.
|
||||
- ability to register required set of permissions for given test case using
|
||||
`UnitTestOptions.perms`.
|
||||
- sanitization of resources - ensuring that tests close all opened resources
|
||||
preventing interference between tests.
|
||||
- sanitization of async ops - ensuring that tests don't leak async ops by
|
||||
ensuring that all started async ops are done before test finishes.
|
||||
|
||||
## Running tests
|
||||
|
||||
`unit_test_runner.ts` is the main script used to run unit tests.
|
||||
|
||||
Runner discovers required permissions combinations by loading
|
||||
`cli/tests/unit/unit_tests.ts` and going through all registered instances of
|
||||
`unitTest`.
|
||||
|
||||
There are three ways to run `unit_test_runner.ts`:
|
||||
|
||||
```sh
|
||||
# Run all tests. Spawns worker processes for each discovered permission
|
||||
# combination:
|
||||
target/debug/deno run -A cli/tests/unit/unit_test_runner.ts --master
|
||||
# Run all tests.
|
||||
target/debug/deno test --allow-all --unstable cli/tests/unit/
|
||||
|
||||
# By default all output of worker processes is discarded; for debug purposes
|
||||
# the --verbose flag preserves output from the worker.
|
||||
target/debug/deno run -A cli/tests/unit/unit_test_runner.ts --master --verbose
|
||||
|
||||
# Run subset of tests that don't require any permissions.
|
||||
target/debug/deno run --unstable cli/tests/unit/unit_test_runner.ts
|
||||
|
||||
# Run subset tests that require "net" and "read" permissions.
|
||||
target/debug/deno run --unstable --allow-net --allow-read cli/tests/unit/unit_test_runner.ts
|
||||
|
||||
# "worker" mode communicates with parent using TCP socket on provided address;
|
||||
# after initial setup drops permissions to specified set. It shouldn't be used
|
||||
# directly, only be "master" process.
|
||||
target/debug/deno run -A cli/tests/unit/unit_test_runner.ts --worker --addr=127.0.0.1:4500 --perms=net,write,run
|
||||
|
||||
# Run specific tests.
|
||||
target/debug/deno run --unstable --allow-net cli/tests/unit/unit_test_runner.ts -- netTcpListenClose
|
||||
|
||||
RUST_BACKTRACE=1 cargo run -- run --unstable --allow-read --allow-write cli/tests/unit/unit_test_runner.ts -- netUnixDialListen
|
||||
# Run a specific test module
|
||||
target/debug/deno test --allow-all --unstable cli/tests/unit/files_test.ts
|
||||
```
|
||||
|
||||
### Http server
|
||||
|
|
|
@ -25,105 +25,6 @@ export type { Deferred } from "../../../test_util/std/async/deferred.ts";
|
|||
export { readLines } from "../../../test_util/std/io/bufio.ts";
|
||||
export { parse as parseArgs } from "../../../test_util/std/flags/mod.ts";
|
||||
|
||||
export interface Permissions {
|
||||
read: boolean;
|
||||
write: boolean;
|
||||
net: boolean;
|
||||
env: boolean;
|
||||
run: boolean;
|
||||
plugin: boolean;
|
||||
hrtime: boolean;
|
||||
}
|
||||
|
||||
export function fmtPerms(perms: Permissions): string {
|
||||
const p = Object.keys(perms)
|
||||
.filter((e): boolean => perms[e as keyof Permissions] === true)
|
||||
.map((key) => `--allow-${key}`);
|
||||
|
||||
if (p.length) {
|
||||
return p.join(" ");
|
||||
}
|
||||
|
||||
return "<no permissions>";
|
||||
}
|
||||
|
||||
const isGranted = async (name: Deno.PermissionName): Promise<boolean> =>
|
||||
(await Deno.permissions.query({ name })).state === "granted";
|
||||
|
||||
export async function getProcessPermissions(): Promise<Permissions> {
|
||||
return {
|
||||
run: await isGranted("run"),
|
||||
read: await isGranted("read"),
|
||||
write: await isGranted("write"),
|
||||
net: await isGranted("net"),
|
||||
env: await isGranted("env"),
|
||||
plugin: await isGranted("plugin"),
|
||||
hrtime: await isGranted("hrtime"),
|
||||
};
|
||||
}
|
||||
|
||||
export function permissionsMatch(
|
||||
processPerms: Permissions,
|
||||
requiredPerms: Permissions,
|
||||
): boolean {
|
||||
for (const permName in processPerms) {
|
||||
if (
|
||||
processPerms[permName as keyof Permissions] !==
|
||||
requiredPerms[permName as keyof Permissions]
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export const permissionCombinations: Map<string, Permissions> = new Map();
|
||||
|
||||
function permToString(perms: Permissions): string {
|
||||
const r = perms.read ? 1 : 0;
|
||||
const w = perms.write ? 1 : 0;
|
||||
const n = perms.net ? 1 : 0;
|
||||
const e = perms.env ? 1 : 0;
|
||||
const u = perms.run ? 1 : 0;
|
||||
const p = perms.plugin ? 1 : 0;
|
||||
const h = perms.hrtime ? 1 : 0;
|
||||
return `permR${r}W${w}N${n}E${e}U${u}P${p}H${h}`;
|
||||
}
|
||||
|
||||
function registerPermCombination(perms: Permissions): void {
|
||||
const key = permToString(perms);
|
||||
if (!permissionCombinations.has(key)) {
|
||||
permissionCombinations.set(key, perms);
|
||||
}
|
||||
}
|
||||
|
||||
export async function registerUnitTests(): Promise<void> {
|
||||
const processPerms = await getProcessPermissions();
|
||||
|
||||
const onlyTests = REGISTERED_UNIT_TESTS.filter(({ only }) => only);
|
||||
const unitTests = onlyTests.length > 0 ? onlyTests : REGISTERED_UNIT_TESTS;
|
||||
for (const unitTestDefinition of unitTests) {
|
||||
if (!permissionsMatch(processPerms, unitTestDefinition.perms)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Deno.test(unitTestDefinition);
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeTestPermissions(perms: UnitTestPermissions): Permissions {
|
||||
return {
|
||||
read: !!perms.read,
|
||||
write: !!perms.write,
|
||||
net: !!perms.net,
|
||||
run: !!perms.run,
|
||||
env: !!perms.env,
|
||||
plugin: !!perms.plugin,
|
||||
hrtime: !!perms.hrtime,
|
||||
};
|
||||
}
|
||||
|
||||
interface UnitTestPermissions {
|
||||
read?: boolean;
|
||||
write?: boolean;
|
||||
|
@ -140,16 +41,8 @@ interface UnitTestOptions {
|
|||
perms?: UnitTestPermissions;
|
||||
}
|
||||
|
||||
interface UnitTestDefinition extends Deno.TestDefinition {
|
||||
ignore: boolean;
|
||||
only: boolean;
|
||||
perms: Permissions;
|
||||
}
|
||||
|
||||
type TestFunction = () => void | Promise<void>;
|
||||
|
||||
export const REGISTERED_UNIT_TESTS: UnitTestDefinition[] = [];
|
||||
|
||||
export function unitTest(fn: TestFunction): void;
|
||||
export function unitTest(options: UnitTestOptions, fn: TestFunction): void;
|
||||
export function unitTest(
|
||||
|
@ -179,188 +72,25 @@ export function unitTest(
|
|||
assert(name, "Missing test function name");
|
||||
}
|
||||
|
||||
const normalizedPerms = normalizeTestPermissions(options.perms || {});
|
||||
registerPermCombination(normalizedPerms);
|
||||
|
||||
const unitTestDefinition: UnitTestDefinition = {
|
||||
const testDefinition: Deno.TestDefinition = {
|
||||
name,
|
||||
fn,
|
||||
ignore: !!options.ignore,
|
||||
only: !!options.only,
|
||||
perms: normalizedPerms,
|
||||
permissions: Object.assign({
|
||||
read: false,
|
||||
write: false,
|
||||
net: false,
|
||||
env: false,
|
||||
run: false,
|
||||
plugin: false,
|
||||
hrtime: false,
|
||||
}, options.perms),
|
||||
};
|
||||
|
||||
REGISTERED_UNIT_TESTS.push(unitTestDefinition);
|
||||
Deno.test(testDefinition);
|
||||
}
|
||||
|
||||
const encoder = new TextEncoder();
|
||||
|
||||
// Replace functions with null, errors with their stack strings, and JSONify.
|
||||
// deno-lint-ignore no-explicit-any
|
||||
function serializeTestMessage(message: any): string {
|
||||
return JSON.stringify({
|
||||
start: message.start && {
|
||||
...message.start,
|
||||
tests: message.start.tests.map((test: Deno.TestDefinition) => ({
|
||||
...test,
|
||||
fn: null,
|
||||
})),
|
||||
},
|
||||
testStart: message.testStart && { ...message.testStart, fn: null },
|
||||
testEnd: message.testEnd && {
|
||||
...message.testEnd,
|
||||
error: String(message.testEnd.error?.stack),
|
||||
},
|
||||
end: message.end && {
|
||||
...message.end,
|
||||
// deno-lint-ignore no-explicit-any
|
||||
results: message.end.results.map((result: any) => ({
|
||||
...result,
|
||||
error: result.error?.stack,
|
||||
})),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function reportToConn(
|
||||
conn: Deno.Conn,
|
||||
// deno-lint-ignore no-explicit-any
|
||||
message: any,
|
||||
): Promise<void> {
|
||||
const line = serializeTestMessage(message);
|
||||
const encodedMsg = encoder.encode(line + (message.end == null ? "\n" : ""));
|
||||
// deno-lint-ignore no-deprecated-deno-api
|
||||
await Deno.writeAll(conn, encodedMsg);
|
||||
if (message.end != null) {
|
||||
conn.closeWrite();
|
||||
}
|
||||
}
|
||||
|
||||
unitTest(function permissionsMatches(): void {
|
||||
assert(
|
||||
permissionsMatch(
|
||||
{
|
||||
read: true,
|
||||
write: false,
|
||||
net: false,
|
||||
env: false,
|
||||
run: false,
|
||||
plugin: false,
|
||||
hrtime: false,
|
||||
},
|
||||
normalizeTestPermissions({ read: true }),
|
||||
),
|
||||
);
|
||||
|
||||
assert(
|
||||
permissionsMatch(
|
||||
{
|
||||
read: false,
|
||||
write: false,
|
||||
net: false,
|
||||
env: false,
|
||||
run: false,
|
||||
plugin: false,
|
||||
hrtime: false,
|
||||
},
|
||||
normalizeTestPermissions({}),
|
||||
),
|
||||
);
|
||||
|
||||
assertEquals(
|
||||
permissionsMatch(
|
||||
{
|
||||
read: false,
|
||||
write: true,
|
||||
net: true,
|
||||
env: true,
|
||||
run: true,
|
||||
plugin: true,
|
||||
hrtime: true,
|
||||
},
|
||||
normalizeTestPermissions({ read: true }),
|
||||
),
|
||||
false,
|
||||
);
|
||||
|
||||
assertEquals(
|
||||
permissionsMatch(
|
||||
{
|
||||
read: true,
|
||||
write: false,
|
||||
net: true,
|
||||
env: false,
|
||||
run: false,
|
||||
plugin: false,
|
||||
hrtime: false,
|
||||
},
|
||||
normalizeTestPermissions({ read: true }),
|
||||
),
|
||||
false,
|
||||
);
|
||||
|
||||
assert(
|
||||
permissionsMatch(
|
||||
{
|
||||
read: true,
|
||||
write: true,
|
||||
net: true,
|
||||
env: true,
|
||||
run: true,
|
||||
plugin: true,
|
||||
hrtime: true,
|
||||
},
|
||||
{
|
||||
read: true,
|
||||
write: true,
|
||||
net: true,
|
||||
env: true,
|
||||
run: true,
|
||||
plugin: true,
|
||||
hrtime: true,
|
||||
},
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
/*
|
||||
* Ensure all unit test files (e.g. xxx_test.ts) are present as imports in
|
||||
* cli/tests/unit/unit_tests.ts as it is easy to miss this out
|
||||
*/
|
||||
unitTest(
|
||||
{ perms: { read: true } },
|
||||
function assertAllUnitTestFilesImported(): void {
|
||||
const directoryTestFiles = [...Deno.readDirSync("./cli/tests/unit/")]
|
||||
.map((k) => k.name)
|
||||
.filter(
|
||||
(file) =>
|
||||
file!.endsWith(".ts") &&
|
||||
!file!.endsWith("unit_tests.ts") &&
|
||||
!file!.endsWith("test_util.ts") &&
|
||||
!file!.endsWith("unit_test_runner.ts"),
|
||||
);
|
||||
const unitTestsFile: Uint8Array = Deno.readFileSync(
|
||||
"./cli/tests/unit/unit_tests.ts",
|
||||
);
|
||||
const importLines = new TextDecoder("utf-8")
|
||||
.decode(unitTestsFile)
|
||||
.split("\n")
|
||||
.filter((line) => line.startsWith("import"));
|
||||
const importedTestFiles = importLines.map(
|
||||
(relativeFilePath) => relativeFilePath.match(/\/([^\/]+)";/)![1],
|
||||
);
|
||||
|
||||
directoryTestFiles.forEach((dirFile) => {
|
||||
if (!importedTestFiles.includes(dirFile!)) {
|
||||
throw new Error(
|
||||
"cil/tests/unit/unit_tests.ts is missing import of test file: cli/js/" +
|
||||
dirFile,
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
export function pathToAbsoluteFileUrl(path: string): URL {
|
||||
path = resolve(path);
|
||||
|
||||
|
|
|
@ -1,319 +0,0 @@
|
|||
#!/usr/bin/env -S deno run --reload --allow-run
|
||||
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
||||
import "./unit_tests.ts";
|
||||
import {
|
||||
colors,
|
||||
fmtPerms,
|
||||
parseArgs,
|
||||
permissionCombinations,
|
||||
Permissions,
|
||||
readLines,
|
||||
REGISTERED_UNIT_TESTS,
|
||||
registerUnitTests,
|
||||
reportToConn,
|
||||
} from "./test_util.ts";
|
||||
|
||||
// @ts-expect-error TypeScript (as of 3.7) does not support indexing namespaces by symbol
|
||||
const internalObj = Deno[Deno.internal];
|
||||
// deno-lint-ignore no-explicit-any
|
||||
const reportToConsole = internalObj.reportToConsole as (message: any) => void;
|
||||
// deno-lint-ignore no-explicit-any
|
||||
const runTests = internalObj.runTests as (options: any) => Promise<any>;
|
||||
|
||||
interface PermissionSetTestResult {
|
||||
perms: Permissions;
|
||||
passed: boolean;
|
||||
// deno-lint-ignore no-explicit-any
|
||||
endMessage: any;
|
||||
permsStr: string;
|
||||
}
|
||||
|
||||
const PERMISSIONS: Deno.PermissionName[] = [
|
||||
"read",
|
||||
"write",
|
||||
"net",
|
||||
"env",
|
||||
"run",
|
||||
"plugin",
|
||||
"hrtime",
|
||||
];
|
||||
|
||||
/**
|
||||
* Take a list of permissions and revoke missing permissions.
|
||||
*/
|
||||
async function dropWorkerPermissions(
|
||||
requiredPermissions: Deno.PermissionName[],
|
||||
): Promise<void> {
|
||||
const permsToDrop = PERMISSIONS.filter((p): boolean => {
|
||||
return !requiredPermissions.includes(p);
|
||||
});
|
||||
|
||||
for (const perm of permsToDrop) {
|
||||
await Deno.permissions.revoke({ name: perm });
|
||||
}
|
||||
}
|
||||
|
||||
async function workerRunnerMain(
|
||||
addrStr: string,
|
||||
permsStr: string,
|
||||
filter?: string,
|
||||
): Promise<void> {
|
||||
const [hostname, port] = addrStr.split(":");
|
||||
const addr = { hostname, port: Number(port) };
|
||||
|
||||
let perms: Deno.PermissionName[] = [];
|
||||
if (permsStr.length > 0) {
|
||||
perms = permsStr.split(",") as Deno.PermissionName[];
|
||||
}
|
||||
// Setup reporter
|
||||
const conn = await Deno.connect(addr);
|
||||
// Drop current process permissions to requested set
|
||||
await dropWorkerPermissions(perms);
|
||||
// Register unit tests that match process permissions
|
||||
await registerUnitTests();
|
||||
// Execute tests
|
||||
await runTests({
|
||||
exitOnFail: false,
|
||||
filter,
|
||||
reportToConsole: false,
|
||||
onMessage: reportToConn.bind(null, conn),
|
||||
});
|
||||
}
|
||||
|
||||
function spawnWorkerRunner(
|
||||
verbose: boolean,
|
||||
addr: string,
|
||||
perms: Permissions,
|
||||
filter?: string,
|
||||
): Deno.Process {
|
||||
// run subsequent tests using same deno executable
|
||||
const permStr = Object.keys(perms)
|
||||
.filter((permName): boolean => {
|
||||
return perms[permName as Deno.PermissionName] === true;
|
||||
})
|
||||
.join(",");
|
||||
|
||||
const cmd = [
|
||||
Deno.execPath(),
|
||||
"run",
|
||||
"--unstable", // TODO(ry) be able to test stable vs unstable
|
||||
"--location=http://js-unit-tests/foo/bar",
|
||||
"-A",
|
||||
"cli/tests/unit/unit_test_runner.ts",
|
||||
"--worker",
|
||||
`--addr=${addr}`,
|
||||
`--perms=${permStr}`,
|
||||
];
|
||||
|
||||
if (filter) {
|
||||
cmd.push("--");
|
||||
cmd.push(filter);
|
||||
}
|
||||
|
||||
const ioMode = verbose ? "inherit" : "null";
|
||||
|
||||
const p = Deno.run({
|
||||
cmd,
|
||||
stdin: ioMode,
|
||||
stdout: ioMode,
|
||||
stderr: ioMode,
|
||||
});
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
async function runTestsForPermissionSet(
|
||||
listener: Deno.Listener,
|
||||
addrStr: string,
|
||||
verbose: boolean,
|
||||
perms: Permissions,
|
||||
filter?: string,
|
||||
): Promise<PermissionSetTestResult> {
|
||||
const permsFmt = fmtPerms(perms);
|
||||
console.log(`Running tests for: ${permsFmt}`);
|
||||
const workerProcess = spawnWorkerRunner(verbose, addrStr, perms, filter);
|
||||
// Wait for worker subprocess to go online
|
||||
const conn = await listener.accept();
|
||||
|
||||
let expectedPassedTests;
|
||||
// deno-lint-ignore no-explicit-any
|
||||
let endMessage: any;
|
||||
|
||||
try {
|
||||
for await (const line of readLines(conn)) {
|
||||
// deno-lint-ignore no-explicit-any
|
||||
const message = JSON.parse(line) as any;
|
||||
reportToConsole(message);
|
||||
if (message.start != null) {
|
||||
expectedPassedTests = message.start.tests.length;
|
||||
} else if (message.end != null) {
|
||||
endMessage = message.end;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
// Close socket to worker.
|
||||
conn.close();
|
||||
}
|
||||
|
||||
if (expectedPassedTests == null) {
|
||||
throw new Error("Worker runner didn't report start");
|
||||
}
|
||||
|
||||
if (endMessage == null) {
|
||||
throw new Error("Worker runner didn't report end");
|
||||
}
|
||||
|
||||
const workerStatus = await workerProcess.status();
|
||||
if (!workerStatus.success) {
|
||||
throw new Error(
|
||||
`Worker runner exited with status code: ${workerStatus.code}`,
|
||||
);
|
||||
}
|
||||
|
||||
workerProcess.close();
|
||||
|
||||
const passed = expectedPassedTests === endMessage.passed + endMessage.ignored;
|
||||
|
||||
return {
|
||||
perms,
|
||||
passed,
|
||||
permsStr: permsFmt,
|
||||
endMessage,
|
||||
};
|
||||
}
|
||||
|
||||
async function masterRunnerMain(
|
||||
verbose: boolean,
|
||||
filter?: string,
|
||||
): Promise<void> {
|
||||
console.log(
|
||||
"Discovered permission combinations for tests:",
|
||||
permissionCombinations.size,
|
||||
);
|
||||
|
||||
for (const perms of permissionCombinations.values()) {
|
||||
console.log("\t" + fmtPerms(perms));
|
||||
}
|
||||
|
||||
const testResults = new Set<PermissionSetTestResult>();
|
||||
const addr = { hostname: "127.0.0.1", port: 4510 };
|
||||
const addrStr = `${addr.hostname}:${addr.port}`;
|
||||
const listener = Deno.listen(addr);
|
||||
|
||||
for (const perms of permissionCombinations.values()) {
|
||||
const result = await runTestsForPermissionSet(
|
||||
listener,
|
||||
addrStr,
|
||||
verbose,
|
||||
perms,
|
||||
filter,
|
||||
);
|
||||
testResults.add(result);
|
||||
}
|
||||
|
||||
// if any run tests returned non-zero status then whole test
|
||||
// run should fail
|
||||
let testsPassed = true;
|
||||
|
||||
for (const testResult of testResults) {
|
||||
const { permsStr, endMessage } = testResult;
|
||||
console.log(`Summary for ${permsStr}`);
|
||||
reportToConsole({ end: endMessage });
|
||||
testsPassed = testsPassed && testResult.passed;
|
||||
}
|
||||
|
||||
if (!testsPassed) {
|
||||
console.error("Unit tests failed");
|
||||
Deno.exit(1);
|
||||
}
|
||||
|
||||
console.log("Unit tests passed");
|
||||
|
||||
if (REGISTERED_UNIT_TESTS.find(({ only }) => only)) {
|
||||
console.error(
|
||||
`\n${colors.red("FAILED")} because the "only" option was used`,
|
||||
);
|
||||
Deno.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
const HELP = `Unit test runner
|
||||
|
||||
Run tests matching current process permissions:
|
||||
|
||||
deno --allow-write unit_test_runner.ts
|
||||
|
||||
deno --allow-net --allow-hrtime unit_test_runner.ts
|
||||
|
||||
deno --allow-write unit_test_runner.ts -- testWriteFile
|
||||
|
||||
Run "master" process that creates "worker" processes
|
||||
for each discovered permission combination:
|
||||
|
||||
deno -A unit_test_runner.ts --master
|
||||
|
||||
Run worker process for given permissions:
|
||||
|
||||
deno -A unit_test_runner.ts --worker --perms=net,read,write --addr=127.0.0.1:4500
|
||||
|
||||
|
||||
OPTIONS:
|
||||
--master
|
||||
Run in master mode, spawning worker processes for
|
||||
each discovered permission combination
|
||||
|
||||
--worker
|
||||
Run in worker mode, requires "perms" and "addr" flags,
|
||||
should be run with "-A" flag; after setup worker will
|
||||
drop permissions to required set specified in "perms"
|
||||
|
||||
--perms=<perm_name>...
|
||||
Set of permissions this process should run tests with,
|
||||
|
||||
--addr=<addr>
|
||||
Address of TCP socket for reporting
|
||||
|
||||
ARGS:
|
||||
-- <filter>...
|
||||
Run only tests with names matching filter, must
|
||||
be used after "--"
|
||||
`;
|
||||
|
||||
function assertOrHelp(expr: unknown): asserts expr {
|
||||
if (!expr) {
|
||||
console.log(HELP);
|
||||
Deno.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
async function main(): Promise<void> {
|
||||
const args = parseArgs(Deno.args, {
|
||||
boolean: ["master", "worker", "verbose"],
|
||||
"--": true,
|
||||
});
|
||||
|
||||
if (args.help) {
|
||||
console.log(HELP);
|
||||
return;
|
||||
}
|
||||
|
||||
const filter = args["--"][0];
|
||||
|
||||
// Master mode
|
||||
if (args.master) {
|
||||
return masterRunnerMain(args.verbose, filter);
|
||||
}
|
||||
|
||||
// Worker mode
|
||||
if (args.worker) {
|
||||
assertOrHelp(typeof args.addr === "string");
|
||||
assertOrHelp(typeof args.perms === "string");
|
||||
return workerRunnerMain(args.addr, args.perms, filter);
|
||||
}
|
||||
|
||||
// Running tests matching current process permissions
|
||||
await registerUnitTests();
|
||||
await runTests({ filter });
|
||||
}
|
||||
|
||||
main();
|
|
@ -1,77 +0,0 @@
|
|||
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
// This test is executed as part of unit test suite.
|
||||
//
|
||||
// Test runner automatically spawns subprocesses for each required permissions combination.
|
||||
|
||||
import "./abort_controller_test.ts";
|
||||
import "./blob_test.ts";
|
||||
import "./body_test.ts";
|
||||
import "./buffer_test.ts";
|
||||
import "./build_test.ts";
|
||||
import "./chmod_test.ts";
|
||||
import "./chown_test.ts";
|
||||
import "./console_test.ts";
|
||||
import "./copy_file_test.ts";
|
||||
import "./custom_event_test.ts";
|
||||
import "./dir_test.ts";
|
||||
import "./opcall_test.ts";
|
||||
import "./error_stack_test.ts";
|
||||
import "./event_test.ts";
|
||||
import "./event_target_test.ts";
|
||||
import "./fetch_test.ts";
|
||||
import "./file_test.ts";
|
||||
import "./filereader_test.ts";
|
||||
import "./files_test.ts";
|
||||
import "./filter_function_test.ts";
|
||||
import "./format_error_test.ts";
|
||||
import "./fs_events_test.ts";
|
||||
import "./get_random_values_test.ts";
|
||||
import "./globals_test.ts";
|
||||
import "./headers_test.ts";
|
||||
import "./http_test.ts";
|
||||
import "./internals_test.ts";
|
||||
import "./io_test.ts";
|
||||
import "./link_test.ts";
|
||||
import "./make_temp_test.ts";
|
||||
import "./metrics_test.ts";
|
||||
import "./mkdir_test.ts";
|
||||
import "./net_test.ts";
|
||||
import "./os_test.ts";
|
||||
import "./permissions_test.ts";
|
||||
import "./path_from_url_test.ts";
|
||||
import "./process_test.ts";
|
||||
import "./progressevent_test.ts";
|
||||
import "./real_path_test.ts";
|
||||
import "./read_dir_test.ts";
|
||||
import "./read_text_file_test.ts";
|
||||
import "./read_file_test.ts";
|
||||
import "./read_link_test.ts";
|
||||
import "./remove_test.ts";
|
||||
import "./rename_test.ts";
|
||||
import "./request_test.ts";
|
||||
import "./resources_test.ts";
|
||||
import "./response_test.ts";
|
||||
import "./signal_test.ts";
|
||||
import "./stat_test.ts";
|
||||
import "./stdio_test.ts";
|
||||
import "./streams_deprecated.ts";
|
||||
import "./symlink_test.ts";
|
||||
import "./sync_test.ts";
|
||||
import "./text_encoding_test.ts";
|
||||
import "./testing_test.ts";
|
||||
import "./timers_test.ts";
|
||||
import "./tls_test.ts";
|
||||
import "./truncate_test.ts";
|
||||
import "./tty_test.ts";
|
||||
import "./umask_test.ts";
|
||||
import "./url_test.ts";
|
||||
import "./url_search_params_test.ts";
|
||||
import "./utime_test.ts";
|
||||
import "./worker_types.ts";
|
||||
import "./write_file_test.ts";
|
||||
import "./write_text_file_test.ts";
|
||||
import "./performance_test.ts";
|
||||
import "./version_test.ts";
|
||||
import "./websocket_test.ts";
|
||||
import "./webgpu_test.ts";
|
|
@ -179,10 +179,11 @@ unitTest({
|
|||
});
|
||||
|
||||
const encoder = device.createCommandEncoder();
|
||||
const view = texture.createView();
|
||||
const renderPass = encoder.beginRenderPass({
|
||||
colorAttachments: [
|
||||
{
|
||||
view: texture.createView(),
|
||||
view,
|
||||
storeOp: "store",
|
||||
loadValue: [0, 1, 0, 1],
|
||||
},
|
||||
|
@ -204,7 +205,8 @@ unitTest({
|
|||
dimensions,
|
||||
);
|
||||
|
||||
device.queue.submit([encoder.finish()]);
|
||||
const bundle = encoder.finish();
|
||||
device.queue.submit([bundle]);
|
||||
|
||||
await outputBuffer.mapAsync(1);
|
||||
const data = new Uint8Array(outputBuffer.getMappedRange());
|
||||
|
|
Loading…
Add table
Reference in a new issue