2020-01-02 15:13:47 -05:00
|
|
|
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
2020-06-24 18:57:08 -04:00
|
|
|
import {
|
|
|
|
unitTest,
|
|
|
|
assert,
|
|
|
|
assertThrows,
|
|
|
|
assertThrowsAsync,
|
|
|
|
} from "./test_util.ts";
|
2018-09-10 23:40:03 -04:00
|
|
|
|
2020-05-31 13:19:56 -04:00
|
|
|
const REMOVE_METHODS = ["remove", "removeSync"] as const;
|
2018-09-10 23:40:03 -04:00
|
|
|
|
2020-03-04 11:31:14 -05:00
|
|
|
unitTest(
|
|
|
|
{ perms: { write: true, read: true } },
|
2020-05-31 13:19:56 -04:00
|
|
|
async function removeDirSuccess(): Promise<void> {
|
|
|
|
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
|
2020-06-24 18:57:08 -04:00
|
|
|
assertThrows(() => {
|
2020-05-31 13:19:56 -04:00
|
|
|
Deno.statSync(path);
|
2020-06-24 18:57:08 -04:00
|
|
|
}, Deno.errors.NotFound);
|
2020-03-04 11:31:14 -05:00
|
|
|
}
|
2020-07-14 15:24:17 -04:00
|
|
|
},
|
2020-03-04 11:31:14 -05:00
|
|
|
);
|
2018-09-10 23:40:03 -04:00
|
|
|
|
2020-03-04 11:31:14 -05:00
|
|
|
unitTest(
|
|
|
|
{ perms: { write: true, read: true } },
|
2020-05-31 13:19:56 -04:00
|
|
|
async function removeFileSuccess(): Promise<void> {
|
|
|
|
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
|
2020-06-24 18:57:08 -04:00
|
|
|
assertThrows(() => {
|
2020-05-31 13:19:56 -04:00
|
|
|
Deno.statSync(filename);
|
2020-06-24 18:57:08 -04:00
|
|
|
}, Deno.errors.NotFound);
|
2020-03-04 11:31:14 -05:00
|
|
|
}
|
2020-07-14 15:24:17 -04:00
|
|
|
},
|
2020-03-04 11:31:14 -05:00
|
|
|
);
|
2018-09-10 23:40:03 -04:00
|
|
|
|
2020-06-11 12:36:20 -04:00
|
|
|
unitTest(
|
|
|
|
{ perms: { write: true, read: true } },
|
|
|
|
async function removeFileByUrl(): Promise<void> {
|
|
|
|
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(
|
2020-07-14 15:24:17 -04:00
|
|
|
`file://${Deno.build.os === "windows" ? "/" : ""}${tempDir}/test.txt`,
|
2020-06-11 12:36:20 -04:00
|
|
|
);
|
|
|
|
|
|
|
|
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
|
2020-06-24 18:57:08 -04:00
|
|
|
assertThrows(() => {
|
2020-06-11 12:36:20 -04:00
|
|
|
Deno.statSync(fileUrl);
|
2020-06-24 18:57:08 -04:00
|
|
|
}, Deno.errors.NotFound);
|
2020-06-11 12:36:20 -04:00
|
|
|
}
|
2020-07-14 15:24:17 -04:00
|
|
|
},
|
2020-06-11 12:36:20 -04:00
|
|
|
);
|
|
|
|
|
2020-03-04 11:31:14 -05:00
|
|
|
unitTest(
|
|
|
|
{ perms: { write: true, read: true } },
|
2020-05-31 13:19:56 -04:00
|
|
|
async function removeFail(): Promise<void> {
|
|
|
|
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
|
2020-06-24 18:57:08 -04:00
|
|
|
|
|
|
|
await assertThrowsAsync(async () => {
|
2020-05-31 13:19:56 -04:00
|
|
|
await Deno[method](path);
|
2020-06-24 18:57:08 -04:00
|
|
|
}, Error);
|
2020-05-31 13:19:56 -04:00
|
|
|
// TODO(ry) Is Other really the error we should get here? What would Go do?
|
2020-06-24 18:57:08 -04:00
|
|
|
|
2020-05-31 13:19:56 -04:00
|
|
|
// NON-EXISTENT DIRECTORY/FILE
|
2020-06-24 18:57:08 -04:00
|
|
|
await assertThrowsAsync(async () => {
|
2020-05-31 13:19:56 -04:00
|
|
|
await Deno[method]("/baddir");
|
2020-06-24 18:57:08 -04:00
|
|
|
}, Deno.errors.NotFound);
|
2020-05-18 18:46:02 -04:00
|
|
|
}
|
2020-07-14 15:24:17 -04:00
|
|
|
},
|
2020-02-03 08:20:15 -05:00
|
|
|
);
|
|
|
|
|
2020-03-04 11:31:14 -05:00
|
|
|
unitTest(
|
|
|
|
{ perms: { write: true, read: true } },
|
2020-05-31 13:19:56 -04:00
|
|
|
async function removeDanglingSymlinkSuccess(): Promise<void> {
|
|
|
|
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);
|
2020-06-24 18:57:08 -04:00
|
|
|
assertThrows(() => {
|
2020-05-31 13:19:56 -04:00
|
|
|
Deno.lstatSync(danglingSymlinkPath);
|
2020-06-24 18:57:08 -04:00
|
|
|
}, Deno.errors.NotFound);
|
2020-02-03 08:20:15 -05:00
|
|
|
}
|
2020-07-14 15:24:17 -04:00
|
|
|
},
|
2020-02-03 08:20:15 -05:00
|
|
|
);
|
|
|
|
|
2020-03-04 11:31:14 -05:00
|
|
|
unitTest(
|
|
|
|
{ perms: { write: true, read: true } },
|
2020-05-31 13:19:56 -04:00
|
|
|
async function removeValidSymlinkSuccess(): Promise<void> {
|
|
|
|
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);
|
2020-06-24 18:57:08 -04:00
|
|
|
assertThrows(() => {
|
2020-05-31 13:19:56 -04:00
|
|
|
Deno.statSync(validSymlinkPath);
|
2020-06-24 18:57:08 -04:00
|
|
|
}, Deno.errors.NotFound);
|
2020-05-31 13:19:56 -04:00
|
|
|
await Deno[method](filePath);
|
2020-03-04 11:31:14 -05:00
|
|
|
}
|
2020-07-14 15:24:17 -04:00
|
|
|
},
|
2020-03-04 11:31:14 -05:00
|
|
|
);
|
2018-09-10 23:40:03 -04:00
|
|
|
|
2020-05-31 13:19:56 -04:00
|
|
|
unitTest({ perms: { write: false } }, async function removePerm(): Promise<
|
|
|
|
void
|
|
|
|
> {
|
|
|
|
for (const method of REMOVE_METHODS) {
|
2020-06-24 18:57:08 -04:00
|
|
|
await assertThrowsAsync(async () => {
|
2020-05-31 13:19:56 -04:00
|
|
|
await Deno[method]("/baddir");
|
2020-06-24 18:57:08 -04:00
|
|
|
}, Deno.errors.PermissionDenied);
|
2018-09-10 23:40:03 -04:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2020-03-04 11:31:14 -05:00
|
|
|
unitTest(
|
|
|
|
{ perms: { write: true, read: true } },
|
2020-05-31 13:19:56 -04:00
|
|
|
async function removeAllDirSuccess(): Promise<void> {
|
|
|
|
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
|
2020-06-24 18:57:08 -04:00
|
|
|
assertThrows(
|
|
|
|
() => {
|
|
|
|
Deno.statSync(path);
|
|
|
|
}, // Directory is gone
|
2020-07-14 15:24:17 -04:00
|
|
|
Deno.errors.NotFound,
|
2020-06-24 18:57:08 -04:00
|
|
|
);
|
2018-09-10 23:40:03 -04:00
|
|
|
|
2020-05-31 13:19:56 -04:00
|
|
|
// 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
|
2020-06-24 18:57:08 -04:00
|
|
|
assertThrows(() => {
|
2020-05-31 13:19:56 -04:00
|
|
|
Deno.statSync(path);
|
2020-06-24 18:57:08 -04:00
|
|
|
}, Deno.errors.NotFound);
|
2020-05-31 13:19:56 -04:00
|
|
|
// Directory is gone
|
2020-05-18 18:46:02 -04:00
|
|
|
}
|
2020-07-14 15:24:17 -04:00
|
|
|
},
|
2020-02-03 08:20:15 -05:00
|
|
|
);
|
|
|
|
|
2020-03-04 11:31:14 -05:00
|
|
|
unitTest(
|
|
|
|
{ perms: { write: true, read: true } },
|
2020-05-31 13:19:56 -04:00
|
|
|
async function removeAllFileSuccess(): Promise<void> {
|
|
|
|
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
|
2020-06-24 18:57:08 -04:00
|
|
|
assertThrows(() => {
|
2020-05-31 13:19:56 -04:00
|
|
|
Deno.statSync(filename);
|
2020-06-24 18:57:08 -04:00
|
|
|
}, Deno.errors.NotFound);
|
2020-05-31 13:19:56 -04:00
|
|
|
// File is gone
|
2020-02-03 08:20:15 -05:00
|
|
|
}
|
2020-07-14 15:24:17 -04:00
|
|
|
},
|
2020-02-03 08:20:15 -05:00
|
|
|
);
|
|
|
|
|
2020-05-31 13:19:56 -04:00
|
|
|
unitTest({ perms: { write: true } }, async function removeAllFail(): Promise<
|
2020-03-04 11:31:14 -05:00
|
|
|
void
|
|
|
|
> {
|
2020-05-31 13:19:56 -04:00
|
|
|
for (const method of REMOVE_METHODS) {
|
|
|
|
// NON-EXISTENT DIRECTORY/FILE
|
2020-06-24 18:57:08 -04:00
|
|
|
await assertThrowsAsync(async () => {
|
2020-05-31 13:19:56 -04:00
|
|
|
// Non-existent
|
|
|
|
await Deno[method]("/baddir", { recursive: true });
|
2020-06-24 18:57:08 -04:00
|
|
|
}, Deno.errors.NotFound);
|
2018-09-10 23:40:03 -04:00
|
|
|
}
|
2020-05-31 13:19:56 -04:00
|
|
|
});
|
2018-09-10 23:40:03 -04:00
|
|
|
|
2020-05-31 13:19:56 -04:00
|
|
|
unitTest({ perms: { write: false } }, async function removeAllPerm(): Promise<
|
|
|
|
void
|
|
|
|
> {
|
|
|
|
for (const method of REMOVE_METHODS) {
|
2020-06-24 18:57:08 -04:00
|
|
|
await assertThrowsAsync(async () => {
|
2020-05-31 13:19:56 -04:00
|
|
|
await Deno[method]("/baddir", { recursive: true });
|
2020-06-24 18:57:08 -04:00
|
|
|
}, Deno.errors.PermissionDenied);
|
2018-09-10 23:40:03 -04:00
|
|
|
}
|
|
|
|
});
|
2020-05-18 08:50:44 -04:00
|
|
|
|
2020-05-30 14:48:26 -04:00
|
|
|
unitTest(
|
|
|
|
{
|
|
|
|
ignore: Deno.build.os === "windows",
|
|
|
|
perms: { write: true, read: true },
|
|
|
|
},
|
|
|
|
async function removeUnixSocketSuccess(): Promise<void> {
|
2020-05-31 13:19:56 -04:00
|
|
|
for (const method of REMOVE_METHODS) {
|
2020-05-30 14:48:26 -04:00
|
|
|
// 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);
|
2020-06-24 18:57:08 -04:00
|
|
|
assertThrows(() => {
|
2020-05-30 14:48:26 -04:00
|
|
|
Deno.statSync(path);
|
2020-06-24 18:57:08 -04:00
|
|
|
}, Deno.errors.NotFound);
|
2020-05-30 14:48:26 -04:00
|
|
|
}
|
2020-07-14 15:24:17 -04:00
|
|
|
},
|
2020-05-30 14:48:26 -04:00
|
|
|
);
|
|
|
|
|
2020-05-18 08:50:44 -04:00
|
|
|
if (Deno.build.os === "windows") {
|
|
|
|
unitTest(
|
|
|
|
{ perms: { run: true, write: true, read: true } },
|
|
|
|
async function removeFileSymlink(): Promise<void> {
|
|
|
|
const symlink = Deno.run({
|
|
|
|
cmd: ["cmd", "/c", "mklink", "file_link", "bar"],
|
|
|
|
stdout: "null",
|
|
|
|
});
|
|
|
|
|
|
|
|
assert(await symlink.status());
|
|
|
|
symlink.close();
|
|
|
|
await Deno.remove("file_link");
|
2020-06-24 18:57:08 -04:00
|
|
|
await assertThrowsAsync(async () => {
|
2020-05-18 08:50:44 -04:00
|
|
|
await Deno.lstat("file_link");
|
2020-06-24 18:57:08 -04:00
|
|
|
}, Deno.errors.NotFound);
|
2020-07-14 15:24:17 -04:00
|
|
|
},
|
2020-05-18 08:50:44 -04:00
|
|
|
);
|
|
|
|
|
|
|
|
unitTest(
|
|
|
|
{ perms: { run: true, write: true, read: true } },
|
|
|
|
async function removeDirSymlink(): Promise<void> {
|
|
|
|
const symlink = Deno.run({
|
|
|
|
cmd: ["cmd", "/c", "mklink", "/d", "dir_link", "bar"],
|
|
|
|
stdout: "null",
|
|
|
|
});
|
|
|
|
|
|
|
|
assert(await symlink.status());
|
|
|
|
symlink.close();
|
|
|
|
|
|
|
|
await Deno.remove("dir_link");
|
2020-06-24 18:57:08 -04:00
|
|
|
await assertThrowsAsync(async () => {
|
2020-05-18 08:50:44 -04:00
|
|
|
await Deno.lstat("dir_link");
|
2020-06-24 18:57:08 -04:00
|
|
|
}, Deno.errors.NotFound);
|
2020-07-14 15:24:17 -04:00
|
|
|
},
|
2020-05-18 08:50:44 -04:00
|
|
|
);
|
|
|
|
}
|