mirror of
https://github.com/denoland/deno.git
synced 2024-11-25 15:29:32 -05:00
Add ability to unit test by permissions.
This commit is contained in:
parent
722c7e4a1b
commit
e13f3c10ca
7 changed files with 113 additions and 25 deletions
|
@ -1,5 +1,5 @@
|
||||||
// Copyright 2018 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018 the Deno authors. All rights reserved. MIT license.
|
||||||
import { test, assert, assertEqual } from "./testing/testing.ts";
|
import { test, assert, assertEqual } from "./test_util.ts";
|
||||||
import * as compiler from "compiler";
|
import * as compiler from "compiler";
|
||||||
import * as ts from "typescript";
|
import * as ts from "typescript";
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Copyright 2018 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
import { test, assert, assertEqual } from "./testing/testing.ts";
|
import { test, assert, assertEqual } from "./test_util.ts";
|
||||||
import { stringifyArgs } from "./console.ts";
|
import { stringifyArgs } from "./console.ts";
|
||||||
|
|
||||||
// tslint:disable-next-line:no-any
|
// tslint:disable-next-line:no-any
|
||||||
|
|
70
js/test_util.ts
Normal file
70
js/test_util.ts
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
// Copyright 2018 the Deno authors. All rights reserved. MIT license.
|
||||||
|
//
|
||||||
|
// We want to test many ops in deno which have different behavior depending on
|
||||||
|
// the permissions set. These tests can specify which permissions they expect,
|
||||||
|
// which appends a special string like "permW1N0" to the end of the test name.
|
||||||
|
// Here we run several copies of deno with different permissions, filtering the
|
||||||
|
// tests by the special string. permW0N0 means allow-write but not allow-net.
|
||||||
|
// See tools/unit_tests.py for more details.
|
||||||
|
|
||||||
|
import * as deno from "deno";
|
||||||
|
import * as testing from "./testing/testing.ts";
|
||||||
|
export { assert, assertEqual } from "./testing/testing.ts";
|
||||||
|
|
||||||
|
// testing.setFilter must be run before any tests are defined.
|
||||||
|
const permFilter = deno.argv[1];
|
||||||
|
permFromString(permFilter);
|
||||||
|
testing.setFilter(permFilter);
|
||||||
|
|
||||||
|
interface DenoPermissions {
|
||||||
|
write?: boolean;
|
||||||
|
net?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
function permToString(perms: DenoPermissions): string {
|
||||||
|
const w = perms.write ? 1 : 0;
|
||||||
|
const n = perms.net ? 1 : 0;
|
||||||
|
return `permW${w}N${n}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function permFromString(s: string): DenoPermissions {
|
||||||
|
const re = /^permW([01])N([01])$/;
|
||||||
|
const found = s.match(re);
|
||||||
|
if (!found) {
|
||||||
|
throw Error("Not a permission string");
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
write: Boolean(Number(found[1])),
|
||||||
|
net: Boolean(Number(found[2]))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function testPerm(perms: DenoPermissions, fn: testing.TestFunction) {
|
||||||
|
const name = `${fn.name}_${permToString(perms)}`;
|
||||||
|
testing.test({ fn, name });
|
||||||
|
}
|
||||||
|
|
||||||
|
export function test(fn: testing.TestFunction) {
|
||||||
|
testPerm({ write: false, net: false }, fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
test(function permSerialization() {
|
||||||
|
for (let write of [true, false]) {
|
||||||
|
for (let net of [true, false]) {
|
||||||
|
let perms: DenoPermissions = { write, net };
|
||||||
|
testing.assertEqual(perms, permFromString(permToString(perms)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// To better catch internal errors, permFromString should throw if it gets an
|
||||||
|
// invalid permission string.
|
||||||
|
test(function permFromStringThrows() {
|
||||||
|
let threw = false;
|
||||||
|
try {
|
||||||
|
permFromString("bad");
|
||||||
|
} catch (e) {
|
||||||
|
threw = true;
|
||||||
|
}
|
||||||
|
testing.assert(threw);
|
||||||
|
});
|
|
@ -24,22 +24,14 @@ export interface TestDefinition {
|
||||||
|
|
||||||
export const exitOnFail = true;
|
export const exitOnFail = true;
|
||||||
|
|
||||||
/* A subset of the tests can be ran by providing a filter expression.
|
let filterRegExp: RegExp | null;
|
||||||
* In Node.js the filter is specified on the command line:
|
|
||||||
*
|
|
||||||
* ts-node test_node log # all tests with 'log' in the name
|
|
||||||
* ts-node test_node ^util # tests starting with 'util'
|
|
||||||
*
|
|
||||||
* In the browser, the filter is specified as part of the url:
|
|
||||||
*
|
|
||||||
* http://localhost:9876/test.html#script=some/script.js&filter=log
|
|
||||||
* http://localhost:9876/test.html#script=some/script.js&filter=^util
|
|
||||||
*/
|
|
||||||
let filterExpr: string = null;
|
|
||||||
|
|
||||||
const filterRegExp = filterExpr ? new RegExp(filterExpr, "i") : null;
|
|
||||||
const tests: TestDefinition[] = [];
|
const tests: TestDefinition[] = [];
|
||||||
|
|
||||||
|
// Must be called before any test() that needs to be filtered.
|
||||||
|
export function setFilter(s: string): void {
|
||||||
|
filterRegExp = new RegExp(s, "i");
|
||||||
|
}
|
||||||
|
|
||||||
export function test(t: TestDefinition | TestFunction): void {
|
export function test(t: TestDefinition | TestFunction): void {
|
||||||
const fn: TestFunction = typeof t === "function" ? t : t.fn;
|
const fn: TestFunction = typeof t === "function" ? t : t.fn;
|
||||||
const name: string = t.name;
|
const name: string = t.name;
|
||||||
|
|
|
@ -3,8 +3,7 @@
|
||||||
// But it can also be run manually:
|
// But it can also be run manually:
|
||||||
// ./deno tests.ts
|
// ./deno tests.ts
|
||||||
|
|
||||||
import { test, assert, assertEqual } from "./testing/testing.ts";
|
import { test, testPerm, assert, assertEqual } from "./test_util.ts";
|
||||||
import { readFileSync } from "deno";
|
|
||||||
import * as deno from "deno";
|
import * as deno from "deno";
|
||||||
|
|
||||||
import "./compiler_test.ts";
|
import "./compiler_test.ts";
|
||||||
|
@ -15,7 +14,7 @@ test(async function tests_test() {
|
||||||
});
|
});
|
||||||
|
|
||||||
test(async function tests_readFileSync() {
|
test(async function tests_readFileSync() {
|
||||||
const data = readFileSync("package.json");
|
const data = deno.readFileSync("package.json");
|
||||||
if (!data.byteLength) {
|
if (!data.byteLength) {
|
||||||
throw Error(
|
throw Error(
|
||||||
`Expected positive value for data.byteLength ${data.byteLength}`
|
`Expected positive value for data.byteLength ${data.byteLength}`
|
||||||
|
@ -32,7 +31,7 @@ test(function tests_readFileSync_NotFound() {
|
||||||
let caughtError = false;
|
let caughtError = false;
|
||||||
let data;
|
let data;
|
||||||
try {
|
try {
|
||||||
data = readFileSync("bad_filename");
|
data = deno.readFileSync("bad_filename");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
caughtError = true;
|
caughtError = true;
|
||||||
assert(e instanceof deno.NotFound);
|
assert(e instanceof deno.NotFound);
|
||||||
|
@ -48,14 +47,14 @@ test(function writeFileSyncSuccess() {
|
||||||
const dataWritten = enc.encode("Hello");
|
const dataWritten = enc.encode("Hello");
|
||||||
const filename = "TEMPDIR/test.txt";
|
const filename = "TEMPDIR/test.txt";
|
||||||
deno.writeFileSync(filename, dataWritten, 0o666);
|
deno.writeFileSync(filename, dataWritten, 0o666);
|
||||||
const dataRead = readFileSync(filename);
|
const dataRead = deno.readFileSync(filename);
|
||||||
assertEqual(dataRead, dataWritten);
|
assertEqual(dataRead, dataWritten);
|
||||||
});
|
});
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// For this test to pass we need --allow-write permission.
|
// For this test to pass we need --allow-write permission.
|
||||||
// Otherwise it will fail with deno.PermissionDenied instead of deno.NotFound.
|
// Otherwise it will fail with deno.PermissionDenied instead of deno.NotFound.
|
||||||
test(function writeFileSyncFail() {
|
testPerm({ write: true }, function writeFileSyncFail() {
|
||||||
const enc = new TextEncoder();
|
const enc = new TextEncoder();
|
||||||
const data = enc.encode("Hello");
|
const data = enc.encode("Hello");
|
||||||
const filename = "/baddir/test.txt";
|
const filename = "/baddir/test.txt";
|
||||||
|
@ -71,7 +70,7 @@ test(function writeFileSyncFail() {
|
||||||
assert(caughtError);
|
assert(caughtError);
|
||||||
});
|
});
|
||||||
|
|
||||||
test(async function tests_fetch() {
|
testPerm({ net: true }, async function tests_fetch() {
|
||||||
const response = await fetch("http://localhost:4545/package.json");
|
const response = await fetch("http://localhost:4545/package.json");
|
||||||
const json = await response.json();
|
const json = await response.json();
|
||||||
assertEqual(json.name, "deno");
|
assertEqual(json.name, "deno");
|
||||||
|
@ -84,7 +83,7 @@ test(async function tests_writeFileSync() {
|
||||||
// TODO need ability to get tmp dir.
|
// TODO need ability to get tmp dir.
|
||||||
const fn = "/tmp/test.txt";
|
const fn = "/tmp/test.txt";
|
||||||
writeFileSync("/tmp/test.txt", data, 0o666);
|
writeFileSync("/tmp/test.txt", data, 0o666);
|
||||||
const dataRead = readFileSync("/tmp/test.txt");
|
const dataRead = deno.readFileSync("/tmp/test.txt");
|
||||||
const dec = new TextDecoder("utf-8");
|
const dec = new TextDecoder("utf-8");
|
||||||
const actual = dec.decode(dataRead);
|
const actual = dec.decode(dataRead);
|
||||||
assertEqual("Hello", actual);
|
assertEqual("Hello", actual);
|
||||||
|
|
|
@ -5,6 +5,7 @@ import os
|
||||||
import sys
|
import sys
|
||||||
from check_output_test import check_output_test
|
from check_output_test import check_output_test
|
||||||
from util import executable_suffix, run, build_path
|
from util import executable_suffix, run, build_path
|
||||||
|
from unit_tests import unit_tests
|
||||||
from util_test import util_test
|
from util_test import util_test
|
||||||
import subprocess
|
import subprocess
|
||||||
import http_server
|
import http_server
|
||||||
|
@ -41,7 +42,7 @@ def main(argv):
|
||||||
|
|
||||||
deno_exe = os.path.join(build_dir, "deno" + executable_suffix)
|
deno_exe = os.path.join(build_dir, "deno" + executable_suffix)
|
||||||
check_exists(deno_exe)
|
check_exists(deno_exe)
|
||||||
run([deno_exe, "js/unit_tests.ts", "--allow-write"])
|
unit_tests(deno_exe)
|
||||||
|
|
||||||
check_exists(deno_exe)
|
check_exists(deno_exe)
|
||||||
check_output_test(deno_exe)
|
check_output_test(deno_exe)
|
||||||
|
|
26
tools/unit_tests.py
Executable file
26
tools/unit_tests.py
Executable file
|
@ -0,0 +1,26 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
from util import run
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
# We want to test many ops in deno which have different behavior depending on
|
||||||
|
# the permissions set. These tests can specify which permissions they expect,
|
||||||
|
# which appends a special string like "permW1N0" to the end of the test name.
|
||||||
|
# Here we run several copies of deno with different permissions, filtering the
|
||||||
|
# tests by the special string. permW0N0 means allow-write but not allow-net.
|
||||||
|
# See js/test_util.ts for more details.
|
||||||
|
def unit_tests(deno_exe):
|
||||||
|
run([deno_exe, "js/unit_tests.ts", "permW0N0"])
|
||||||
|
run([deno_exe, "js/unit_tests.ts", "permW1N0", "--allow-write"])
|
||||||
|
run([deno_exe, "js/unit_tests.ts", "permW0N1", "--allow-net"])
|
||||||
|
run([
|
||||||
|
deno_exe, "js/unit_tests.ts", "permW1N1", "--allow-write",
|
||||||
|
"--allow-net"
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
print "Usage ./tools/unit_tests.py out/debug/deno"
|
||||||
|
sys.exit(1)
|
||||||
|
unit_tests(sys.argv[1])
|
Loading…
Reference in a new issue