mirror of
https://github.com/denoland/deno.git
synced 2024-10-30 09:08:00 -04:00
45c49034a7
- "SpawnOutput" extends "ChildStatus" instead of composing it - "SpawnOutput::stdout", "SpawnOutput::stderr", "Child::stdin", "Child::stdout" and "Child::stderr" are no longer optional, instead made them getters that throw at runtime if that stream wasn't set to "piped". - Remove the complicated "<T extends SpawnOptions = SpawnOptions>" which we currently need to give proper type hints for the availability of these fields. Their typings for these would get increasingly complex if it became dependent on more options (e.g. "SpawnOptions::pty" which if set should make the stdio streams unavailable)
293 lines
8.9 KiB
TypeScript
293 lines
8.9 KiB
TypeScript
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
|
import { assert, assertRejects, assertThrows } from "./test_util.ts";
|
|
|
|
const REMOVE_METHODS = ["remove", "removeSync"] as const;
|
|
|
|
Deno.test(
|
|
{ permissions: { write: true, read: true } },
|
|
async function removeDirSuccess() {
|
|
for (const method of REMOVE_METHODS) {
|
|
// REMOVE EMPTY DIRECTORY
|
|
const path = Deno.makeTempDirSync() + "/subdir";
|
|
Deno.mkdirSync(path);
|
|
const pathInfo = Deno.statSync(path);
|
|
assert(pathInfo.isDirectory); // check exist first
|
|
await Deno[method](path); // remove
|
|
// We then check again after remove
|
|
assertThrows(() => {
|
|
Deno.statSync(path);
|
|
}, Deno.errors.NotFound);
|
|
}
|
|
},
|
|
);
|
|
|
|
Deno.test(
|
|
{ permissions: { write: true, read: true } },
|
|
async function removeFileSuccess() {
|
|
for (const method of REMOVE_METHODS) {
|
|
// REMOVE FILE
|
|
const enc = new TextEncoder();
|
|
const data = enc.encode("Hello");
|
|
const filename = Deno.makeTempDirSync() + "/test.txt";
|
|
Deno.writeFileSync(filename, data, { mode: 0o666 });
|
|
const fileInfo = Deno.statSync(filename);
|
|
assert(fileInfo.isFile); // check exist first
|
|
await Deno[method](filename); // remove
|
|
// We then check again after remove
|
|
assertThrows(() => {
|
|
Deno.statSync(filename);
|
|
}, Deno.errors.NotFound);
|
|
}
|
|
},
|
|
);
|
|
|
|
Deno.test(
|
|
{ permissions: { write: true, read: true } },
|
|
async function removeFileByUrl() {
|
|
for (const method of REMOVE_METHODS) {
|
|
// REMOVE FILE
|
|
const enc = new TextEncoder();
|
|
const data = enc.encode("Hello");
|
|
|
|
const tempDir = Deno.makeTempDirSync();
|
|
const fileUrl = new URL(
|
|
`file://${Deno.build.os === "windows" ? "/" : ""}${tempDir}/test.txt`,
|
|
);
|
|
|
|
Deno.writeFileSync(fileUrl, data, { mode: 0o666 });
|
|
const fileInfo = Deno.statSync(fileUrl);
|
|
assert(fileInfo.isFile); // check exist first
|
|
await Deno[method](fileUrl); // remove
|
|
// We then check again after remove
|
|
assertThrows(() => {
|
|
Deno.statSync(fileUrl);
|
|
}, Deno.errors.NotFound);
|
|
}
|
|
},
|
|
);
|
|
|
|
Deno.test(
|
|
{ permissions: { write: true, read: true } },
|
|
async function removeFail() {
|
|
for (const method of REMOVE_METHODS) {
|
|
// NON-EMPTY DIRECTORY
|
|
const path = Deno.makeTempDirSync() + "/dir/subdir";
|
|
const subPath = path + "/subsubdir";
|
|
Deno.mkdirSync(path, { recursive: true });
|
|
Deno.mkdirSync(subPath);
|
|
const pathInfo = Deno.statSync(path);
|
|
assert(pathInfo.isDirectory); // check exist first
|
|
const subPathInfo = Deno.statSync(subPath);
|
|
assert(subPathInfo.isDirectory); // check exist first
|
|
|
|
await assertRejects(
|
|
async () => {
|
|
await Deno[method](path);
|
|
},
|
|
Error,
|
|
`remove '${path}'`,
|
|
);
|
|
// TODO(ry) Is Other really the error we should get here? What would Go do?
|
|
|
|
// NON-EXISTENT DIRECTORY/FILE
|
|
await assertRejects(
|
|
async () => {
|
|
await Deno[method]("/baddir");
|
|
},
|
|
Deno.errors.NotFound,
|
|
`remove '/baddir'`,
|
|
);
|
|
}
|
|
},
|
|
);
|
|
|
|
Deno.test(
|
|
{ permissions: { write: true, read: true } },
|
|
async function removeDanglingSymlinkSuccess() {
|
|
for (const method of REMOVE_METHODS) {
|
|
const danglingSymlinkPath = Deno.makeTempDirSync() + "/dangling_symlink";
|
|
if (Deno.build.os === "windows") {
|
|
Deno.symlinkSync("unexistent_file", danglingSymlinkPath, {
|
|
type: "file",
|
|
});
|
|
} else {
|
|
Deno.symlinkSync("unexistent_file", danglingSymlinkPath);
|
|
}
|
|
const pathInfo = Deno.lstatSync(danglingSymlinkPath);
|
|
assert(pathInfo.isSymlink);
|
|
await Deno[method](danglingSymlinkPath);
|
|
assertThrows(() => {
|
|
Deno.lstatSync(danglingSymlinkPath);
|
|
}, Deno.errors.NotFound);
|
|
}
|
|
},
|
|
);
|
|
|
|
Deno.test(
|
|
{ permissions: { write: true, read: true } },
|
|
async function removeValidSymlinkSuccess() {
|
|
for (const method of REMOVE_METHODS) {
|
|
const encoder = new TextEncoder();
|
|
const data = encoder.encode("Test");
|
|
const tempDir = Deno.makeTempDirSync();
|
|
const filePath = tempDir + "/test.txt";
|
|
const validSymlinkPath = tempDir + "/valid_symlink";
|
|
Deno.writeFileSync(filePath, data, { mode: 0o666 });
|
|
if (Deno.build.os === "windows") {
|
|
Deno.symlinkSync(filePath, validSymlinkPath, { type: "file" });
|
|
} else {
|
|
Deno.symlinkSync(filePath, validSymlinkPath);
|
|
}
|
|
const symlinkPathInfo = Deno.statSync(validSymlinkPath);
|
|
assert(symlinkPathInfo.isFile);
|
|
await Deno[method](validSymlinkPath);
|
|
assertThrows(() => {
|
|
Deno.statSync(validSymlinkPath);
|
|
}, Deno.errors.NotFound);
|
|
await Deno[method](filePath);
|
|
}
|
|
},
|
|
);
|
|
|
|
Deno.test({ permissions: { write: false } }, async function removePerm() {
|
|
for (const method of REMOVE_METHODS) {
|
|
await assertRejects(async () => {
|
|
await Deno[method]("/baddir");
|
|
}, Deno.errors.PermissionDenied);
|
|
}
|
|
});
|
|
|
|
Deno.test(
|
|
{ permissions: { write: true, read: true } },
|
|
async function removeAllDirSuccess() {
|
|
for (const method of REMOVE_METHODS) {
|
|
// REMOVE EMPTY DIRECTORY
|
|
let path = Deno.makeTempDirSync() + "/dir/subdir";
|
|
Deno.mkdirSync(path, { recursive: true });
|
|
let pathInfo = Deno.statSync(path);
|
|
assert(pathInfo.isDirectory); // check exist first
|
|
await Deno[method](path, { recursive: true }); // remove
|
|
// We then check again after remove
|
|
assertThrows(
|
|
() => {
|
|
Deno.statSync(path);
|
|
}, // Directory is gone
|
|
Deno.errors.NotFound,
|
|
);
|
|
|
|
// REMOVE NON-EMPTY DIRECTORY
|
|
path = Deno.makeTempDirSync() + "/dir/subdir";
|
|
const subPath = path + "/subsubdir";
|
|
Deno.mkdirSync(path, { recursive: true });
|
|
Deno.mkdirSync(subPath);
|
|
pathInfo = Deno.statSync(path);
|
|
assert(pathInfo.isDirectory); // check exist first
|
|
const subPathInfo = Deno.statSync(subPath);
|
|
assert(subPathInfo.isDirectory); // check exist first
|
|
await Deno[method](path, { recursive: true }); // remove
|
|
// We then check parent directory again after remove
|
|
assertThrows(() => {
|
|
Deno.statSync(path);
|
|
}, Deno.errors.NotFound);
|
|
// Directory is gone
|
|
}
|
|
},
|
|
);
|
|
|
|
Deno.test(
|
|
{ permissions: { write: true, read: true } },
|
|
async function removeAllFileSuccess() {
|
|
for (const method of REMOVE_METHODS) {
|
|
// REMOVE FILE
|
|
const enc = new TextEncoder();
|
|
const data = enc.encode("Hello");
|
|
const filename = Deno.makeTempDirSync() + "/test.txt";
|
|
Deno.writeFileSync(filename, data, { mode: 0o666 });
|
|
const fileInfo = Deno.statSync(filename);
|
|
assert(fileInfo.isFile); // check exist first
|
|
await Deno[method](filename, { recursive: true }); // remove
|
|
// We then check again after remove
|
|
assertThrows(() => {
|
|
Deno.statSync(filename);
|
|
}, Deno.errors.NotFound);
|
|
// File is gone
|
|
}
|
|
},
|
|
);
|
|
|
|
Deno.test({ permissions: { write: true } }, async function removeAllFail() {
|
|
for (const method of REMOVE_METHODS) {
|
|
// NON-EXISTENT DIRECTORY/FILE
|
|
await assertRejects(
|
|
async () => {
|
|
// Non-existent
|
|
await Deno[method]("/baddir", { recursive: true });
|
|
},
|
|
Deno.errors.NotFound,
|
|
`remove '/baddir'`,
|
|
);
|
|
}
|
|
});
|
|
|
|
Deno.test({ permissions: { write: false } }, async function removeAllPerm() {
|
|
for (const method of REMOVE_METHODS) {
|
|
await assertRejects(async () => {
|
|
await Deno[method]("/baddir", { recursive: true });
|
|
}, Deno.errors.PermissionDenied);
|
|
}
|
|
});
|
|
|
|
Deno.test(
|
|
{
|
|
ignore: Deno.build.os === "windows",
|
|
permissions: { write: true, read: true },
|
|
},
|
|
async function removeUnixSocketSuccess() {
|
|
for (const method of REMOVE_METHODS) {
|
|
// MAKE TEMPORARY UNIX SOCKET
|
|
const path = Deno.makeTempDirSync() + "/test.sock";
|
|
const listener = Deno.listen({ transport: "unix", path });
|
|
listener.close();
|
|
Deno.statSync(path); // check if unix socket exists
|
|
|
|
await Deno[method](path);
|
|
assertThrows(() => {
|
|
Deno.statSync(path);
|
|
}, Deno.errors.NotFound);
|
|
}
|
|
},
|
|
);
|
|
|
|
if (Deno.build.os === "windows") {
|
|
Deno.test(
|
|
{ permissions: { run: true, write: true, read: true } },
|
|
async function removeFileSymlink() {
|
|
const { success } = await Deno.spawn("cmd", {
|
|
args: ["/c", "mklink", "file_link", "bar"],
|
|
stdout: "null",
|
|
});
|
|
|
|
assert(success);
|
|
await Deno.remove("file_link");
|
|
await assertRejects(async () => {
|
|
await Deno.lstat("file_link");
|
|
}, Deno.errors.NotFound);
|
|
},
|
|
);
|
|
|
|
Deno.test(
|
|
{ permissions: { run: true, write: true, read: true } },
|
|
async function removeDirSymlink() {
|
|
const { success } = await Deno.spawn("cmd", {
|
|
args: ["/c", "mklink", "/d", "dir_link", "bar"],
|
|
stdout: "null",
|
|
});
|
|
|
|
assert(success);
|
|
await Deno.remove("dir_link");
|
|
await assertRejects(async () => {
|
|
await Deno.lstat("dir_link");
|
|
}, Deno.errors.NotFound);
|
|
},
|
|
);
|
|
}
|