summaryrefslogtreecommitdiff
path: root/cli/js
diff options
context:
space:
mode:
authordubiousjim <dubiousjim@gmail.com>2020-04-03 11:00:16 -0400
committerGitHub <noreply@github.com>2020-04-03 11:00:16 -0400
commitce02167c75c42e2e2f85a98128d70504e88da02b (patch)
treeb75a520b9aae1711c0045af91b6d88b1ad89fc84 /cli/js
parentd8f32c7eff02fb62250e06c1bb1eda95b86a52a7 (diff)
Improve tests and docs for Deno.rename (#4597)
Diffstat (limited to 'cli/js')
-rw-r--r--cli/js/lib.deno.ns.d.ts14
-rw-r--r--cli/js/tests/rename_test.ts186
2 files changed, 168 insertions, 32 deletions
diff --git a/cli/js/lib.deno.ns.d.ts b/cli/js/lib.deno.ns.d.ts
index 9cef597a4..b76fac1a5 100644
--- a/cli/js/lib.deno.ns.d.ts
+++ b/cli/js/lib.deno.ns.d.ts
@@ -1284,8 +1284,10 @@ declare namespace Deno {
*
* Deno.renameSync("old/path", "new/path");
*
- * Throws error if attempting to rename to a directory which exists and is not
- * empty.
+ * On Unix, this operation does not follow symlinks at either path.
+ *
+ * It varies between platforms when the operation throws errors, and if so what
+ * they are. It's always an error to rename anything to a non-empty directory.
*
* Requires `allow-read` and `allow-write` permissions. */
export function renameSync(oldpath: string, newpath: string): void;
@@ -1297,10 +1299,12 @@ declare namespace Deno {
*
* await Deno.rename("old/path", "new/path");
*
- * Throws error if attempting to rename to a directory which exists and is not
- * empty.
+ * On Unix, this operation does not follow symlinks at either path.
+ *
+ * It varies between platforms when the operation throws errors, and if so what
+ * they are. It's always an error to rename anything to a non-empty directory.
*
- * Requires `allow-read` and `allow-write`. */
+ * Requires `allow-read` and `allow-write` permission. */
export function rename(oldpath: string, newpath: string): Promise<void>;
/** Synchronously reads and returns the entire contents of a file as an array
diff --git a/cli/js/tests/rename_test.ts b/cli/js/tests/rename_test.ts
index 288f24bd7..45f6d709e 100644
--- a/cli/js/tests/rename_test.ts
+++ b/cli/js/tests/rename_test.ts
@@ -1,5 +1,31 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
-import { unitTest, assert, assertEquals } from "./test_util.ts";
+import { unitTest, assert, assertEquals, assertThrows } from "./test_util.ts";
+
+function assertMissing(path: string): void {
+ let caughtErr = false;
+ let info;
+ try {
+ info = Deno.lstatSync(path);
+ } catch (e) {
+ caughtErr = true;
+ assert(e instanceof Deno.errors.NotFound);
+ }
+ assert(caughtErr);
+ assertEquals(info, undefined);
+}
+
+function assertFile(path: string): void {
+ const info = Deno.lstatSync(path);
+ assert(info.isFile());
+}
+
+function assertDirectory(path: string, mode?: number): void {
+ const info = Deno.lstatSync(path);
+ assert(info.isDirectory());
+ if (Deno.build.os !== "win" && mode !== undefined) {
+ assertEquals(info.mode! & 0o777, mode & ~Deno.umask());
+ }
+}
unitTest(
{ perms: { read: true, write: true } },
@@ -9,20 +35,8 @@ unitTest(
const newpath = testDir + "/newpath";
Deno.mkdirSync(oldpath);
Deno.renameSync(oldpath, newpath);
- const newPathInfo = Deno.statSync(newpath);
- assert(newPathInfo.isDirectory());
-
- let caughtErr = false;
- let oldPathInfo;
-
- try {
- oldPathInfo = Deno.statSync(oldpath);
- } catch (e) {
- caughtErr = true;
- assert(e instanceof Deno.errors.NotFound);
- }
- assert(caughtErr);
- assertEquals(oldPathInfo, undefined);
+ assertDirectory(newpath);
+ assertMissing(oldpath);
}
);
@@ -66,19 +80,137 @@ unitTest(
const newpath = testDir + "/newpath";
Deno.mkdirSync(oldpath);
await Deno.rename(oldpath, newpath);
- const newPathInfo = Deno.statSync(newpath);
- assert(newPathInfo.isDirectory());
+ assertDirectory(newpath);
+ assertMissing(oldpath);
+ }
+);
- let caughtErr = false;
- let oldPathInfo;
+function readFileString(filename: string): string {
+ const dataRead = Deno.readFileSync(filename);
+ const dec = new TextDecoder("utf-8");
+ return dec.decode(dataRead);
+}
- try {
- oldPathInfo = Deno.statSync(oldpath);
- } catch (e) {
- caughtErr = true;
- assert(e instanceof Deno.errors.NotFound);
- }
- assert(caughtErr);
- assertEquals(oldPathInfo, undefined);
+function writeFileString(filename: string, s: string): void {
+ const enc = new TextEncoder();
+ const data = enc.encode(s);
+ Deno.writeFileSync(filename, data, { mode: 0o666 });
+}
+
+unitTest(
+ { ignore: Deno.build.os === "win", perms: { read: true, write: true } },
+ function renameSyncErrorsUnix(): void {
+ const testDir = Deno.makeTempDirSync();
+ const oldfile = testDir + "/oldfile";
+ const olddir = testDir + "/olddir";
+ const emptydir = testDir + "/empty";
+ const fulldir = testDir + "/dir";
+ const file = fulldir + "/file";
+ writeFileString(oldfile, "Hello");
+ Deno.mkdirSync(olddir);
+ Deno.mkdirSync(emptydir);
+ Deno.mkdirSync(fulldir);
+ writeFileString(file, "world");
+
+ assertThrows(
+ (): void => {
+ Deno.renameSync(oldfile, emptydir);
+ },
+ Error,
+ "Is a directory"
+ );
+ assertThrows(
+ (): void => {
+ Deno.renameSync(olddir, fulldir);
+ },
+ Error,
+ "Directory not empty"
+ );
+ assertThrows(
+ (): void => {
+ Deno.renameSync(olddir, file);
+ },
+ Error,
+ "Not a directory"
+ );
+
+ const fileLink = testDir + "/fileLink";
+ const dirLink = testDir + "/dirLink";
+ const danglingLink = testDir + "/danglingLink";
+ Deno.symlinkSync(file, fileLink);
+ Deno.symlinkSync(emptydir, dirLink);
+ Deno.symlinkSync(testDir + "/nonexistent", danglingLink);
+
+ assertThrows(
+ (): void => {
+ Deno.renameSync(olddir, fileLink);
+ },
+ Error,
+ "Not a directory"
+ );
+ assertThrows(
+ (): void => {
+ Deno.renameSync(olddir, dirLink);
+ },
+ Error,
+ "Not a directory"
+ );
+ assertThrows(
+ (): void => {
+ Deno.renameSync(olddir, danglingLink);
+ },
+ Error,
+ "Not a directory"
+ );
+
+ // should succeed on Unix
+ Deno.renameSync(olddir, emptydir);
+ Deno.renameSync(oldfile, dirLink);
+ Deno.renameSync(dirLink, danglingLink);
+ assertFile(danglingLink);
+ assertEquals("Hello", readFileString(danglingLink));
+ }
+);
+
+unitTest(
+ { ignore: Deno.build.os !== "win", perms: { read: true, write: true } },
+ function renameSyncErrorsWin(): void {
+ const testDir = Deno.makeTempDirSync();
+ const oldfile = testDir + "/oldfile";
+ const olddir = testDir + "/olddir";
+ const emptydir = testDir + "/empty";
+ const fulldir = testDir + "/dir";
+ const file = fulldir + "/file";
+ writeFileString(oldfile, "Hello");
+ Deno.mkdirSync(olddir);
+ Deno.mkdirSync(emptydir);
+ Deno.mkdirSync(fulldir);
+ writeFileString(file, "world");
+
+ assertThrows(
+ (): void => {
+ Deno.renameSync(oldfile, emptydir);
+ },
+ Deno.errors.PermissionDenied,
+ "Access is denied"
+ );
+ assertThrows(
+ (): void => {
+ Deno.renameSync(olddir, fulldir);
+ },
+ Deno.errors.PermissionDenied,
+ "Access is denied"
+ );
+ assertThrows(
+ (): void => {
+ Deno.renameSync(olddir, emptydir);
+ },
+ Deno.errors.PermissionDenied,
+ "Access is denied"
+ );
+
+ // should succeed on Windows
+ Deno.renameSync(olddir, file);
+ assertDirectory(file);
}
);