diff --git a/js/compiler_test.ts b/js/compiler_test.ts index 8960112de4..3add3be95c 100644 --- a/js/compiler_test.ts +++ b/js/compiler_test.ts @@ -1,5 +1,5 @@ // 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 ts from "typescript"; diff --git a/js/console_test.ts b/js/console_test.ts index 3efe08dc9c..d38974c663 100644 --- a/js/console_test.ts +++ b/js/console_test.ts @@ -1,6 +1,6 @@ // 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"; // tslint:disable-next-line:no-any diff --git a/js/test_util.ts b/js/test_util.ts new file mode 100644 index 0000000000..7124222a79 --- /dev/null +++ b/js/test_util.ts @@ -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); +}); diff --git a/js/testing/testing.ts b/js/testing/testing.ts index 828ebec2f0..b172688b7b 100644 --- a/js/testing/testing.ts +++ b/js/testing/testing.ts @@ -24,22 +24,14 @@ export interface TestDefinition { export const exitOnFail = true; -/* A subset of the tests can be ran by providing a filter expression. - * 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; +let filterRegExp: RegExp | null; 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 { const fn: TestFunction = typeof t === "function" ? t : t.fn; const name: string = t.name; diff --git a/js/unit_tests.ts b/js/unit_tests.ts index bbe93f5e1e..17ddd52567 100644 --- a/js/unit_tests.ts +++ b/js/unit_tests.ts @@ -3,8 +3,7 @@ // But it can also be run manually: // ./deno tests.ts -import { test, assert, assertEqual } from "./testing/testing.ts"; -import { readFileSync } from "deno"; +import { test, testPerm, assert, assertEqual } from "./test_util.ts"; import * as deno from "deno"; import "./compiler_test.ts"; @@ -15,7 +14,7 @@ test(async function tests_test() { }); test(async function tests_readFileSync() { - const data = readFileSync("package.json"); + const data = deno.readFileSync("package.json"); if (!data.byteLength) { throw Error( `Expected positive value for data.byteLength ${data.byteLength}` @@ -32,7 +31,7 @@ test(function tests_readFileSync_NotFound() { let caughtError = false; let data; try { - data = readFileSync("bad_filename"); + data = deno.readFileSync("bad_filename"); } catch (e) { caughtError = true; assert(e instanceof deno.NotFound); @@ -48,14 +47,14 @@ test(function writeFileSyncSuccess() { const dataWritten = enc.encode("Hello"); const filename = "TEMPDIR/test.txt"; deno.writeFileSync(filename, dataWritten, 0o666); - const dataRead = readFileSync(filename); + const dataRead = deno.readFileSync(filename); assertEqual(dataRead, dataWritten); }); */ // For this test to pass we need --allow-write permission. // Otherwise it will fail with deno.PermissionDenied instead of deno.NotFound. -test(function writeFileSyncFail() { +testPerm({ write: true }, function writeFileSyncFail() { const enc = new TextEncoder(); const data = enc.encode("Hello"); const filename = "/baddir/test.txt"; @@ -71,7 +70,7 @@ test(function writeFileSyncFail() { assert(caughtError); }); -test(async function tests_fetch() { +testPerm({ net: true }, async function tests_fetch() { const response = await fetch("http://localhost:4545/package.json"); const json = await response.json(); assertEqual(json.name, "deno"); @@ -84,7 +83,7 @@ test(async function tests_writeFileSync() { // TODO need ability to get tmp dir. const fn = "/tmp/test.txt"; 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 actual = dec.decode(dataRead); assertEqual("Hello", actual); diff --git a/tools/test.py b/tools/test.py index 12582f83fe..6e5cb548b9 100755 --- a/tools/test.py +++ b/tools/test.py @@ -5,6 +5,7 @@ import os import sys from check_output_test import check_output_test from util import executable_suffix, run, build_path +from unit_tests import unit_tests from util_test import util_test import subprocess import http_server @@ -41,7 +42,7 @@ def main(argv): deno_exe = os.path.join(build_dir, "deno" + executable_suffix) check_exists(deno_exe) - run([deno_exe, "js/unit_tests.ts", "--allow-write"]) + unit_tests(deno_exe) check_exists(deno_exe) check_output_test(deno_exe) diff --git a/tools/unit_tests.py b/tools/unit_tests.py new file mode 100755 index 0000000000..a2cfa33b6d --- /dev/null +++ b/tools/unit_tests.py @@ -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])