summaryrefslogtreecommitdiff
path: root/tests/unit/rename_test.ts
diff options
context:
space:
mode:
Diffstat (limited to 'tests/unit/rename_test.ts')
-rw-r--r--tests/unit/rename_test.ts274
1 files changed, 274 insertions, 0 deletions
diff --git a/tests/unit/rename_test.ts b/tests/unit/rename_test.ts
new file mode 100644
index 000000000..4f6bb09cf
--- /dev/null
+++ b/tests/unit/rename_test.ts
@@ -0,0 +1,274 @@
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+import {
+ assert,
+ assertEquals,
+ AssertionError,
+ assertIsError,
+ assertThrows,
+ pathToAbsoluteFileUrl,
+} from "./test_util.ts";
+
+function assertMissing(path: string) {
+ 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) {
+ const info = Deno.lstatSync(path);
+ assert(info.isFile);
+}
+
+function assertDirectory(path: string, mode?: number) {
+ const info = Deno.lstatSync(path);
+ assert(info.isDirectory);
+ if (Deno.build.os !== "windows" && mode !== undefined) {
+ assertEquals(info.mode! & 0o777, mode & ~Deno.umask());
+ }
+}
+
+Deno.test(
+ { permissions: { read: true, write: true } },
+ function renameSyncSuccess() {
+ const testDir = Deno.makeTempDirSync();
+ const oldpath = testDir + "/oldpath";
+ const newpath = testDir + "/newpath";
+ Deno.mkdirSync(oldpath);
+ Deno.renameSync(oldpath, newpath);
+ assertDirectory(newpath);
+ assertMissing(oldpath);
+ },
+);
+
+Deno.test(
+ { permissions: { read: true, write: true } },
+ function renameSyncWithURL() {
+ const testDir = Deno.makeTempDirSync();
+ const oldpath = testDir + "/oldpath";
+ const newpath = testDir + "/newpath";
+ Deno.mkdirSync(oldpath);
+ Deno.renameSync(
+ pathToAbsoluteFileUrl(oldpath),
+ pathToAbsoluteFileUrl(newpath),
+ );
+ assertDirectory(newpath);
+ assertMissing(oldpath);
+ },
+);
+
+Deno.test(
+ { permissions: { read: false, write: true } },
+ function renameSyncReadPerm() {
+ assertThrows(() => {
+ const oldpath = "/oldbaddir";
+ const newpath = "/newbaddir";
+ Deno.renameSync(oldpath, newpath);
+ }, Deno.errors.PermissionDenied);
+ },
+);
+
+Deno.test(
+ { permissions: { read: true, write: false } },
+ function renameSyncWritePerm() {
+ assertThrows(() => {
+ const oldpath = "/oldbaddir";
+ const newpath = "/newbaddir";
+ Deno.renameSync(oldpath, newpath);
+ }, Deno.errors.PermissionDenied);
+ },
+);
+
+Deno.test(
+ { permissions: { read: true, write: true } },
+ async function renameSuccess() {
+ const testDir = Deno.makeTempDirSync();
+ const oldpath = testDir + "/oldpath";
+ const newpath = testDir + "/newpath";
+ Deno.mkdirSync(oldpath);
+ await Deno.rename(oldpath, newpath);
+ assertDirectory(newpath);
+ assertMissing(oldpath);
+ },
+);
+
+Deno.test(
+ { permissions: { read: true, write: true } },
+ async function renameWithURL() {
+ const testDir = Deno.makeTempDirSync();
+ const oldpath = testDir + "/oldpath";
+ const newpath = testDir + "/newpath";
+ Deno.mkdirSync(oldpath);
+ await Deno.rename(
+ pathToAbsoluteFileUrl(oldpath),
+ pathToAbsoluteFileUrl(newpath),
+ );
+ assertDirectory(newpath);
+ assertMissing(oldpath);
+ },
+);
+
+function readFileString(filename: string): string {
+ const dataRead = Deno.readFileSync(filename);
+ const dec = new TextDecoder("utf-8");
+ return dec.decode(dataRead);
+}
+
+function writeFileString(filename: string, s: string) {
+ const enc = new TextEncoder();
+ const data = enc.encode(s);
+ Deno.writeFileSync(filename, data, { mode: 0o666 });
+}
+
+Deno.test(
+ {
+ ignore: Deno.build.os === "windows",
+ permissions: { read: true, write: true },
+ },
+ function renameSyncErrorsUnix() {
+ 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(
+ () => {
+ Deno.renameSync(oldfile, emptydir);
+ },
+ Error,
+ "Is a directory",
+ );
+ try {
+ assertThrows(
+ () => {
+ Deno.renameSync(olddir, fulldir);
+ },
+ Error,
+ "Directory not empty",
+ );
+ } catch (e) {
+ // rename syscall may also return EEXIST, e.g. with XFS
+ assertIsError(
+ e,
+ AssertionError,
+ `Expected error message to include "Directory not empty", but got "File exists`,
+ );
+ }
+ assertThrows(
+ () => {
+ Deno.renameSync(olddir, file);
+ },
+ Error,
+ "Not a directory",
+ );
+ assertThrows(
+ () => {
+ Deno.renameSync(olddir, file);
+ },
+ Error,
+ `rename '${olddir}' -> '${file}'`,
+ );
+
+ 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(
+ () => {
+ Deno.renameSync(olddir, fileLink);
+ },
+ Error,
+ "Not a directory",
+ );
+ assertThrows(
+ () => {
+ Deno.renameSync(olddir, dirLink);
+ },
+ Error,
+ "Not a directory",
+ );
+ assertThrows(
+ () => {
+ 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));
+ },
+);
+
+Deno.test(
+ {
+ ignore: Deno.build.os !== "windows",
+ permissions: { read: true, write: true },
+ },
+ function renameSyncErrorsWin() {
+ 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(
+ () => {
+ Deno.renameSync(oldfile, emptydir);
+ },
+ Deno.errors.PermissionDenied,
+ "Access is denied",
+ );
+ assertThrows(
+ () => {
+ Deno.renameSync(olddir, fulldir);
+ },
+ Deno.errors.PermissionDenied,
+ "Access is denied",
+ );
+ assertThrows(
+ () => {
+ Deno.renameSync(olddir, emptydir);
+ },
+ Deno.errors.PermissionDenied,
+ "Access is denied",
+ );
+ assertThrows(
+ () => {
+ Deno.renameSync(olddir, emptydir);
+ },
+ Error,
+ `rename '${olddir}' -> '${emptydir}'`,
+ );
+
+ // should succeed on Windows
+ Deno.renameSync(olddir, file);
+ assertDirectory(file);
+ },
+);