| /* |
| * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. |
| * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. |
| */ |
| |
| package kotlin.jdk7.test |
| |
| import java.io.IOException |
| import java.nio.file.* |
| import java.nio.file.attribute.* |
| import kotlin.io.path.* |
| import kotlin.random.Random |
| import kotlin.test.* |
| |
| class PathExtensionsTest : AbstractPathTest() { |
| private val isCaseInsensitiveFileSystem = Path("C:/") == Path("c:/") |
| private val isBackslashSeparator = FileSystems.getDefault().separator == "\\" |
| |
| @Test |
| fun filenameComponents() { |
| fun check(path: String, name: String, nameNoExt: String, extension: String) { |
| val p = Path(path) |
| assertEquals(name, p.name, "name") |
| assertEquals(nameNoExt, p.nameWithoutExtension, "nameWithoutExtension") |
| assertEquals(extension, p.extension, "extension") |
| } |
| |
| check(path = "aaa.bbb", name = "aaa.bbb", nameNoExt = "aaa", extension = "bbb") |
| check(path = "aaa", name = "aaa", nameNoExt = "aaa", extension = "") |
| check(path = "aaa.", name = "aaa.", nameNoExt = "aaa", extension = "") |
| check(path = ".aaa", name = ".aaa", nameNoExt = "", extension = "aaa") |
| check(path = "/dir.ext/aaa.bbb", name = "aaa.bbb", nameNoExt = "aaa", extension = "bbb") |
| check(path = "/dir.ext/aaa", name = "aaa", nameNoExt = "aaa", extension = "") |
| check(path = "/", name = "", nameNoExt = "", extension = "") |
| check(path = "", name = "", nameNoExt = "", extension = "") |
| } |
| |
| @Test |
| fun invariantSeparators() { |
| val path = Path("base") / "nested" / "leaf" |
| assertEquals("base/nested/leaf", path.invariantSeparatorsPathString) |
| |
| val path2 = Path("base", "nested", "terminal") |
| assertEquals("base/nested/terminal", path2.invariantSeparatorsPathString) |
| } |
| |
| @Test |
| fun createNewFile() { |
| val dir = createTempDirectory().cleanupRecursively() |
| |
| val file = dir / "new-file" |
| |
| assertTrue(file.notExists()) |
| |
| file.createFile() |
| assertTrue(file.exists()) |
| assertTrue(file.isRegularFile()) |
| |
| assertFailsWith<FileAlreadyExistsException> { file.createFile() } |
| } |
| |
| @Test |
| fun createParentDirectories() { |
| val dir = createTempDirectory().cleanupRecursively() |
| val file = dir / "test-dir" / "sub-dir" / "new-file" |
| val parent = file.parent!! |
| |
| assertTrue(file.notExists()) |
| assertTrue(parent.notExists()) |
| |
| val result = file.createParentDirectories() |
| assertTrue(file.notExists()) |
| assertTrue(parent.isDirectory()) |
| assertEquals(file, result) |
| |
| file.createFile() |
| file.createParentDirectories() |
| assertTrue(file.exists()) |
| assertTrue(parent.isDirectory()) |
| } |
| |
| @Test |
| fun createParentDirectoriesRelativePath() { |
| run { |
| val path = Path("test_path_without_parent") |
| path.createParentDirectories() |
| assertTrue(path.toAbsolutePath().parent!!.isDirectory()) |
| } |
| |
| run { |
| val path = Path("build/test_subdirectory/test_path") |
| val parent = path.parent!! |
| assertTrue(parent.notExists()) |
| parent.cleanupRecursively() |
| path.createParentDirectories() |
| assertTrue(path.notExists()) |
| assertTrue(parent.isDirectory()) |
| } |
| } |
| |
| @Test |
| fun createParentDirectoriesOverExistingSymlink() { |
| val root = createTempDirectory("createParent-root").cleanupRecursively() |
| val dir = (root / "dir").createDirectory() |
| val link = (root / "link").tryCreateSymbolicLinkTo(dir) ?: return |
| val file = (link / "file") |
| file.createParentDirectories().writeText("txt") |
| assertTrue((dir / "file").isRegularFile()) |
| } |
| |
| @Test |
| fun createTempFileDefaultDir() { |
| val file1 = createTempFile().cleanup() |
| val file2 = createTempFile(directory = null).cleanup() |
| |
| assertEquals(file1.parent, file2.parent) |
| } |
| |
| @Test |
| fun createTempDirectoryDefaultDir() { |
| val dir1 = createTempDirectory().cleanup() |
| val dir2 = createTempDirectory(directory = null).cleanupRecursively() |
| val dir3 = createTempDirectory(dir2) |
| |
| assertEquals(dir1.parent, dir2.parent) |
| assertNotEquals(dir2.parent, dir3.parent) |
| } |
| |
| @Test |
| fun copyTo() { |
| val root = createTempDirectory("copyTo-root").cleanupRecursively() |
| val srcFile = createTempFile(root, "src") |
| val dstFile = createTempFile(root, "dst") |
| |
| srcFile.writeText("Hello, World!") |
| assertFailsWith<FileAlreadyExistsException>("copy do not overwrite existing file") { |
| srcFile.copyTo(dstFile) |
| } |
| |
| var dst = srcFile.copyTo(dstFile, overwrite = true) |
| assertSame(dst, dstFile) |
| compareFiles(srcFile, dst, "copy with overwrite over existing file") |
| |
| srcFile.copyTo(srcFile) |
| srcFile.copyTo(srcFile, overwrite = true) |
| compareFiles(dst, srcFile, "copying file to itself leaves it intact") |
| |
| assertTrue(dstFile.deleteIfExists()) |
| dst = srcFile.copyTo(dstFile) |
| compareFiles(srcFile, dst, "copy to new file") |
| |
| val subDst = dstFile.resolve("foo/bar") |
| assertFailsWith<FileSystemException> { srcFile.copyTo(subDst) } |
| assertFailsWith<FileSystemException> { srcFile.copyTo(subDst, overwrite = true) } |
| assertTrue(dstFile.deleteIfExists()) |
| assertFailsWith<FileSystemException> { srcFile.copyTo(subDst) } |
| |
| dstFile.createDirectory() |
| val child = dstFile.resolve("child").createFile() |
| assertFailsWith<DirectoryNotEmptyException>("copy with overwrite do not overwrite non-empty dir") { |
| srcFile.copyTo(dstFile, overwrite = true) |
| } |
| child.deleteExisting() |
| |
| srcFile.copyTo(dstFile, overwrite = true) |
| assertEquals(srcFile.readText(), dstFile.readText(), "copy with overwrite over empty dir") |
| |
| assertTrue(srcFile.deleteIfExists()) |
| assertTrue(dstFile.deleteIfExists()) |
| |
| assertFailsWith<NoSuchFileException> { |
| srcFile.copyTo(dstFile) |
| } |
| |
| srcFile.createDirectory() |
| srcFile.resolve("somefile").writeText("some content") |
| dstFile.writeText("") |
| assertFailsWith<FileAlreadyExistsException>("copy dir do not overwrite file") { |
| srcFile.copyTo(dstFile) |
| } |
| srcFile.copyTo(dstFile, overwrite = true) |
| assertTrue(dstFile.isDirectory()) |
| assertTrue(dstFile.listDirectoryEntries().isEmpty(), "only directory is copied, but not its content") |
| |
| assertFailsWith<FileAlreadyExistsException>("copy dir do not overwrite dir") { |
| srcFile.copyTo(dstFile) |
| } |
| |
| srcFile.copyTo(dstFile, overwrite = true) |
| assertTrue(dstFile.isDirectory()) |
| assertTrue(dstFile.listDirectoryEntries().isEmpty(), "only directory is copied, but not its content") |
| |
| dstFile.resolve("somefile2").writeText("some content2") |
| assertFailsWith<DirectoryNotEmptyException>("copy dir do not overwrite non-empty dir") { |
| srcFile.copyTo(dstFile, overwrite = true) |
| } |
| } |
| |
| @Test |
| fun copyToRestrictedReadSource() { |
| val root = createTempDirectory("copyTo-root").cleanupRecursively() |
| |
| // copy file |
| val srcFile = createTempFile(root, "srcFile") |
| val dstFile = root.resolve("dstFile") |
| |
| withRestrictedRead(srcFile, alsoReset = listOf(dstFile)) { |
| assertFailsWith<AccessDeniedException> { srcFile.copyTo(dstFile) } // fails to copy restricted file |
| } |
| |
| // copy directory |
| val srcDirectory = createTempDirectory(root, "srcDirectory") |
| val dstDirectory = root.resolve("dstDirectory") |
| |
| withRestrictedRead(srcDirectory, alsoReset = listOf(dstDirectory)) { |
| srcDirectory.copyTo(dstDirectory) // successfully copies restricted directory |
| assertFalse(dstDirectory.isReadable()) // copies access permissions |
| } |
| } |
| |
| @Test |
| fun copyToRestrictedWriteDestination() { |
| val root = createTempDirectory("copyTo-root").cleanupRecursively() |
| |
| // copy file |
| val srcFile = createTempFile(root, "srcFile") |
| val dstFile = createTempFile(root, "dstFile") |
| |
| withRestrictedWrite(dstFile) { |
| assertFailsWith<FileAlreadyExistsException> { srcFile.copyTo(dstFile) } |
| try { |
| srcFile.copyTo(dstFile, overwrite = true) // successfully overwrites restricted file in Unix |
| assertTrue(dstFile.isWritable()) // copies access permissions |
| } catch (_: AccessDeniedException) { |
| // Windows does not allow to overwrite readonly file |
| } |
| } |
| |
| // copy directory |
| val srcDirectory = createTempDirectory(root, "srcDirectory") |
| val dstDirectory = createTempDirectory(root, "dstDirectory") |
| |
| withRestrictedWrite(dstDirectory) { |
| assertFailsWith<FileAlreadyExistsException> { srcDirectory.copyTo(dstDirectory) } |
| srcDirectory.copyTo(dstDirectory, overwrite = true) // successfully overwrites restricted directory |
| assertTrue(dstDirectory.isWritable()) // copies access permissions |
| } |
| } |
| |
| @Test |
| fun copyToSymlinkDestination() { |
| val root = createTempDirectory("copyTo-root").cleanupRecursively() |
| val targetFile = createTempFile(root, "targetFile").also { it.writeText("target file") } |
| val targetDirectory = createTempDirectory(root, "targetDirectory").also { it.resolve("a").createFile() } |
| |
| // copy file |
| val srcFile = createTempFile(root, "srcFile").also { it.writeText("source file") } |
| val dstFile = root.resolve("dstFile").tryCreateSymbolicLinkTo(targetFile) ?: return |
| |
| assertFailsWith<FileAlreadyExistsException> { |
| srcFile.copyTo(dstFile) |
| } |
| assertFailsWith<FileAlreadyExistsException> { |
| srcFile.copyTo(dstFile, LinkOption.NOFOLLOW_LINKS) |
| } |
| assertTrue(dstFile.isSymbolicLink()) |
| assertEquals("target file", dstFile.readText()) |
| |
| // copy directory |
| val srcDirectory = createTempDirectory(root, "srcDirectory") |
| val dstDirectory = root.resolve("dstDirectory").tryCreateSymbolicLinkTo(targetDirectory) ?: return |
| |
| assertFailsWith<FileAlreadyExistsException> { |
| srcDirectory.copyTo(dstDirectory) |
| } |
| assertFailsWith<FileAlreadyExistsException> { |
| srcDirectory.copyTo(dstDirectory, LinkOption.NOFOLLOW_LINKS) |
| } |
| assertTrue(dstDirectory.isSymbolicLink()) |
| assertEquals("a", dstDirectory.listDirectoryEntries().single().name) |
| |
| // overwrite file |
| srcFile.copyTo(dstFile, overwrite = true) |
| assertFalse(dstFile.isSymbolicLink()) |
| assertEquals("source file", dstFile.readText()) |
| assertEquals("target file", targetFile.readText()) |
| |
| dstFile.deleteExisting() |
| dstFile.tryCreateSymbolicLinkTo(targetFile)!! |
| srcFile.copyTo(dstFile, StandardCopyOption.REPLACE_EXISTING, LinkOption.NOFOLLOW_LINKS) |
| assertFalse(dstFile.isSymbolicLink()) |
| assertEquals("source file", dstFile.readText()) |
| assertEquals("target file", targetFile.readText()) |
| |
| // overwrite directory |
| srcDirectory.copyTo(dstDirectory, overwrite = true) |
| assertFalse(dstDirectory.isSymbolicLink()) |
| assertEquals(emptyList(), dstDirectory.listDirectoryEntries()) |
| assertEquals("a", targetDirectory.listDirectoryEntries().single().name) |
| |
| dstDirectory.deleteExisting() |
| dstDirectory.tryCreateSymbolicLinkTo(targetDirectory)!! |
| srcDirectory.copyTo(dstDirectory, StandardCopyOption.REPLACE_EXISTING, LinkOption.NOFOLLOW_LINKS) |
| assertFalse(dstDirectory.isSymbolicLink()) |
| assertEquals(emptyList(), dstDirectory.listDirectoryEntries()) |
| assertEquals("a", targetDirectory.listDirectoryEntries().single().name) |
| } |
| |
| @Test |
| fun copyToBrokenSymlinkDestination() { |
| val root = createTempDirectory("copyTo-root").cleanupRecursively() |
| val symlinkTarget = root.resolve("target") |
| |
| // copy file |
| val srcFile = createTempFile(root, "srcFile").also { it.writeText("source file") } |
| val dstFile = root.resolve("dstFile").tryCreateSymbolicLinkTo(symlinkTarget) ?: return |
| |
| assertFailsWith<FileAlreadyExistsException> { |
| srcFile.copyTo(dstFile) |
| } |
| assertFailsWith<FileAlreadyExistsException> { |
| srcFile.copyTo(dstFile, LinkOption.NOFOLLOW_LINKS) |
| } |
| assertTrue(dstFile.isSymbolicLink()) |
| assertFailsWith<NoSuchFileException> { |
| dstFile.readText() |
| } |
| |
| // copy directory |
| val srcDirectory = createTempDirectory(root, "srcDirectory") |
| val dstDirectory = root.resolve("dstDirectory").tryCreateSymbolicLinkTo(symlinkTarget) ?: return |
| |
| assertFailsWith<FileAlreadyExistsException> { |
| srcDirectory.copyTo(dstDirectory) |
| } |
| assertFailsWith<FileAlreadyExistsException> { |
| srcDirectory.copyTo(dstDirectory, LinkOption.NOFOLLOW_LINKS) |
| } |
| assertTrue(dstDirectory.isSymbolicLink()) |
| assertFailsWith<FileSystemException> { // Fails with NoSuchFileException in Unix, NotDirectoryException in Windows. |
| dstDirectory.listDirectoryEntries() |
| } |
| |
| // overwrite file |
| srcFile.copyTo(dstFile, overwrite = true) |
| assertFalse(dstFile.isSymbolicLink()) |
| assertEquals("source file", dstFile.readText()) |
| |
| dstFile.deleteExisting() |
| dstFile.tryCreateSymbolicLinkTo(symlinkTarget)!! |
| srcFile.copyTo(dstFile, StandardCopyOption.REPLACE_EXISTING, LinkOption.NOFOLLOW_LINKS) |
| assertFalse(dstFile.isSymbolicLink()) |
| assertEquals("source file", dstFile.readText()) |
| |
| // overwrite directory |
| srcDirectory.copyTo(dstDirectory, overwrite = true) |
| assertFalse(dstDirectory.isSymbolicLink()) |
| assertEquals(emptyList(), dstDirectory.listDirectoryEntries()) |
| |
| dstDirectory.deleteExisting() |
| dstDirectory.tryCreateSymbolicLinkTo(symlinkTarget)!! |
| srcDirectory.copyTo(dstDirectory, StandardCopyOption.REPLACE_EXISTING, LinkOption.NOFOLLOW_LINKS) |
| assertFalse(dstDirectory.isSymbolicLink()) |
| assertEquals(emptyList(), dstDirectory.listDirectoryEntries()) |
| } |
| |
| @Test |
| fun copyToNameWithoutParent() { |
| val currentDir = Path("").absolute() |
| val srcFile = createTempFile().cleanup() |
| val dstFile = createTempFile(directory = currentDir).cleanup() |
| |
| srcFile.writeText("Hello, World!", Charsets.UTF_8) |
| dstFile.deleteExisting() |
| |
| val dstRelative = Path(dstFile.name) |
| |
| srcFile.copyTo(dstRelative) |
| |
| assertEquals(srcFile.readText(), dstFile.readText()) |
| } |
| |
| @Test |
| fun copyToDstLinkPointingToSrc() { |
| for (options in listOf(arrayOf(), arrayOf<CopyOption>(LinkOption.NOFOLLOW_LINKS))) { |
| val root = createTempDirectory().cleanupRecursively() |
| val src = root.resolve("src").createFile() |
| val dstLink = root.resolve("dstLink").tryCreateSymbolicLinkTo(src) ?: return |
| |
| assertTrue(src.isSameFileAs(dstLink)) |
| assertTrue(dstLink.isSameFileAs(src)) |
| assertFailsWith<FileAlreadyExistsException> { |
| src.copyTo(dstLink, *options) |
| } |
| assertTrue(dstLink.isSymbolicLink()) |
| } |
| } |
| |
| @Test |
| fun copyToDstLinkPointingToSrcOverwrite() { |
| for (options in listOf(arrayOf(), arrayOf<CopyOption>(LinkOption.NOFOLLOW_LINKS))) { |
| val root = createTempDirectory().cleanupRecursively() |
| val src = root.resolve("src").createFile() |
| val dstLink = root.resolve("dstLink").tryCreateSymbolicLinkTo(src) ?: return |
| |
| src.copyTo(dstLink, StandardCopyOption.REPLACE_EXISTING, *options) |
| assertFalse(dstLink.isSymbolicLink()) |
| } |
| } |
| |
| @Test |
| fun copyToSrcLinkAndDstLinkPointingToSameFile() { |
| for (options in listOf(arrayOf(), arrayOf<CopyOption>(LinkOption.NOFOLLOW_LINKS))) { |
| val root = createTempDirectory().cleanupRecursively() |
| val original = root.resolve("original").createFile() |
| val srcLink = root.resolve("srcLink").tryCreateSymbolicLinkTo(original) ?: return |
| val dstLink = root.resolve("dstLink").tryCreateSymbolicLinkTo(original) ?: return |
| |
| assertTrue(srcLink.isSameFileAs(dstLink)) |
| assertTrue(dstLink.isSameFileAs(srcLink)) |
| assertFailsWith<FileAlreadyExistsException> { |
| srcLink.copyTo(dstLink, *options) |
| } |
| assertTrue(dstLink.isSymbolicLink()) |
| } |
| } |
| |
| @Test |
| fun copyToSrcLinkAndDstLinkPointingToSameFileOverwrite() { |
| for (options in listOf(arrayOf(), arrayOf<CopyOption>(LinkOption.NOFOLLOW_LINKS))) { |
| val root = createTempDirectory().cleanupRecursively() |
| val original = root.resolve("original").createFile() |
| val srcLink = root.resolve("srcLink").tryCreateSymbolicLinkTo(original) ?: return |
| val dstLink = root.resolve("dstLink").tryCreateSymbolicLinkTo(original) ?: return |
| |
| srcLink.copyTo(dstLink, StandardCopyOption.REPLACE_EXISTING, *options) |
| |
| if (LinkOption.NOFOLLOW_LINKS in options) { |
| assertTrue(dstLink.isSymbolicLink()) // src symlink was copied |
| } else { |
| assertFalse(dstLink.isSymbolicLink()) // src symlink target was copied |
| } |
| } |
| } |
| |
| @Test |
| fun copyToSameLinkDifferentRoute() { |
| for (options in listOf(arrayOf(), arrayOf<CopyOption>(LinkOption.NOFOLLOW_LINKS))) { |
| val root = createTempDirectory().cleanupRecursively() |
| val original = root.resolve("original").createFile() |
| val srcLink = root.resolve("srcLink").tryCreateSymbolicLinkTo(original) ?: return |
| val dstLink = root.resolve("dstLink").tryCreateSymbolicLinkTo(root)?.resolve("srcLink") ?: return |
| |
| assertTrue(srcLink.isSameFileAs(dstLink)) |
| assertTrue(dstLink.isSameFileAs(srcLink)) |
| |
| if (LinkOption.NOFOLLOW_LINKS in options) { |
| srcLink.copyTo(dstLink, *options) // same file |
| } else { |
| assertFailsWith<FileAlreadyExistsException> { |
| srcLink.copyTo(dstLink, *options) // target of srcLink copied to srcLink location |
| } |
| } |
| |
| assertTrue(dstLink.isSymbolicLink()) |
| } |
| } |
| |
| @Test |
| fun copyToSameLinkDifferentRouteOverwrite() { |
| for (options in listOf(arrayOf(), arrayOf<CopyOption>(LinkOption.NOFOLLOW_LINKS))) { |
| val root = createTempDirectory().cleanupRecursively() |
| val original = root.resolve("original").createFile() |
| val srcLink = root.resolve("srcLink").tryCreateSymbolicLinkTo(original) ?: return |
| val dstLink = root.resolve("dstLink").tryCreateSymbolicLinkTo(root)?.resolve("srcLink") ?: return |
| |
| if (LinkOption.NOFOLLOW_LINKS in options) { |
| srcLink.copyTo(dstLink, StandardCopyOption.REPLACE_EXISTING, *options) // same file |
| } else { |
| // dstLink is deleted before srcLink gets copied. |
| // Actually srcLink gets removed because dstLink is srcLink with different path. |
| val error = assertFailsWith<NoSuchFileException> { |
| srcLink.copyTo(dstLink, StandardCopyOption.REPLACE_EXISTING, *options) |
| } |
| assertEquals(srcLink.toString(), error.file) |
| assertFalse(srcLink.exists(LinkOption.NOFOLLOW_LINKS)) |
| assertFalse(dstLink.exists(LinkOption.NOFOLLOW_LINKS)) |
| } |
| } |
| } |
| |
| @Test |
| fun copyToSameFileDifferentRoute() { |
| val root = createTempDirectory().cleanupRecursively() |
| val src = root.resolve("src").createFile() |
| val dst = root.resolve("dstLink").tryCreateSymbolicLinkTo(root)?.resolve("src") ?: return |
| |
| assertTrue(src.isSameFileAs(dst)) |
| assertTrue(dst.isSameFileAs(src)) |
| src.copyTo(dst) |
| } |
| |
| @Test |
| fun copyToSameFileDifferentRouteOverwrite() { |
| val root = createTempDirectory().cleanupRecursively() |
| val src = root.resolve("src").createFile() |
| val dst = root.resolve("dstLink").tryCreateSymbolicLinkTo(root)?.resolve("src") ?: return |
| |
| src.copyTo(dst, overwrite = true) |
| } |
| |
| @Test |
| fun moveTo() { |
| val root = createTempDirectory("moveTo-root").cleanupRecursively() |
| val original = createTempFile(root, "original") |
| val srcFile = createTempFile(root, "src") |
| val dstFile = createTempFile(root, "dst") |
| fun restoreSrcFile() { original.copyTo(srcFile, overwrite = true) } |
| original.writeText("Hello, World!") |
| restoreSrcFile() |
| |
| assertFailsWith<FileAlreadyExistsException>("do not overwrite existing file") { |
| srcFile.moveTo(dstFile) |
| } |
| |
| var dst = srcFile.moveTo(dstFile, overwrite = true) |
| assertSame(dst, dstFile) |
| compareFiles(original, dst, "move with overwrite over existing file") |
| assertTrue(srcFile.notExists()) |
| |
| restoreSrcFile() |
| srcFile.moveTo(srcFile) |
| srcFile.moveTo(srcFile, overwrite = true) |
| |
| compareFiles(original, srcFile, "move file to itself leaves it intact") |
| |
| assertTrue(dstFile.deleteIfExists()) |
| dst = srcFile.moveTo(dstFile) |
| compareFiles(original, dst, "move to new file") |
| |
| restoreSrcFile() |
| val subDst = dstFile.resolve("foo/bar") |
| assertFailsWith<FileSystemException> { srcFile.moveTo(subDst) } |
| assertFailsWith<FileSystemException> { srcFile.moveTo(subDst, overwrite = true) } |
| assertTrue(dstFile.deleteIfExists()) |
| assertFailsWith<FileSystemException> { srcFile.moveTo(subDst) } |
| |
| dstFile.createDirectory() |
| val child = dstFile.resolve("child").createFile() |
| assertFailsWith<DirectoryNotEmptyException>("move with overwrite do not overwrite non-empty dir") { |
| srcFile.moveTo(dstFile, overwrite = true) |
| } |
| child.deleteExisting() |
| |
| srcFile.moveTo(dstFile, overwrite = true) |
| compareFiles(original, dstFile, "move with overwrite over empty dir") |
| |
| assertTrue(srcFile.notExists()) |
| assertTrue(dstFile.deleteIfExists()) |
| |
| assertFailsWith<NoSuchFileException> { |
| srcFile.moveTo(dstFile) |
| } |
| |
| srcFile.createDirectory() |
| srcFile.resolve("somefile").writeText("some content") |
| dstFile.writeText("") |
| assertFailsWith<FileAlreadyExistsException>("move dir do not overwrite file") { |
| srcFile.moveTo(dstFile) |
| } |
| srcFile.moveTo(dstFile, overwrite = true) |
| assertTrue(dstFile.isDirectory()) |
| assertEquals(listOf(dstFile / "somefile"), dstFile.listDirectoryEntries(), "directory is moved with its content") |
| } |
| |
| private fun compareFiles(src: Path, dst: Path, message: String? = null) { |
| assertTrue(dst.exists()) |
| assertEquals(src.isRegularFile(), dst.isRegularFile(), message) |
| assertEquals(src.isDirectory(), dst.isDirectory(), message) |
| if (dst.isRegularFile()) { |
| assertTrue(src.readBytes().contentEquals(dst.readBytes()), message) |
| } |
| } |
| |
| @Test |
| fun fileSize() { |
| val file = createTempFile().cleanup() |
| assertEquals(0, file.fileSize()) |
| |
| file.writeBytes(ByteArray(100)) |
| assertEquals(100, file.fileSize()) |
| |
| file.appendText("Hello", Charsets.US_ASCII) |
| assertEquals(105, file.fileSize()) |
| |
| file.deleteExisting() |
| assertFailsWith<NoSuchFileException> { file.fileSize() } |
| } |
| |
| @Test |
| fun deleteExisting() { |
| val file = createTempFile().cleanup() |
| file.deleteExisting() |
| assertFailsWith<NoSuchFileException> { file.deleteExisting() } |
| |
| val dir = createTempDirectory().cleanup() |
| dir.deleteExisting() |
| assertFailsWith<NoSuchFileException> { dir.deleteExisting() } |
| } |
| |
| @Test |
| fun deleteIfExists() { |
| val file = createTempFile().cleanup() |
| assertTrue(file.deleteIfExists()) |
| assertFalse(file.deleteIfExists()) |
| |
| val dir = createTempDirectory().cleanup() |
| assertTrue(dir.deleteIfExists()) |
| assertFalse(dir.deleteIfExists()) |
| } |
| |
| @Test |
| fun attributeGettersOnFile() { |
| val file = createTempFile("temp", ".file").cleanup() |
| assertTrue(file.exists()) |
| assertFalse(file.notExists()) |
| assertTrue(file.isRegularFile()) |
| assertFalse(file.isDirectory()) |
| assertFalse(file.isSymbolicLink()) |
| assertTrue(file.isReadable()) |
| assertTrue(file.isWritable()) |
| assertTrue(file.isSameFileAs(file)) |
| |
| // The default value of these depends on the current operating system, so just check that |
| // they don't throw an exception. |
| file.isExecutable() |
| file.isHidden() |
| } |
| |
| @Test |
| fun attributeGettersOnDirectory() { |
| val file = createTempDirectory(".tmpdir").cleanup() |
| assertTrue(file.exists()) |
| assertFalse(file.notExists()) |
| assertFalse(file.isRegularFile()) |
| assertTrue(file.isDirectory()) |
| assertFalse(file.isSymbolicLink()) |
| assertTrue(file.isReadable()) |
| assertTrue(file.isWritable()) |
| assertTrue(file.isSameFileAs(file)) |
| |
| file.isExecutable() |
| file.isHidden() |
| } |
| |
| @Test |
| fun attributeGettersOnNonExistentPath() { |
| val file = createTempDirectory().cleanup().resolve("foo") |
| assertFalse(file.exists()) |
| assertTrue(file.notExists()) |
| assertFalse(file.isRegularFile()) |
| assertFalse(file.isDirectory()) |
| assertFalse(file.isSymbolicLink()) |
| assertFalse(file.isReadable()) |
| assertFalse(file.isWritable()) |
| assertTrue(file.isSameFileAs(file)) |
| |
| file.isExecutable() |
| // This function will either throw an exception or return false, |
| // depending on the operating system. |
| try { |
| assertFalse(file.isHidden()) |
| } catch (e: IOException) { |
| } |
| } |
| |
| private interface SpecialFileAttributesView : FileAttributeView |
| private interface SpecialFileAttributes : BasicFileAttributes |
| |
| @Test |
| fun readWriteAttributes() { |
| val file = createTempFile().cleanup() |
| val modifiedTime = file.getLastModifiedTime() |
| assertEquals(modifiedTime, file.getAttribute("lastModifiedTime")) |
| assertEquals(modifiedTime, file.getAttribute("basic:lastModifiedTime")) |
| assertEquals(modifiedTime, file.readAttributes<BasicFileAttributes>().lastModifiedTime()) |
| assertEquals(modifiedTime, file.readAttributes("basic:lastModifiedTime,creationTime")["lastModifiedTime"]) |
| assertEquals(modifiedTime, file.readAttributes("*")["lastModifiedTime"]) |
| |
| assertFailsWith<UnsupportedOperationException> { file.readAttributes<SpecialFileAttributes>() } |
| assertFailsWith<UnsupportedOperationException> { file.readAttributes("really_unsupported_view:*") } |
| assertFailsWith<IllegalArgumentException> { file.readAttributes("basic:really_unknown_attribute") } |
| |
| val newTime1 = FileTime.fromMillis(modifiedTime.toMillis() + 3600_000) |
| file.setLastModifiedTime(newTime1) |
| assertEquals(newTime1, file.getLastModifiedTime()) |
| |
| val newTime2 = FileTime.fromMillis(modifiedTime.toMillis() + 2 * 3600_000) |
| file.setAttribute("lastModifiedTime", newTime2) |
| assertEquals(newTime2, file.getLastModifiedTime()) |
| |
| val newTime3 = FileTime.fromMillis(modifiedTime.toMillis() + 3 * 3600_000) |
| file.fileAttributesView<BasicFileAttributeView>().setTimes(newTime3, null, null) |
| assertEquals(newTime3, file.getLastModifiedTime()) |
| |
| assertFailsWith<UnsupportedOperationException> { file.fileAttributesView<SpecialFileAttributesView>() } |
| assertNull(file.fileAttributesViewOrNull<SpecialFileAttributesView>()) |
| |
| file.setAttribute("lastModifiedTime", null) |
| assertEquals(newTime3, file.getLastModifiedTime()) |
| } |
| |
| @Test |
| fun links() { |
| val dir = createTempDirectory().cleanupRecursively() |
| val original = createTempFile(dir) |
| original.writeBytes(Random.nextBytes(100)) |
| |
| val link = try { |
| (dir / ("link-" + original.fileName)).createLinkPointingTo(original) |
| } catch (e: IOException) { |
| // may require a privilege |
| println("Creating a link failed with $e") |
| return |
| } |
| |
| assertTrue(link.isRegularFile()) |
| assertTrue(link.isRegularFile(LinkOption.NOFOLLOW_LINKS)) |
| assertTrue(original.isSameFileAs(link)) |
| compareFiles(original, link) |
| assertFailsWith<NotLinkException> { link.readSymbolicLink() } |
| } |
| |
| @Test |
| fun symlinks() { |
| val dir = createTempDirectory().cleanupRecursively() |
| val original = createTempFile(dir) |
| original.writeBytes(Random.nextBytes(100)) |
| |
| val symlink = try { |
| (dir / ("symlink-" + original.fileName)).createSymbolicLinkPointingTo(original) |
| } catch (e: IOException) { |
| // may require a privilege |
| println("Creating a symlink failed with $e") |
| return |
| } |
| |
| assertTrue(symlink.isRegularFile()) |
| assertFalse(symlink.isRegularFile(LinkOption.NOFOLLOW_LINKS)) |
| assertTrue(original.isSameFileAs(symlink)) |
| compareFiles(original, symlink) |
| assertEquals(original, symlink.readSymbolicLink()) |
| } |
| |
| @Test |
| fun directoryEntriesList() { |
| val dir = createTempDirectory().cleanupRecursively() |
| assertEquals(0, dir.listDirectoryEntries().size) |
| |
| val file = dir.resolve("f1").createFile() |
| assertEquals(listOf(file), dir.listDirectoryEntries()) |
| |
| val fileTxt = createTempFile(dir, suffix = ".txt") |
| assertEquals(listOf(fileTxt), dir.listDirectoryEntries("*.txt")) |
| |
| assertFailsWith<NotDirectoryException> { file.listDirectoryEntries() } |
| } |
| |
| @Test |
| fun directoryEntriesUseSequence() { |
| val dir = createTempDirectory().cleanupRecursively() |
| assertEquals(0, dir.useDirectoryEntries { it.toList() }.size) |
| |
| val file = dir.resolve("f1").createFile() |
| assertEquals(listOf(file), dir.useDirectoryEntries { it.toList() }) |
| |
| val fileTxt = createTempFile(dir, suffix = ".txt") |
| assertEquals(listOf(fileTxt), dir.useDirectoryEntries("*.txt") { it.toList() }) |
| |
| assertFailsWith<NotDirectoryException> { file.useDirectoryEntries { error("shouldn't get here") } } |
| } |
| |
| @Test |
| fun directoryEntriesForEach() { |
| val dir = createTempDirectory().cleanupRecursively() |
| dir.forEachDirectoryEntry { error("shouldn't get here, but received $it") } |
| |
| val file = createTempFile(dir) |
| dir.forEachDirectoryEntry { assertEquals(file, it) } |
| |
| val fileTxt = createTempFile(dir, suffix = ".txt") |
| dir.forEachDirectoryEntry("*.txt") { assertEquals(fileTxt, it) } |
| |
| assertFailsWith<NotDirectoryException> { file.forEachDirectoryEntry { error("shouldn't get here, but received $it") } } |
| } |
| |
| |
| private fun testRelativeTo(expected: String?, path: String, base: String) = |
| testRelativeTo(expected?.let { Path(it) }, Path(path), Path(base)) |
| private fun testRelativeTo(expected: String, path: Path, base: Path) = |
| testRelativeTo(Path(expected), path, base) |
| |
| private fun testRelativeTo(expected: Path?, path: Path, base: Path) { |
| val context = "path: '$path', base: '$base'" |
| if (expected != null) { |
| assertEquals(expected, path.relativeTo(base), context) |
| } else { |
| val e = assertFailsWith<IllegalArgumentException>(context) { path.relativeTo(base) } |
| val message = assertNotNull(e.message) |
| assertTrue(path.toString() in message, message) |
| assertTrue(base.toString() in message, message) |
| } |
| assertEquals(expected, path.relativeToOrNull(base), context) |
| assertEquals(expected ?: path, path.relativeToOrSelf(base), context) |
| } |
| |
| @Test |
| fun relativeToRooted() { |
| val file1 = "/foo/bar/baz" |
| val file2 = "/foo/baa/ghoo" |
| |
| testRelativeTo("../../bar/baz", file1, file2) |
| |
| val file3 = "/foo/bar" |
| |
| testRelativeTo("baz", file1, file3) |
| testRelativeTo("..", file3, file1) |
| |
| val file4 = "/foo/bar/" |
| |
| testRelativeTo("baz", file1, file4) |
| testRelativeTo("..", file4, file1) |
| testRelativeTo("", file3, file4) |
| testRelativeTo("", file4, file3) |
| |
| val file5 = "/foo/baran" |
| |
| testRelativeTo("../bar", file3, file5) |
| testRelativeTo("../baran", file5, file3) |
| testRelativeTo("../bar", file4, file5) |
| testRelativeTo("../baran", file5, file4) |
| |
| if (isBackslashSeparator) { |
| val file6 = "C:\\Users\\Me" |
| val file7 = "C:\\Users\\Me\\Documents" |
| |
| testRelativeTo("..", file6, file7) |
| testRelativeTo("Documents", file7, file6) |
| |
| val file8 = """\\my.host\home/user/documents/vip""" |
| val file9 = """\\my.host\home/other/images/nice""" |
| |
| testRelativeTo("../../../user/documents/vip", file8, file9) |
| testRelativeTo("../../../other/images/nice", file9, file8) |
| } |
| |
| if (isCaseInsensitiveFileSystem) { |
| testRelativeTo("bar", "C:/bar", "c:/") |
| } |
| } |
| |
| @Test |
| fun relativeToRelative() { |
| val nested = Path("foo/bar") |
| val base = Path("foo") |
| |
| testRelativeTo("bar", nested, base) |
| testRelativeTo("..", base, nested) |
| |
| val empty = Path("") |
| val current = Path(".") |
| val parent = Path("..") |
| val outOfRoot = Path("../bar") |
| |
| testRelativeTo("../bar", outOfRoot, empty) |
| testRelativeTo("../../bar", outOfRoot, base) |
| testRelativeTo("bar", outOfRoot, parent) |
| testRelativeTo("..", parent, outOfRoot) |
| |
| val root = Path("/root") |
| val files = listOf(nested, base, empty, outOfRoot, current, parent) |
| val bases = listOf(nested, base, empty, current) |
| |
| for (file in files) |
| // file should have empty path relative to itself |
| testRelativeTo("", file, file) |
| |
| for (file in files) { |
| @Suppress("NAME_SHADOWING") |
| for (base in bases) { |
| val rootedFile = root.resolve(file) |
| val rootedBase = root.resolve(base) |
| assertEquals(rootedFile.relativeTo(rootedBase), file.relativeTo(base), "nested: $file, base: $base") |
| } |
| } |
| } |
| |
| @Test |
| fun relativeToFails() { |
| val absolute = Path("/foo/bar/baz") |
| val relative = Path("foo/bar") |
| val networkShare1 = Path("""\\my.host\share1/folder""") |
| val networkShare2 = Path("""\\my.host\share2\folder""") |
| |
| val allFiles = listOf(absolute, relative) + if (isBackslashSeparator) listOf(networkShare1, networkShare2) else emptyList() |
| for (file in allFiles) { |
| for (base in allFiles) { |
| if (file != base) testRelativeTo(null, file, base) |
| } |
| } |
| |
| if (isBackslashSeparator) { |
| testRelativeTo(null, "C:/dir1", "D:/dir2") |
| } |
| |
| testRelativeTo(null, "foo", "..") |
| testRelativeTo(null, "../foo", "../..") |
| } |
| |
| @Test |
| fun relativeTo() { |
| testRelativeTo("kotlin", "src/kotlin", "src") |
| testRelativeTo("", "dir", "dir") |
| testRelativeTo("..", "dir", "dir/subdir") |
| testRelativeTo("../../test", "test", "dir/dir") |
| testRelativeTo("foo/bar", "../../foo/bar", "../../sub/../.") |
| testRelativeTo(null, "../../foo/bar", "../../sub/../..") |
| } |
| |
| @Test |
| fun absolutePaths() { |
| val relative = Path("./example") |
| assertTrue(relative.absolute().isAbsolute) |
| assertEquals(relative.absolute().pathString, relative.absolutePathString()) |
| } |
| } |