diff options
Diffstat (limited to 'tests/unit/rename_test.ts')
-rw-r--r-- | tests/unit/rename_test.ts | 274 |
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); + }, +); |