0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-10-31 09:14:20 -04:00
denoland-deno/cli/tests/unit/remove_test.ts
Nayeem Rahman 45c49034a7
BREAKING(unstable): Improve Deno.spawn() stdio API (#14919)
- "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)
2022-07-18 15:16:12 +02:00

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);
},
);
}