diff options
author | Matt Mastracci <matthew@mastracci.com> | 2024-02-10 13:22:13 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-10 20:22:13 +0000 |
commit | f5e46c9bf2f50d66a953fa133161fc829cecff06 (patch) | |
tree | 8faf2f5831c1c7b11d842cd9908d141082c869a5 /cli/tests/unit/command_test.ts | |
parent | d2477f780630a812bfd65e3987b70c0d309385bb (diff) |
chore: move cli/tests/ -> tests/ (#22369)
This looks like a massive PR, but it's only a move from cli/tests ->
tests, and updates of relative paths for files.
This is the first step towards aggregate all of the integration test
files under tests/, which will lead to a set of integration tests that
can run without the CLI binary being built.
While we could leave these tests under `cli`, it would require us to
keep a more complex directory structure for the various test runners. In
addition, we have a lot of complexity to ignore various test files in
the `cli` project itself (cargo publish exclusion rules, autotests =
false, etc).
And finally, the `tests/` folder will eventually house the `test_ffi`,
`test_napi` and other testing code, reducing the size of the root repo
directory.
For easier review, the extremely large and noisy "move" is in the first
commit (with no changes -- just a move), while the remainder of the
changes to actual files is in the second commit.
Diffstat (limited to 'cli/tests/unit/command_test.ts')
-rw-r--r-- | cli/tests/unit/command_test.ts | 967 |
1 files changed, 0 insertions, 967 deletions
diff --git a/cli/tests/unit/command_test.ts b/cli/tests/unit/command_test.ts deleted file mode 100644 index cbb1c4921..000000000 --- a/cli/tests/unit/command_test.ts +++ /dev/null @@ -1,967 +0,0 @@ -// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. - -import { - assert, - assertEquals, - assertRejects, - assertStringIncludes, - assertThrows, -} from "./test_util.ts"; - -Deno.test( - { permissions: { write: true, run: true, read: true } }, - async function commandWithCwdIsAsync() { - const enc = new TextEncoder(); - const cwd = await Deno.makeTempDir({ prefix: "deno_command_test" }); - - const exitCodeFile = "deno_was_here"; - const programFile = "poll_exit.ts"; - const program = ` -async function tryExit() { - try { - const code = parseInt(await Deno.readTextFile("${exitCodeFile}")); - Deno.exit(code); - } catch { - // Retry if we got here before deno wrote the file. - setTimeout(tryExit, 0.01); - } -} - -tryExit(); -`; - - Deno.writeFileSync(`${cwd}/${programFile}`, enc.encode(program)); - - const command = new Deno.Command(Deno.execPath(), { - cwd, - args: ["run", "--allow-read", programFile], - stdout: "inherit", - stderr: "inherit", - }); - const child = command.spawn(); - - // Write the expected exit code *after* starting deno. - // This is how we verify that `Child` is actually asynchronous. - const code = 84; - Deno.writeFileSync(`${cwd}/${exitCodeFile}`, enc.encode(`${code}`)); - - const status = await child.status; - await Deno.remove(cwd, { recursive: true }); - assertEquals(status.success, false); - assertEquals(status.code, code); - assertEquals(status.signal, null); - }, -); - -Deno.test( - { permissions: { run: true, read: true } }, - async function commandStdinPiped() { - const command = new Deno.Command(Deno.execPath(), { - args: [ - "eval", - "if (new TextDecoder().decode(await Deno.readAll(Deno.stdin)) !== 'hello') throw new Error('Expected \\'hello\\'')", - ], - stdin: "piped", - stdout: "null", - stderr: "null", - }); - const child = command.spawn(); - - assertThrows(() => child.stdout, TypeError, "stdout is not piped"); - assertThrows(() => child.stderr, TypeError, "stderr is not piped"); - - const msg = new TextEncoder().encode("hello"); - const writer = child.stdin.getWriter(); - await writer.write(msg); - writer.releaseLock(); - - await child.stdin.close(); - const status = await child.status; - assertEquals(status.success, true); - assertEquals(status.code, 0); - assertEquals(status.signal, null); - }, -); - -Deno.test( - { permissions: { run: true, read: true } }, - async function commandStdinPiped() { - const command = new Deno.Command(Deno.execPath(), { - args: ["info"], - stdout: "null", - stderr: "null", - }); - const child = command.spawn(); - - assertThrows(() => child.stdin, TypeError, "stdin is not piped"); - assertThrows(() => child.stdout, TypeError, "stdout is not piped"); - assertThrows(() => child.stderr, TypeError, "stderr is not piped"); - - await child.status; - }, -); - -Deno.test( - { permissions: { run: true, read: true } }, - async function commandStdoutPiped() { - const command = new Deno.Command(Deno.execPath(), { - args: [ - "eval", - "await Deno.stdout.write(new TextEncoder().encode('hello'))", - ], - stderr: "null", - stdout: "piped", - }); - const child = command.spawn(); - - assertThrows(() => child.stdin, TypeError, "stdin is not piped"); - assertThrows(() => child.stderr, TypeError, "stderr is not piped"); - - const readable = child.stdout.pipeThrough(new TextDecoderStream()); - const reader = readable.getReader(); - const res = await reader.read(); - assert(!res.done); - assertEquals(res.value, "hello"); - - const resEnd = await reader.read(); - assert(resEnd.done); - assertEquals(resEnd.value, undefined); - reader.releaseLock(); - - const status = await child.status; - assertEquals(status.success, true); - assertEquals(status.code, 0); - assertEquals(status.signal, null); - }, -); - -Deno.test( - { permissions: { run: true, read: true } }, - async function commandStderrPiped() { - const command = new Deno.Command(Deno.execPath(), { - args: [ - "eval", - "await Deno.stderr.write(new TextEncoder().encode('hello'))", - ], - stdout: "null", - stderr: "piped", - }); - const child = command.spawn(); - - assertThrows(() => child.stdin, TypeError, "stdin is not piped"); - assertThrows(() => child.stdout, TypeError, "stdout is not piped"); - - const readable = child.stderr.pipeThrough(new TextDecoderStream()); - const reader = readable.getReader(); - const res = await reader.read(); - assert(!res.done); - assertEquals(res.value, "hello"); - - const resEnd = await reader.read(); - assert(resEnd.done); - assertEquals(resEnd.value, undefined); - reader.releaseLock(); - - const status = await child.status; - assertEquals(status.success, true); - assertEquals(status.code, 0); - assertEquals(status.signal, null); - }, -); - -Deno.test( - { permissions: { run: true, write: true, read: true } }, - async function commandRedirectStdoutStderr() { - const tempDir = await Deno.makeTempDir(); - const fileName = tempDir + "/redirected_stdio.txt"; - const file = await Deno.open(fileName, { - create: true, - write: true, - }); - - const command = new Deno.Command(Deno.execPath(), { - args: [ - "eval", - "Deno.stderr.write(new TextEncoder().encode('error\\n')); Deno.stdout.write(new TextEncoder().encode('output\\n'));", - ], - stdout: "piped", - stderr: "piped", - }); - const child = command.spawn(); - await child.stdout.pipeTo(file.writable, { - preventClose: true, - }); - await child.stderr.pipeTo(file.writable); - await child.status; - - const fileContents = await Deno.readFile(fileName); - const decoder = new TextDecoder(); - const text = decoder.decode(fileContents); - - assertStringIncludes(text, "error"); - assertStringIncludes(text, "output"); - }, -); - -Deno.test( - { permissions: { run: true, write: true, read: true } }, - async function commandRedirectStdin() { - const tempDir = await Deno.makeTempDir(); - const fileName = tempDir + "/redirected_stdio.txt"; - await Deno.writeTextFile(fileName, "hello"); - const file = await Deno.open(fileName); - - const command = new Deno.Command(Deno.execPath(), { - args: [ - "eval", - "if (new TextDecoder().decode(await Deno.readAll(Deno.stdin)) !== 'hello') throw new Error('Expected \\'hello\\'')", - ], - stdin: "piped", - stdout: "null", - stderr: "null", - }); - const child = command.spawn(); - await file.readable.pipeTo(child.stdin, { - preventClose: true, - }); - - await child.stdin.close(); - const status = await child.status; - assertEquals(status.code, 0); - }, -); - -Deno.test( - { permissions: { run: true, read: true } }, - async function commandKillSuccess() { - const command = new Deno.Command(Deno.execPath(), { - args: ["eval", "setTimeout(() => {}, 10000)"], - stdout: "null", - stderr: "null", - }); - const child = command.spawn(); - - child.kill("SIGKILL"); - const status = await child.status; - - assertEquals(status.success, false); - if (Deno.build.os === "windows") { - assertEquals(status.code, 1); - assertEquals(status.signal, null); - } else { - assertEquals(status.code, 137); - assertEquals(status.signal, "SIGKILL"); - } - }, -); - -Deno.test( - { permissions: { run: true, read: true } }, - // deno lint bug, see https://github.com/denoland/deno_lint/issues/1206 - // deno-lint-ignore require-await - async function childProcessExplicitResourceManagement() { - let dead = undefined; - { - const command = new Deno.Command(Deno.execPath(), { - args: ["eval", "setTimeout(() => {}, 10000)"], - stdout: "null", - stderr: "null", - }); - await using child = command.spawn(); - child.status.then(({ signal }) => { - dead = signal; - }); - } - - if (Deno.build.os == "windows") { - assertEquals(dead, null); - } else { - assertEquals(dead, "SIGTERM"); - } - }, -); - -Deno.test( - { permissions: { run: true, read: true } }, - async function childProcessExplicitResourceManagementManualClose() { - const command = new Deno.Command(Deno.execPath(), { - args: ["eval", "setTimeout(() => {}, 10000)"], - stdout: "null", - stderr: "null", - }); - await using child = command.spawn(); - child.kill("SIGTERM"); - await child.status; - }, -); - -Deno.test( - { permissions: { run: true, read: true } }, - async function commandKillFailed() { - const command = new Deno.Command(Deno.execPath(), { - args: ["eval", "setTimeout(() => {}, 5000)"], - stdout: "null", - stderr: "null", - }); - const child = command.spawn(); - - assertThrows(() => { - // @ts-expect-error testing runtime error of bad signal - child.kill("foobar"); - }, TypeError); - - await child.status; - }, -); - -Deno.test( - { permissions: { run: true, read: true } }, - async function commandKillOptional() { - const command = new Deno.Command(Deno.execPath(), { - args: ["eval", "setTimeout(() => {}, 10000)"], - stdout: "null", - stderr: "null", - }); - const child = command.spawn(); - - child.kill(); - const status = await child.status; - - assertEquals(status.success, false); - if (Deno.build.os === "windows") { - assertEquals(status.code, 1); - assertEquals(status.signal, null); - } else { - assertEquals(status.code, 143); - assertEquals(status.signal, "SIGTERM"); - } - }, -); - -Deno.test( - { permissions: { run: true, read: true } }, - async function commandAbort() { - const ac = new AbortController(); - const command = new Deno.Command(Deno.execPath(), { - args: [ - "eval", - "setTimeout(console.log, 1e8)", - ], - signal: ac.signal, - stdout: "null", - stderr: "null", - }); - const child = command.spawn(); - queueMicrotask(() => ac.abort()); - const status = await child.status; - assertEquals(status.success, false); - if (Deno.build.os === "windows") { - assertEquals(status.code, 1); - assertEquals(status.signal, null); - } else { - assertEquals(status.success, false); - assertEquals(status.code, 143); - } - }, -); - -Deno.test( - { permissions: { read: true, run: false } }, - async function commandPermissions() { - await assertRejects(async () => { - await new Deno.Command(Deno.execPath(), { - args: ["eval", "console.log('hello world')"], - }).output(); - }, Deno.errors.PermissionDenied); - }, -); - -Deno.test( - { permissions: { read: true, run: false } }, - function commandSyncPermissions() { - assertThrows(() => { - new Deno.Command(Deno.execPath(), { - args: ["eval", "console.log('hello world')"], - }).outputSync(); - }, Deno.errors.PermissionDenied); - }, -); - -Deno.test( - { permissions: { run: true, read: true } }, - async function commandSuccess() { - const output = await new Deno.Command(Deno.execPath(), { - args: ["eval", "console.log('hello world')"], - }).output(); - - assertEquals(output.success, true); - assertEquals(output.code, 0); - assertEquals(output.signal, null); - }, -); - -Deno.test( - { permissions: { run: true, read: true } }, - function commandSyncSuccess() { - const output = new Deno.Command(Deno.execPath(), { - args: ["eval", "console.log('hello world')"], - }).outputSync(); - - assertEquals(output.success, true); - assertEquals(output.code, 0); - assertEquals(output.signal, null); - }, -); - -Deno.test( - { permissions: { run: true, read: true } }, - async function commandUrl() { - const output = await new Deno.Command( - new URL(`file:///${Deno.execPath()}`), - { - args: ["eval", "console.log('hello world')"], - }, - ).output(); - - assertEquals(new TextDecoder().decode(output.stdout), "hello world\n"); - - assertEquals(output.success, true); - assertEquals(output.code, 0); - assertEquals(output.signal, null); - }, -); - -Deno.test( - { permissions: { run: true, read: true } }, - function commandSyncUrl() { - const output = new Deno.Command( - new URL(`file:///${Deno.execPath()}`), - { - args: ["eval", "console.log('hello world')"], - }, - ).outputSync(); - - assertEquals(new TextDecoder().decode(output.stdout), "hello world\n"); - - assertEquals(output.success, true); - assertEquals(output.code, 0); - assertEquals(output.signal, null); - }, -); - -Deno.test({ permissions: { run: true } }, function commandNotFound() { - assertThrows( - () => new Deno.Command("this file hopefully doesn't exist").output(), - Deno.errors.NotFound, - ); -}); - -Deno.test({ permissions: { run: true } }, function commandSyncNotFound() { - assertThrows( - () => new Deno.Command("this file hopefully doesn't exist").outputSync(), - Deno.errors.NotFound, - ); -}); - -Deno.test({ permissions: { run: true, read: true } }, function cwdNotFound() { - assertThrows( - () => - new Deno.Command(Deno.execPath(), { - cwd: Deno.cwd() + "/non-existent-directory", - }).output(), - Deno.errors.NotFound, - "No such cwd", - ); -}); - -Deno.test( - { permissions: { run: true, read: true } }, - function cwdNotDirectory() { - assertThrows( - () => - new Deno.Command(Deno.execPath(), { - cwd: Deno.execPath(), - }).output(), - Deno.errors.NotFound, - "cwd is not a directory", - ); - }, -); - -Deno.test( - { permissions: { run: true, read: true } }, - async function commandFailedWithCode() { - const output = await new Deno.Command(Deno.execPath(), { - args: ["eval", "Deno.exit(41 + 1)"], - }).output(); - assertEquals(output.success, false); - assertEquals(output.code, 42); - assertEquals(output.signal, null); - }, -); - -Deno.test( - { permissions: { run: true, read: true } }, - function commandSyncFailedWithCode() { - const output = new Deno.Command(Deno.execPath(), { - args: ["eval", "Deno.exit(41 + 1)"], - }).outputSync(); - assertEquals(output.success, false); - assertEquals(output.code, 42); - assertEquals(output.signal, null); - }, -); - -Deno.test( - { - permissions: { run: true, read: true }, - }, - async function commandFailedWithSignal() { - const output = await new Deno.Command(Deno.execPath(), { - args: ["eval", "--unstable", "Deno.kill(Deno.pid, 'SIGKILL')"], - }).output(); - assertEquals(output.success, false); - if (Deno.build.os === "windows") { - assertEquals(output.code, 1); - assertEquals(output.signal, null); - } else { - assertEquals(output.code, 128 + 9); - assertEquals(output.signal, "SIGKILL"); - } - }, -); - -Deno.test( - { - permissions: { run: true, read: true }, - }, - function commandSyncFailedWithSignal() { - const output = new Deno.Command(Deno.execPath(), { - args: ["eval", "--unstable", "Deno.kill(Deno.pid, 'SIGKILL')"], - }).outputSync(); - assertEquals(output.success, false); - if (Deno.build.os === "windows") { - assertEquals(output.code, 1); - assertEquals(output.signal, null); - } else { - assertEquals(output.code, 128 + 9); - assertEquals(output.signal, "SIGKILL"); - } - }, -); - -Deno.test( - { permissions: { run: true, read: true } }, - async function commandOutput() { - const { stdout } = await new Deno.Command(Deno.execPath(), { - args: [ - "eval", - "await Deno.stdout.write(new TextEncoder().encode('hello'))", - ], - }).output(); - - const s = new TextDecoder().decode(stdout); - assertEquals(s, "hello"); - }, -); - -Deno.test( - { permissions: { run: true, read: true } }, - function commandSyncOutput() { - const { stdout } = new Deno.Command(Deno.execPath(), { - args: [ - "eval", - "await Deno.stdout.write(new TextEncoder().encode('hello'))", - ], - }).outputSync(); - - const s = new TextDecoder().decode(stdout); - assertEquals(s, "hello"); - }, -); - -Deno.test( - { permissions: { run: true, read: true } }, - async function commandStderrOutput() { - const { stderr } = await new Deno.Command(Deno.execPath(), { - args: [ - "eval", - "await Deno.stderr.write(new TextEncoder().encode('error'))", - ], - }).output(); - - const s = new TextDecoder().decode(stderr); - assertEquals(s, "error"); - }, -); - -Deno.test( - { permissions: { run: true, read: true } }, - function commandSyncStderrOutput() { - const { stderr } = new Deno.Command(Deno.execPath(), { - args: [ - "eval", - "await Deno.stderr.write(new TextEncoder().encode('error'))", - ], - }).outputSync(); - - const s = new TextDecoder().decode(stderr); - assertEquals(s, "error"); - }, -); - -Deno.test( - { permissions: { run: true, read: true } }, - async function commandEnv() { - const { stdout } = await new Deno.Command(Deno.execPath(), { - args: [ - "eval", - "Deno.stdout.write(new TextEncoder().encode(Deno.env.get('FOO') + Deno.env.get('BAR')))", - ], - env: { - FOO: "0123", - BAR: "4567", - }, - }).output(); - const s = new TextDecoder().decode(stdout); - assertEquals(s, "01234567"); - }, -); - -Deno.test( - { permissions: { run: true, read: true } }, - function commandSyncEnv() { - const { stdout } = new Deno.Command(Deno.execPath(), { - args: [ - "eval", - "Deno.stdout.write(new TextEncoder().encode(Deno.env.get('FOO') + Deno.env.get('BAR')))", - ], - env: { - FOO: "0123", - BAR: "4567", - }, - }).outputSync(); - const s = new TextDecoder().decode(stdout); - assertEquals(s, "01234567"); - }, -); - -Deno.test( - { permissions: { run: true, read: true, env: true } }, - async function commandClearEnv() { - const { stdout } = await new Deno.Command(Deno.execPath(), { - args: [ - "eval", - "-p", - "JSON.stringify(Deno.env.toObject())", - ], - clearEnv: true, - env: { - FOO: "23147", - }, - }).output(); - - const obj = JSON.parse(new TextDecoder().decode(stdout)); - - // can't check for object equality because the OS may set additional env - // vars for processes, so we check if PATH isn't present as that is a common - // env var across OS's and isn't set for processes. - assertEquals(obj.FOO, "23147"); - assert(!("PATH" in obj)); - }, -); - -Deno.test( - { permissions: { run: true, read: true, env: true } }, - function commandSyncClearEnv() { - const { stdout } = new Deno.Command(Deno.execPath(), { - args: [ - "eval", - "-p", - "JSON.stringify(Deno.env.toObject())", - ], - clearEnv: true, - env: { - FOO: "23147", - }, - }).outputSync(); - - const obj = JSON.parse(new TextDecoder().decode(stdout)); - - // can't check for object equality because the OS may set additional env - // vars for processes, so we check if PATH isn't present as that is a common - // env var across OS's and isn't set for processes. - assertEquals(obj.FOO, "23147"); - assert(!("PATH" in obj)); - }, -); - -Deno.test( - { - permissions: { run: true, read: true }, - ignore: Deno.build.os === "windows", - }, - async function commandUid() { - const { stdout } = await new Deno.Command("id", { - args: ["-u"], - }).output(); - - const currentUid = new TextDecoder().decode(stdout); - - if (currentUid !== "0") { - await assertRejects(async () => { - await new Deno.Command("echo", { - args: ["fhqwhgads"], - uid: 0, - }).output(); - }, Deno.errors.PermissionDenied); - } - }, -); - -Deno.test( - { - permissions: { run: true, read: true }, - ignore: Deno.build.os === "windows", - }, - function commandSyncUid() { - const { stdout } = new Deno.Command("id", { - args: ["-u"], - }).outputSync(); - - const currentUid = new TextDecoder().decode(stdout); - - if (currentUid !== "0") { - assertThrows(() => { - new Deno.Command("echo", { - args: ["fhqwhgads"], - uid: 0, - }).outputSync(); - }, Deno.errors.PermissionDenied); - } - }, -); - -Deno.test( - { - permissions: { run: true, read: true }, - ignore: Deno.build.os === "windows", - }, - async function commandGid() { - const { stdout } = await new Deno.Command("id", { - args: ["-g"], - }).output(); - - const currentGid = new TextDecoder().decode(stdout); - - if (currentGid !== "0") { - await assertRejects(async () => { - await new Deno.Command("echo", { - args: ["fhqwhgads"], - gid: 0, - }).output(); - }, Deno.errors.PermissionDenied); - } - }, -); - -Deno.test( - { - permissions: { run: true, read: true }, - ignore: Deno.build.os === "windows", - }, - function commandSyncGid() { - const { stdout } = new Deno.Command("id", { - args: ["-g"], - }).outputSync(); - - const currentGid = new TextDecoder().decode(stdout); - - if (currentGid !== "0") { - assertThrows(() => { - new Deno.Command("echo", { - args: ["fhqwhgads"], - gid: 0, - }).outputSync(); - }, Deno.errors.PermissionDenied); - } - }, -); - -Deno.test(function commandStdinPipedFails() { - assertThrows( - () => - new Deno.Command("id", { - stdin: "piped", - }).output(), - TypeError, - "Piped stdin is not supported for this function, use 'Deno.Command.spawn()' instead", - ); -}); - -Deno.test(function spawnSyncStdinPipedFails() { - assertThrows( - () => - new Deno.Command("id", { - stdin: "piped", - }).outputSync(), - TypeError, - "Piped stdin is not supported for this function, use 'Deno.Command.spawn()' instead", - ); -}); - -Deno.test( - // FIXME(bartlomieju): this test is very flaky on CI, fix it - { - ignore: true, - permissions: { write: true, run: true, read: true }, - }, - async function commandChildUnref() { - const enc = new TextEncoder(); - const cwd = await Deno.makeTempDir({ prefix: "deno_command_test" }); - - const programFile = "unref.ts"; - const program = ` -const command = await new Deno.Command(Deno.execPath(), { - cwd: Deno.args[0], - stdout: "piped", - args: ["run", "-A", "--unstable", Deno.args[1]], -}); -const child = command.spawn(); -const readable = child.stdout.pipeThrough(new TextDecoderStream()); -const reader = readable.getReader(); -// set up an interval that will end after reading a few messages from stdout, -// to verify that stdio streams are properly unrefed -let count = 0; -let interval; -interval = setInterval(async () => { - count += 1; - if (count > 10) { - clearInterval(interval); - console.log("cleared interval"); - } - const res = await reader.read(); - if (res.done) { - throw new Error("stream shouldn't be done"); - } - if (res.value.trim() != "hello from interval") { - throw new Error("invalid message received"); - } -}, 120); -console.log("spawned pid", child.pid); -child.unref(); -`; - - const childProgramFile = "unref_child.ts"; - const childProgram = ` -setInterval(() => { - console.log("hello from interval"); -}, 100); -`; - Deno.writeFileSync(`${cwd}/${programFile}`, enc.encode(program)); - Deno.writeFileSync(`${cwd}/${childProgramFile}`, enc.encode(childProgram)); - // In this subprocess we are spawning another subprocess which has - // an infinite interval set. Following call would never resolve unless - // child process gets unrefed. - const { success, stdout, stderr } = await new Deno.Command( - Deno.execPath(), - { - cwd, - args: ["run", "-A", "--unstable", programFile, cwd, childProgramFile], - }, - ).output(); - - assert(success); - const stdoutText = new TextDecoder().decode(stdout); - const stderrText = new TextDecoder().decode(stderr); - assert(stderrText.length == 0); - const [line1, line2] = stdoutText.split("\n"); - const pidStr = line1.split(" ").at(-1); - assert(pidStr); - assertEquals(line2, "cleared interval"); - const pid = Number.parseInt(pidStr, 10); - await Deno.remove(cwd, { recursive: true }); - // Child process should have been killed when parent process exits. - assertThrows(() => { - Deno.kill(pid, "SIGTERM"); - }, Deno.errors.NotFound); - }, -); - -Deno.test( - { ignore: Deno.build.os !== "windows" }, - async function commandWindowsRawArguments() { - let { success, stdout } = await new Deno.Command("cmd", { - args: ["/d", "/s", "/c", '"deno ^"--version^""'], - windowsRawArguments: true, - }).output(); - assert(success); - let stdoutText = new TextDecoder().decode(stdout); - assertStringIncludes(stdoutText, "deno"); - assertStringIncludes(stdoutText, "v8"); - assertStringIncludes(stdoutText, "typescript"); - - ({ success, stdout } = new Deno.Command("cmd", { - args: ["/d", "/s", "/c", '"deno ^"--version^""'], - windowsRawArguments: true, - }).outputSync()); - assert(success); - stdoutText = new TextDecoder().decode(stdout); - assertStringIncludes(stdoutText, "deno"); - assertStringIncludes(stdoutText, "v8"); - assertStringIncludes(stdoutText, "typescript"); - }, -); - -Deno.test( - { permissions: { read: true, run: true } }, - async function commandWithPrototypePollution() { - const originalThen = Promise.prototype.then; - const originalSymbolIterator = Array.prototype[Symbol.iterator]; - try { - Promise.prototype.then = Array.prototype[Symbol.iterator] = () => { - throw new Error(); - }; - await new Deno.Command(Deno.execPath(), { - args: ["eval", "console.log('hello world')"], - }).output(); - } finally { - Promise.prototype.then = originalThen; - Array.prototype[Symbol.iterator] = originalSymbolIterator; - } - }, -); - -Deno.test( - { permissions: { run: true, read: true } }, - async function commandKillAfterStatus() { - const command = new Deno.Command(Deno.execPath(), { - args: ["help"], - stdout: "null", - stderr: "null", - }); - const child = command.spawn(); - await child.status; - assertThrows( - () => child.kill(), - TypeError, - "Child process has already terminated.", - ); - }, -); - -Deno.test( - "process that fails to spawn, prints its name in error", - async () => { - assertThrows( - () => new Deno.Command("doesntexist").outputSync(), - Error, - "Failed to spawn 'doesntexist'", - ); - await assertRejects( - async () => await new Deno.Command("doesntexist").output(), - Error, - "Failed to spawn 'doesntexist'", - ); - }, -); |