stdlib tests: move JVM-only test source files
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
|
||||
@file:kotlin.jvm.JvmVersion
|
||||
package test.io
|
||||
|
||||
import org.junit.Test
|
||||
import java.nio.charset.Charset
|
||||
import kotlin.test.*
|
||||
|
||||
class ConsoleTest {
|
||||
private val linuxLineSeparator: String = "\n"
|
||||
private val windowsLineSeparator: String = "\r\n"
|
||||
|
||||
@Test
|
||||
fun shouldReadEmptyLine() {
|
||||
testReadLine("", emptyList())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldReadSingleLine() {
|
||||
for (length in 1..3) {
|
||||
val line = buildString { repeat(length) { append('a' + it) } }
|
||||
testReadLine(line, listOf(line))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun trailingEmptyLineIsIgnored() {
|
||||
testReadLine(linuxLineSeparator, listOf(""))
|
||||
testReadLine(windowsLineSeparator, listOf(""))
|
||||
testReadLine("a$linuxLineSeparator", listOf("a"))
|
||||
testReadLine("a$windowsLineSeparator", listOf("a"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldReadOneLine() {
|
||||
testReadLine("first", listOf("first"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldReadTwoLines() {
|
||||
testReadLine("first${linuxLineSeparator}second", listOf("first", "second"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldReadConsecutiveEmptyLines() {
|
||||
testReadLine("$linuxLineSeparator$linuxLineSeparator", listOf("", ""))
|
||||
testReadLine("$linuxLineSeparator$windowsLineSeparator", listOf("", ""))
|
||||
testReadLine("$windowsLineSeparator$linuxLineSeparator", listOf("", ""))
|
||||
testReadLine("$windowsLineSeparator$windowsLineSeparator", listOf("", ""))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldReadWindowsLineSeparator() {
|
||||
testReadLine("first${windowsLineSeparator}second", listOf("first", "second"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldReadMultibyteEncodings() {
|
||||
testReadLine("first${linuxLineSeparator}second", listOf("first", "second"), charset = Charsets.UTF_32)
|
||||
}
|
||||
|
||||
private fun testReadLine(text: String, expected: List<String>, charset: Charset = Charsets.UTF_8) {
|
||||
val actual = readLines(text, charset)
|
||||
assertEquals(expected, actual)
|
||||
val referenceExpected = readLinesReference(text, charset)
|
||||
assertEquals(referenceExpected, actual, "Comparing to reference readLine")
|
||||
|
||||
}
|
||||
|
||||
private fun readLines(text: String, charset: Charset): List<String> {
|
||||
text.byteInputStream(charset).use { stream ->
|
||||
val decoder = charset.newDecoder()
|
||||
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
|
||||
return generateSequence { readLine(stream, decoder) }.toList().also {
|
||||
assertTrue("All bytes should be read") { stream.read() == -1 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun readLinesReference(text: String, charset: Charset): List<String> {
|
||||
text.byteInputStream(charset).bufferedReader(charset).use { reader ->
|
||||
return generateSequence { reader.readLine() }.toList()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,458 @@
|
||||
@file:kotlin.jvm.JvmVersion
|
||||
package test.io
|
||||
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.util.*
|
||||
import kotlin.test.*
|
||||
|
||||
class FileTreeWalkTest {
|
||||
|
||||
companion object {
|
||||
val referenceFilenames =
|
||||
listOf("1", "1/2", "1/3", "1/3/4.txt", "1/3/5.txt", "6", "7.txt", "8", "8/9.txt")
|
||||
fun createTestFiles(): File {
|
||||
val basedir = createTempDir()
|
||||
for (name in referenceFilenames) {
|
||||
val file = basedir.resolve(name)
|
||||
if (file.extension.isEmpty())
|
||||
file.mkdir()
|
||||
else
|
||||
file.createNewFile()
|
||||
}
|
||||
return basedir
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun withSimple() {
|
||||
val basedir = createTestFiles()
|
||||
try {
|
||||
val referenceNames = setOf("") + referenceFilenames
|
||||
val namesTopDown = HashSet<String>()
|
||||
for (file in basedir.walkTopDown()) {
|
||||
val name = file.relativeToOrSelf(basedir).invariantSeparatorsPath
|
||||
assertFalse(namesTopDown.contains(name), "$name is visited twice")
|
||||
namesTopDown.add(name)
|
||||
}
|
||||
assertEquals(referenceNames, namesTopDown)
|
||||
val namesBottomUp = HashSet<String>()
|
||||
for (file in basedir.walkBottomUp()) {
|
||||
val name = file.relativeToOrSelf(basedir).invariantSeparatorsPath
|
||||
assertFalse(namesBottomUp.contains(name), "$name is visited twice")
|
||||
namesBottomUp.add(name)
|
||||
}
|
||||
assertEquals(referenceNames, namesBottomUp)
|
||||
} finally {
|
||||
basedir.deleteRecursively()
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun singleFile() {
|
||||
val testFile = createTempFile()
|
||||
val nonExistantFile = testFile.resolve("foo")
|
||||
try {
|
||||
for (walk in listOf(File::walkTopDown, File::walkBottomUp)) {
|
||||
assertEquals(testFile, walk(testFile).single(), "${walk.name}")
|
||||
assertEquals(testFile, testFile.walk().onEnter { false }.single(), "${walk.name} - enter should not be called for single file")
|
||||
|
||||
assertTrue(walk(nonExistantFile).none(), "${walk.name} - enter should not be called for single file")
|
||||
}
|
||||
}
|
||||
finally {
|
||||
testFile.delete()
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun withEnterLeave() {
|
||||
val basedir = createTestFiles()
|
||||
try {
|
||||
val referenceNames =
|
||||
setOf("", "1", "1/2", "6", "8")
|
||||
val namesTopDownEnter = HashSet<String>()
|
||||
val namesTopDownLeave = HashSet<String>()
|
||||
val namesTopDown = HashSet<String>()
|
||||
fun enter(file: File): Boolean {
|
||||
val name = file.relativeToOrSelf(basedir).invariantSeparatorsPath
|
||||
assertTrue(file.isDirectory, "$name is not directory, only directories should be entered")
|
||||
assertFalse(namesTopDownEnter.contains(name), "$name is entered twice")
|
||||
assertFalse(namesTopDownLeave.contains(name), "$name is left before entrance")
|
||||
if (file.name == "3") return false // filter out 3
|
||||
namesTopDownEnter.add(name)
|
||||
return true
|
||||
}
|
||||
|
||||
fun leave(file: File) {
|
||||
val name = file.relativeToOrSelf(basedir).invariantSeparatorsPath
|
||||
assertTrue(file.isDirectory, "$name is not directory, only directories should be left")
|
||||
assertFalse(namesTopDownLeave.contains(name), "$name is left twice")
|
||||
namesTopDownLeave.add(name)
|
||||
assertTrue(namesTopDownEnter.contains(name), "$name is left before entrance")
|
||||
}
|
||||
|
||||
fun visit(file: File) {
|
||||
val name = file.relativeToOrSelf(basedir).invariantSeparatorsPath
|
||||
if (file.isDirectory) {
|
||||
assertTrue(namesTopDownEnter.contains(name), "$name is visited before entrance")
|
||||
namesTopDown.add(name)
|
||||
assertFalse(namesTopDownLeave.contains(name), "$name is visited after leaving")
|
||||
}
|
||||
if (file == basedir)
|
||||
return
|
||||
val parent = file.parentFile
|
||||
if (parent != null) {
|
||||
val parentName = parent.relativeToOrSelf(basedir).invariantSeparatorsPath
|
||||
assertTrue(namesTopDownEnter.contains(parentName),
|
||||
"$name is visited before entering its parent $parentName")
|
||||
assertFalse(namesTopDownLeave.contains(parentName),
|
||||
"$name is visited after leaving its parent $parentName")
|
||||
}
|
||||
}
|
||||
for (file in basedir.walkTopDown().onEnter(::enter).onLeave(::leave)) {
|
||||
visit(file)
|
||||
}
|
||||
assertEquals(referenceNames, namesTopDownEnter)
|
||||
assertEquals(referenceNames, namesTopDownLeave)
|
||||
namesTopDownEnter.clear()
|
||||
namesTopDownLeave.clear()
|
||||
namesTopDown.clear()
|
||||
for (file in basedir.walkBottomUp().onEnter(::enter).onLeave(::leave)) {
|
||||
visit(file)
|
||||
}
|
||||
assertEquals(referenceNames, namesTopDownEnter)
|
||||
assertEquals(referenceNames, namesTopDownLeave)
|
||||
} finally {
|
||||
basedir.deleteRecursively()
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun withFilterAndMap() {
|
||||
val basedir = createTestFiles()
|
||||
try {
|
||||
val referenceNames = setOf("", "1", "1/2", "1/3", "6", "8")
|
||||
assertEquals(referenceNames, basedir.walkTopDown().filter { it.isDirectory }.map {
|
||||
it.relativeToOrSelf(basedir).invariantSeparatorsPath
|
||||
}.toHashSet())
|
||||
} finally {
|
||||
basedir.deleteRecursively()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test fun withDeleteTxtTopDown() {
|
||||
val basedir = createTestFiles()
|
||||
try {
|
||||
val referenceNames = setOf("", "1", "1/2", "1/3", "6", "8")
|
||||
val namesTopDown = HashSet<String>()
|
||||
fun enter(file: File) {
|
||||
assertTrue(file.isDirectory)
|
||||
for (child in file.listFiles()) {
|
||||
if (child.name.endsWith("txt"))
|
||||
child.delete()
|
||||
}
|
||||
}
|
||||
for (file in basedir.walkTopDown().onEnter { enter(it); true }) {
|
||||
val name = file.relativeToOrSelf(basedir).invariantSeparatorsPath
|
||||
assertFalse(namesTopDown.contains(name), "$name is visited twice")
|
||||
namesTopDown.add(name)
|
||||
}
|
||||
assertEquals(referenceNames, namesTopDown)
|
||||
} finally {
|
||||
basedir.deleteRecursively()
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun withDeleteTxtBottomUp() {
|
||||
val basedir = createTestFiles()
|
||||
try {
|
||||
val referenceNames = setOf("", "1", "1/2", "1/3", "6", "8")
|
||||
val namesTopDown = HashSet<String>()
|
||||
fun enter(file: File) {
|
||||
assertTrue(file.isDirectory)
|
||||
for (child in file.listFiles()) {
|
||||
if (child.name.endsWith("txt"))
|
||||
child.delete()
|
||||
}
|
||||
}
|
||||
for (file in basedir.walkBottomUp().onEnter { enter(it); true }) {
|
||||
val name = file.relativeToOrSelf(basedir).invariantSeparatorsPath
|
||||
assertFalse(namesTopDown.contains(name), "$name is visited twice")
|
||||
namesTopDown.add(name)
|
||||
}
|
||||
assertEquals(referenceNames, namesTopDown)
|
||||
} finally {
|
||||
basedir.deleteRecursively()
|
||||
}
|
||||
}
|
||||
|
||||
private fun compareWalkResults(expected: Set<String>, basedir: File, filter: (File) -> Boolean) {
|
||||
val namesTopDown = HashSet<String>()
|
||||
for (file in basedir.walkTopDown().onEnter { filter(it) }) {
|
||||
val name = file.toRelativeString(basedir)
|
||||
assertFalse(namesTopDown.contains(name), "$name is visited twice")
|
||||
namesTopDown.add(name)
|
||||
}
|
||||
assertEquals(expected, namesTopDown, "Top-down walk results differ")
|
||||
val namesBottomUp = HashSet<String>()
|
||||
for (file in basedir.walkBottomUp().onEnter { filter(it) }) {
|
||||
val name = file.toRelativeString(basedir)
|
||||
assertFalse(namesBottomUp.contains(name), "$name is visited twice")
|
||||
namesBottomUp.add(name)
|
||||
}
|
||||
assertEquals(expected, namesBottomUp, "Bottom-up walk results differ")
|
||||
}
|
||||
|
||||
@Test fun withDirectoryFilter() {
|
||||
val basedir = createTestFiles()
|
||||
try {
|
||||
// Every directory ended with 3 and its content is filtered out
|
||||
fun filter(file: File): Boolean = !file.name.endsWith("3")
|
||||
|
||||
val referenceNames = listOf("", "1", "1/2", "6", "7.txt", "8", "8/9.txt").map { File(it).path }.toSet()
|
||||
compareWalkResults(referenceNames, basedir, ::filter)
|
||||
} finally {
|
||||
basedir.deleteRecursively()
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun withTotalDirectoryFilter() {
|
||||
val basedir = createTestFiles()
|
||||
try {
|
||||
val referenceNames = emptySet<String>()
|
||||
compareWalkResults(referenceNames, basedir, { false })
|
||||
} finally {
|
||||
basedir.deleteRecursively()
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun withForEach() {
|
||||
val basedir = createTestFiles()
|
||||
try {
|
||||
var i = 0
|
||||
basedir.walkTopDown().forEach { _ -> i++ }
|
||||
assertEquals(10, i);
|
||||
i = 0
|
||||
basedir.walkBottomUp().forEach { _ -> i++ }
|
||||
assertEquals(10, i);
|
||||
} finally {
|
||||
basedir.deleteRecursively()
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun withCount() {
|
||||
val basedir = createTestFiles()
|
||||
try {
|
||||
assertEquals(10, basedir.walkTopDown().count());
|
||||
assertEquals(10, basedir.walkBottomUp().count());
|
||||
} finally {
|
||||
basedir.deleteRecursively()
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun withReduce() {
|
||||
val basedir = createTestFiles()
|
||||
try {
|
||||
val res = basedir.walkTopDown().reduce { a, b -> if (a.canonicalPath > b.canonicalPath) a else b }
|
||||
assertTrue(res.endsWith("9.txt"), "Expected end with 9.txt actual: ${res.name}")
|
||||
} finally {
|
||||
basedir.deleteRecursively()
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun withVisitorAndDepth() {
|
||||
val basedir = createTestFiles()
|
||||
try {
|
||||
val files = HashSet<File>()
|
||||
val dirs = HashSet<File>()
|
||||
val failed = HashSet<String>()
|
||||
val stack = ArrayList<File>()
|
||||
fun beforeVisitDirectory(dir: File): Boolean {
|
||||
stack.add(dir)
|
||||
dirs.add(dir.relativeToOrSelf(basedir))
|
||||
return true
|
||||
}
|
||||
|
||||
fun afterVisitDirectory(dir: File) {
|
||||
assertEquals(stack.last(), dir)
|
||||
stack.removeAt(stack.lastIndex)
|
||||
}
|
||||
|
||||
fun visitFile(file: File) {
|
||||
assertTrue(stack.last().listFiles().contains(file), file.toString())
|
||||
files.add(file.relativeToOrSelf(basedir))
|
||||
}
|
||||
|
||||
fun visitDirectoryFailed(dir: File, @Suppress("UNUSED_PARAMETER") e: IOException) {
|
||||
assertEquals(stack.last(), dir)
|
||||
//stack.removeAt(stack.lastIndex)
|
||||
failed.add(dir.name)
|
||||
}
|
||||
basedir.walkTopDown().onEnter(::beforeVisitDirectory).onLeave(::afterVisitDirectory).
|
||||
onFail(::visitDirectoryFailed).forEach { it -> if (!it.isDirectory) visitFile(it) }
|
||||
assertTrue(stack.isEmpty())
|
||||
for (fileName in arrayOf("", "1", "1/2", "1/3", "6", "8")) {
|
||||
assertTrue(dirs.contains(File(fileName)), fileName)
|
||||
}
|
||||
for (fileName in arrayOf("1/3/4.txt", "1/3/4.txt", "7.txt", "8/9.txt")) {
|
||||
assertTrue(files.contains(File(fileName)), fileName)
|
||||
}
|
||||
|
||||
//limit maxDepth
|
||||
files.clear()
|
||||
dirs.clear()
|
||||
basedir.walkTopDown().onEnter(::beforeVisitDirectory).onLeave(::afterVisitDirectory).maxDepth(1).
|
||||
forEach { it -> if (it != basedir) visitFile(it) }
|
||||
assertTrue(stack.isEmpty())
|
||||
assertEquals(setOf(File("")), dirs)
|
||||
for (file in arrayOf("1", "6", "7.txt", "8")) {
|
||||
assertTrue(files.contains(File(file)), file.toString())
|
||||
}
|
||||
|
||||
//restrict access
|
||||
if (File(basedir, "1").setReadable(false)) {
|
||||
try {
|
||||
files.clear()
|
||||
dirs.clear()
|
||||
basedir.walkTopDown().onEnter(::beforeVisitDirectory).onLeave(::afterVisitDirectory).
|
||||
onFail(::visitDirectoryFailed).forEach { it -> if (!it.isDirectory) visitFile(it) }
|
||||
assertTrue(stack.isEmpty())
|
||||
assertEquals(setOf("1"), failed)
|
||||
assertEquals(listOf("", "1", "6", "8").map { File(it) }.toSet(), dirs)
|
||||
assertEquals(listOf("7.txt", "8/9.txt").map { File(it) }.toSet(), files)
|
||||
} finally {
|
||||
File(basedir, "1").setReadable(true)
|
||||
}
|
||||
} else {
|
||||
System.err.println("cannot restrict access")
|
||||
}
|
||||
} finally {
|
||||
basedir.deleteRecursively()
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun topDown() {
|
||||
val basedir = createTestFiles()
|
||||
try {
|
||||
val visited = HashSet<File>()
|
||||
val block: (File) -> Unit = {
|
||||
assertTrue(!visited.contains(it), it.toString())
|
||||
assertTrue(it == basedir && visited.isEmpty() || visited.contains(it.parentFile), it.toString())
|
||||
visited.add(it)
|
||||
}
|
||||
basedir.walkTopDown().forEach(block)
|
||||
assertEquals(10, visited.size)
|
||||
} finally {
|
||||
basedir.deleteRecursively()
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun restrictedAccess() {
|
||||
val basedir = createTestFiles()
|
||||
val restricted = File(basedir, "1")
|
||||
try {
|
||||
if (restricted.setReadable(false)) {
|
||||
val visited = HashSet<File>()
|
||||
val block: (File) -> Unit = {
|
||||
assertTrue(!visited.contains(it), it.toString())
|
||||
assertTrue(it == basedir && visited.isEmpty() || visited.contains(it.parentFile), it.toString())
|
||||
visited.add(it)
|
||||
}
|
||||
basedir.walkTopDown().forEach(block)
|
||||
assertEquals(6, visited.size)
|
||||
}
|
||||
} finally {
|
||||
restricted.setReadable(true)
|
||||
basedir.deleteRecursively()
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun backup() {
|
||||
var count = 0
|
||||
fun makeBackup(file: File) {
|
||||
count++
|
||||
val bakFile = File(file.toString() + ".bak")
|
||||
file.copyTo(bakFile)
|
||||
}
|
||||
|
||||
val basedir1 = createTestFiles()
|
||||
try {
|
||||
basedir1.walkTopDown().forEach {
|
||||
if (it.isFile) {
|
||||
makeBackup(it)
|
||||
}
|
||||
}
|
||||
assertEquals(4, count)
|
||||
} finally {
|
||||
basedir1.deleteRecursively()
|
||||
}
|
||||
|
||||
count = 0
|
||||
val basedir2 = createTestFiles()
|
||||
try {
|
||||
basedir2.walkTopDown().forEach {
|
||||
if (it.isFile) {
|
||||
makeBackup(it)
|
||||
}
|
||||
}
|
||||
assertEquals(4, count)
|
||||
} finally {
|
||||
basedir2.deleteRecursively()
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun find() {
|
||||
val basedir = createTestFiles()
|
||||
try {
|
||||
File(basedir, "8/4.txt").createNewFile()
|
||||
var count = 0
|
||||
basedir.walkTopDown().takeWhile { _ -> count == 0 }.forEach {
|
||||
if (it.name == "4.txt") {
|
||||
count++
|
||||
}
|
||||
}
|
||||
assertEquals(1, count)
|
||||
} finally {
|
||||
basedir.deleteRecursively()
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun findGits() {
|
||||
val basedir = createTestFiles()
|
||||
try {
|
||||
File(basedir, "1/3/.git").mkdir()
|
||||
File(basedir, "1/2/.git").mkdir()
|
||||
File(basedir, "6/.git").mkdir()
|
||||
val found = HashSet<File>()
|
||||
for (file in basedir.walkTopDown()) {
|
||||
if (file.name == ".git") {
|
||||
found.add(file.parentFile)
|
||||
}
|
||||
}
|
||||
assertEquals(3, found.size)
|
||||
} finally {
|
||||
basedir.deleteRecursively()
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun streamFileTree() {
|
||||
val dir = createTempDir()
|
||||
try {
|
||||
val subDir1 = createTempDir(prefix = "d1_", directory = dir)
|
||||
val subDir2 = createTempDir(prefix = "d2_", directory = dir)
|
||||
createTempDir(prefix = "d1_", directory = subDir1)
|
||||
createTempFile(prefix = "f1_", directory = subDir1)
|
||||
createTempDir(prefix = "d1_", directory = subDir2)
|
||||
assertEquals(6, dir.walkTopDown().count())
|
||||
} finally {
|
||||
dir.deleteRecursively()
|
||||
}
|
||||
dir.mkdir()
|
||||
try {
|
||||
val it = dir.walkTopDown().iterator()
|
||||
it.next()
|
||||
assertFailsWith<NoSuchElementException>("Second call to next() should fail.") { it.next() }
|
||||
} finally {
|
||||
dir.delete()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,621 @@
|
||||
@file:kotlin.jvm.JvmVersion
|
||||
package test.io
|
||||
|
||||
import java.io.*
|
||||
import java.util.*
|
||||
import kotlin.io.walkTopDown
|
||||
import kotlin.test.*
|
||||
|
||||
class FilesTest {
|
||||
|
||||
private val isCaseInsensitiveFileSystem = File("C:/") == File("c:/")
|
||||
private val isBackslashSeparator = File.separatorChar == '\\'
|
||||
|
||||
|
||||
@Test fun testPath() {
|
||||
val fileSuf = System.currentTimeMillis().toString()
|
||||
val file1 = createTempFile("temp", fileSuf)
|
||||
assertTrue(file1.path.endsWith(fileSuf), file1.path)
|
||||
}
|
||||
|
||||
@Test fun testCreateTempDir() {
|
||||
val dirSuf = System.currentTimeMillis().toString()
|
||||
val dir1 = createTempDir("temp", dirSuf)
|
||||
assertTrue(dir1.exists() && dir1.isDirectory && dir1.name.startsWith("temp") && dir1.name.endsWith(dirSuf))
|
||||
assertFailsWith(IllegalArgumentException::class) {
|
||||
createTempDir("a")
|
||||
}
|
||||
|
||||
val dir2 = createTempDir("temp")
|
||||
assertTrue(dir2.exists() && dir2.isDirectory && dir2.name.endsWith(".tmp"))
|
||||
|
||||
val dir3 = createTempDir()
|
||||
assertTrue(dir3.exists() && dir3.isDirectory)
|
||||
|
||||
dir1.delete()
|
||||
dir2.delete()
|
||||
dir3.delete()
|
||||
}
|
||||
|
||||
@Test fun testCreateTempFile() {
|
||||
val fileSuf = System.currentTimeMillis().toString()
|
||||
val file1 = createTempFile("temp", fileSuf)
|
||||
assertTrue(file1.exists() && file1.name.startsWith("temp") && file1.name.endsWith(fileSuf))
|
||||
assertFailsWith(IllegalArgumentException::class) {
|
||||
createTempFile("a")
|
||||
}
|
||||
|
||||
val file2 = createTempFile("temp")
|
||||
assertTrue(file2.exists() && file2.name.endsWith(".tmp"))
|
||||
|
||||
val file3 = createTempFile()
|
||||
assertTrue(file3.exists())
|
||||
|
||||
file1.delete()
|
||||
file2.delete()
|
||||
file3.delete()
|
||||
}
|
||||
|
||||
@Test fun listFilesWithFilter() {
|
||||
val dir = createTempDir("temp")
|
||||
|
||||
createTempFile("temp1", ".kt", dir)
|
||||
createTempFile("temp2", ".java", dir)
|
||||
createTempFile("temp3", ".kt", dir)
|
||||
|
||||
// This line works only with Kotlin File.listFiles(filter)
|
||||
val result = dir.listFiles { it -> it.name.endsWith(".kt") } // todo ambiguity on SAM
|
||||
assertEquals(2, result!!.size)
|
||||
// This line works both with Kotlin File.listFiles(filter) and the same Java function because of SAM
|
||||
val result2 = dir.listFiles { it -> it.name.endsWith(".kt") }
|
||||
assertEquals(2, result2!!.size)
|
||||
}
|
||||
|
||||
@Test fun relativeToRooted() {
|
||||
val file1 = File("/foo/bar/baz")
|
||||
val file2 = File("/foo/baa/ghoo")
|
||||
|
||||
assertEquals("../../bar/baz", file1.relativeTo(file2).invariantSeparatorsPath)
|
||||
|
||||
val file3 = File("/foo/bar")
|
||||
|
||||
assertEquals("baz", file1.toRelativeString(file3))
|
||||
assertEquals("..", file3.toRelativeString(file1))
|
||||
|
||||
val file4 = File("/foo/bar/")
|
||||
|
||||
assertEquals("baz", file1.toRelativeString(file4))
|
||||
assertEquals("..", file4.toRelativeString(file1))
|
||||
assertEquals("", file3.toRelativeString(file4))
|
||||
assertEquals("", file4.toRelativeString(file3))
|
||||
|
||||
val file5 = File("/foo/baran")
|
||||
|
||||
assertEquals("../bar", file3.relativeTo(file5).invariantSeparatorsPath)
|
||||
assertEquals("../baran", file5.relativeTo(file3).invariantSeparatorsPath)
|
||||
assertEquals("../bar", file4.relativeTo(file5).invariantSeparatorsPath)
|
||||
assertEquals("../baran", file5.relativeTo(file4).invariantSeparatorsPath)
|
||||
|
||||
if (isBackslashSeparator) {
|
||||
val file6 = File("C:\\Users\\Me")
|
||||
val file7 = File("C:\\Users\\Me\\Documents")
|
||||
|
||||
assertEquals("..", file6.toRelativeString(file7))
|
||||
assertEquals("Documents", file7.toRelativeString(file6))
|
||||
|
||||
val file8 = File("""\\my.host\home/user/documents/vip""")
|
||||
val file9 = File("""\\my.host\home/other/images/nice""")
|
||||
|
||||
assertEquals("../../../user/documents/vip", file8.relativeTo(file9).invariantSeparatorsPath)
|
||||
assertEquals("../../../other/images/nice", file9.relativeTo(file8).invariantSeparatorsPath)
|
||||
}
|
||||
|
||||
if (isCaseInsensitiveFileSystem) {
|
||||
assertEquals("bar", File("C:/bar").toRelativeString(File("c:/")))
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun relativeToRelative() {
|
||||
val nested = File("foo/bar")
|
||||
val base = File("foo")
|
||||
|
||||
assertEquals("bar", nested.toRelativeString(base))
|
||||
assertEquals("..", base.toRelativeString(nested))
|
||||
|
||||
val empty = File("")
|
||||
val current = File(".")
|
||||
val parent = File("..")
|
||||
val outOfRoot = File("../bar")
|
||||
|
||||
assertEquals(File("../bar"), outOfRoot.relativeTo(empty))
|
||||
assertEquals(File("../../bar"), outOfRoot.relativeTo(base))
|
||||
assertEquals("bar", outOfRoot.toRelativeString(parent))
|
||||
assertEquals("..", parent.toRelativeString(outOfRoot))
|
||||
|
||||
val root = File("/root")
|
||||
val files = listOf(nested, base, empty, outOfRoot, current, parent)
|
||||
val bases = listOf(nested, base, empty, current)
|
||||
|
||||
for (file in files)
|
||||
assertEquals("", file.toRelativeString(file), "file should have empty path relative to itself: $file")
|
||||
|
||||
for (file in files) {
|
||||
@Suppress("NAME_SHADOWING")
|
||||
for (base in bases) {
|
||||
val rootedFile = root.resolve(file)
|
||||
val rootedBase = root.resolve(base)
|
||||
assertEquals(file.relativeTo(base), rootedFile.relativeTo(rootedBase), "nested: $file, base: $base")
|
||||
assertEquals(file.toRelativeString(base), rootedFile.toRelativeString(rootedBase), "strings, nested: $file, base: $base")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun relativeToFails() {
|
||||
val absolute = File("/foo/bar/baz")
|
||||
val relative = File("foo/bar")
|
||||
val networkShare1 = File("""\\my.host\share1/folder""")
|
||||
val networkShare2 = File("""\\my.host\share2\folder""")
|
||||
|
||||
fun assertFailsRelativeTo(file: File, base: File) {
|
||||
val e = assertFailsWith<IllegalArgumentException>("file: $file, base: $base") { file.relativeTo(base) }
|
||||
val message = assertNotNull(e.message)
|
||||
assert(file.toString() in message)
|
||||
assert(base.toString() in message)
|
||||
}
|
||||
|
||||
val allFiles = listOf(absolute, relative) + if (isBackslashSeparator) listOf(networkShare1, networkShare2) else emptyList()
|
||||
for (file in allFiles) {
|
||||
for (base in allFiles) {
|
||||
if (file != base) assertFailsRelativeTo(file, base)
|
||||
}
|
||||
}
|
||||
|
||||
assertFailsRelativeTo(File("y"), File("../x"))
|
||||
|
||||
if (isBackslashSeparator) {
|
||||
val fileOnC = File("C:/dir1")
|
||||
val fileOnD = File("D:/dir2")
|
||||
assertFailsRelativeTo(fileOnC, fileOnD)
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun relativeTo() {
|
||||
assertEquals("kotlin", File("src/kotlin").toRelativeString(File("src")))
|
||||
assertEquals("", File("dir").toRelativeString(File("dir")))
|
||||
assertEquals("..", File("dir").toRelativeString(File("dir/subdir")))
|
||||
assertEquals(File("../../test"), File("test").relativeTo(File("dir/dir")))
|
||||
}
|
||||
|
||||
@Suppress("INVISIBLE_MEMBER")
|
||||
private fun checkFilePathComponents(f: File, root: File, elements: List<String>) {
|
||||
assertEquals(root, f.root)
|
||||
val components = f.toComponents()
|
||||
assertEquals(root, components.root)
|
||||
assertEquals(elements, components.segments.map { it.toString() })
|
||||
}
|
||||
|
||||
@Test fun filePathComponents() {
|
||||
checkFilePathComponents(File("/foo/bar"), File("/"), listOf("foo", "bar"))
|
||||
checkFilePathComponents(File("/foo/bar/gav"), File("/"), listOf("foo", "bar", "gav"))
|
||||
checkFilePathComponents(File("/foo/bar/gav/"), File("/"), listOf("foo", "bar", "gav"))
|
||||
checkFilePathComponents(File("bar/gav"), File(""), listOf("bar", "gav"))
|
||||
checkFilePathComponents(File("C:/bar/gav"), File("C:/"), listOf("bar", "gav"))
|
||||
checkFilePathComponents(File("C:/"), File("C:/"), listOf())
|
||||
checkFilePathComponents(File("C:"), File("C:"), listOf())
|
||||
if (isBackslashSeparator) {
|
||||
// Check only in Windows
|
||||
checkFilePathComponents(File("\\\\host.ru\\home\\mike"), File("\\\\host.ru\\home"), listOf("mike"))
|
||||
checkFilePathComponents(File("//host.ru/home/mike"), File("//host.ru/home"), listOf("mike"))
|
||||
checkFilePathComponents(File("\\foo\\bar"), File("\\"), listOf("foo", "bar"))
|
||||
checkFilePathComponents(File("C:\\bar\\gav"), File("C:\\"), listOf("bar", "gav"))
|
||||
checkFilePathComponents(File("C:\\"), File("C:\\"), listOf())
|
||||
}
|
||||
checkFilePathComponents(File(""), File(""), listOf())
|
||||
checkFilePathComponents(File("."), File(""), listOf("."))
|
||||
checkFilePathComponents(File(".."), File(""), listOf(".."))
|
||||
}
|
||||
|
||||
@Test fun fileRoot() {
|
||||
val rooted = File("/foo/bar")
|
||||
assertTrue(rooted.isRooted)
|
||||
// assertEquals("/", rooted.root.invariantSeparatorsPath)
|
||||
|
||||
if (isBackslashSeparator) {
|
||||
val diskRooted = File("""C:\foo\bar""")
|
||||
assertTrue(diskRooted.isRooted)
|
||||
// assertEquals("""C:\""", diskRooted.rootName)
|
||||
|
||||
val networkRooted = File("""\\network\share\""")
|
||||
assertTrue(networkRooted.isRooted)
|
||||
// assertEquals("""\\network\share""", networkRooted.rootName)
|
||||
}
|
||||
|
||||
val relative = File("foo/bar")
|
||||
assertFalse(relative.isRooted)
|
||||
// assertEquals("", relative.rootName)
|
||||
}
|
||||
|
||||
@Test fun startsWith() {
|
||||
assertTrue(File("foo/bar").startsWith(File("foo/bar")))
|
||||
assertTrue(File("foo/bar").startsWith(File("foo")))
|
||||
assertTrue(File("foo/bar").startsWith(""))
|
||||
assertFalse(File("foo/bar").startsWith(File("/")))
|
||||
assertFalse(File("foo/bar").startsWith(File("/foo")))
|
||||
assertFalse(File("foo/bar").startsWith("fo"))
|
||||
|
||||
assertTrue(File("/foo/bar").startsWith(File("/foo/bar")))
|
||||
assertTrue(File("/foo/bar").startsWith(File("/foo")))
|
||||
assertTrue(File("/foo/bar").startsWith("/"))
|
||||
assertFalse(File("/foo/bar").startsWith(""))
|
||||
assertFalse(File("/foo/bar").startsWith(File("foo")))
|
||||
assertFalse(File("/foo/bar").startsWith("/fo"))
|
||||
|
||||
if (isBackslashSeparator) {
|
||||
assertTrue(File("C:\\Users\\Me\\Temp\\Game").startsWith("C:\\Users\\Me"))
|
||||
assertFalse(File("C:\\Users\\Me\\Temp\\Game").startsWith("C:\\Users\\He"))
|
||||
assertTrue(File("C:\\Users\\Me").startsWith("C:\\"))
|
||||
}
|
||||
if (isCaseInsensitiveFileSystem) {
|
||||
assertTrue(File("C:\\Users\\Me").startsWith("c:\\"))
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun endsWith() {
|
||||
assertTrue(File("/foo/bar").endsWith("bar"))
|
||||
assertTrue(File("/foo/bar").endsWith("foo/bar"))
|
||||
assertTrue(File("/foo/bar").endsWith("/foo/bar"))
|
||||
assertTrue(File("foo/bar").endsWith("foo/bar"))
|
||||
assertTrue(File("foo/bar").endsWith("bar/"))
|
||||
|
||||
assertFalse(File("/foo/bar").endsWith("ar"))
|
||||
assertFalse(File("/foo/bar").endsWith("/bar"))
|
||||
assertFalse(File("/foo/bar/gav/bar").endsWith("/bar"))
|
||||
assertFalse(File("/foo/bar/gav/bar").endsWith("/gav/bar"))
|
||||
assertFalse(File("/foo/bar/gav").endsWith("/bar"))
|
||||
assertFalse(File("foo/bar").endsWith("/bar"))
|
||||
if (isCaseInsensitiveFileSystem) {
|
||||
assertTrue(File("/foo/bar").endsWith("Bar"))
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@Test fun subPath() {
|
||||
if (isBackslashSeparator) {
|
||||
// Check only in Windows
|
||||
assertEquals(File("mike"), File("//my.host.net/home/mike/temp").subPath(0, 1))
|
||||
assertEquals(File("mike"), File("\\\\my.host.net\\home\\mike\\temp").subPath(0, 1))
|
||||
}
|
||||
assertEquals(File("bar/gav"), File("/foo/bar/gav/hi").subPath(1, 3))
|
||||
assertEquals(File("foo"), File("/foo/bar/gav/hi").subPath(0, 1))
|
||||
assertEquals(File("gav/hi"), File("/foo/bar/gav/hi").subPath(2, 4))
|
||||
}
|
||||
*/
|
||||
|
||||
@Test fun normalize() {
|
||||
assertEquals(File("/foo/bar/baaz"), File("/foo/./bar/gav/../baaz").normalize())
|
||||
assertEquals(File("/foo/bar/baaz"), File("/foo/bak/../bar/gav/../baaz").normalize())
|
||||
assertEquals(File("../../bar"), File("../foo/../../bar").normalize())
|
||||
// For Unix C:\windows is not correct so it's not the same as C:/windows
|
||||
if (isBackslashSeparator) {
|
||||
assertEquals(File("C:\\windows"), File("C:\\home\\..\\documents\\..\\windows").normalize())
|
||||
assertEquals(File("C:/windows"), File("C:/home/../documents/../windows").normalize())
|
||||
}
|
||||
assertEquals(File("foo"), File("gav/bar/../../foo").normalize())
|
||||
assertEquals(File("/../foo"), File("/bar/../../foo").normalize())
|
||||
}
|
||||
|
||||
@Test fun resolve() {
|
||||
assertEquals(File("/foo/bar/gav"), File("/foo/bar").resolve("gav"))
|
||||
assertEquals(File("/foo/bar/gav"), File("/foo/bar/").resolve("gav"))
|
||||
assertEquals(File("/gav"), File("/foo/bar").resolve("/gav"))
|
||||
// For Unix C:\path is not correct so it's cannot be automatically converted
|
||||
if (isBackslashSeparator) {
|
||||
assertEquals(File("C:\\Users\\Me\\Documents\\important.doc"),
|
||||
File("C:\\Users\\Me").resolve("Documents\\important.doc"))
|
||||
assertEquals(File("C:/Users/Me/Documents/important.doc"),
|
||||
File("C:/Users/Me").resolve("Documents/important.doc"))
|
||||
}
|
||||
assertEquals(File(""), File("").resolve(""))
|
||||
assertEquals(File("bar"), File("").resolve("bar"))
|
||||
assertEquals(File("foo/bar"), File("foo").resolve("bar"))
|
||||
// should it normalize such paths?
|
||||
// assertEquals(File("bar"), File("foo").resolve("../bar"))
|
||||
// assertEquals(File("../bar"), File("foo").resolve("../../bar"))
|
||||
// assertEquals(File("foo/bar"), File("foo").resolve("./bar"))
|
||||
}
|
||||
|
||||
@Test fun resolveSibling() {
|
||||
assertEquals(File("/foo/gav"), File("/foo/bar").resolveSibling("gav"))
|
||||
assertEquals(File("/foo/gav"), File("/foo/bar/").resolveSibling("gav"))
|
||||
assertEquals(File("/gav"), File("/foo/bar").resolveSibling("/gav"))
|
||||
// For Unix C:\path is not correct so it's cannot be automatically converted
|
||||
if (isBackslashSeparator) {
|
||||
assertEquals(File("C:\\Users\\Me\\Documents\\important.doc"),
|
||||
File("C:\\Users\\Me\\profile.ini").resolveSibling("Documents\\important.doc"))
|
||||
assertEquals(File("C:/Users/Me/Documents/important.doc"),
|
||||
File("C:/Users/Me/profile.ini").resolveSibling("Documents/important.doc"))
|
||||
}
|
||||
assertEquals(File("gav"), File("foo").resolveSibling("gav"))
|
||||
assertEquals(File("../gav"), File("").resolveSibling("gav"))
|
||||
}
|
||||
|
||||
@Test fun extension() {
|
||||
assertEquals("bbb", File("aaa.bbb").extension)
|
||||
assertEquals("", File("aaa").extension)
|
||||
assertEquals("", File("aaa.").extension)
|
||||
// maybe we should think that such files have name .bbb and no extension
|
||||
assertEquals("bbb", File(".bbb").extension)
|
||||
assertEquals("", File("/my.dir/log").extension)
|
||||
}
|
||||
|
||||
@Test fun nameWithoutExtension() {
|
||||
assertEquals("aaa", File("aaa.bbb").nameWithoutExtension)
|
||||
assertEquals("aaa", File("aaa").nameWithoutExtension)
|
||||
assertEquals("aaa", File("aaa.").nameWithoutExtension)
|
||||
assertEquals("", File(".bbb").nameWithoutExtension)
|
||||
assertEquals("log", File("/my.dir/log").nameWithoutExtension)
|
||||
}
|
||||
|
||||
@Test fun testCopyTo() {
|
||||
val srcFile = createTempFile()
|
||||
val dstFile = createTempFile()
|
||||
try {
|
||||
srcFile.writeText("Hello, World!")
|
||||
assertFailsWith(FileAlreadyExistsException::class, "copy do not overwrite existing file") {
|
||||
srcFile.copyTo(dstFile)
|
||||
}
|
||||
|
||||
var dst = srcFile.copyTo(dstFile, overwrite = true)
|
||||
assertTrue(dst === dstFile)
|
||||
compareFiles(srcFile, dst, "copy with overwrite over existing file")
|
||||
|
||||
assertTrue(dstFile.delete())
|
||||
dst = srcFile.copyTo(dstFile)
|
||||
compareFiles(srcFile, dst, "copy to new file")
|
||||
|
||||
assertTrue(dstFile.delete())
|
||||
dstFile.mkdir()
|
||||
val child = File(dstFile, "child")
|
||||
child.createNewFile()
|
||||
assertFailsWith(FileAlreadyExistsException::class, "copy with overwrite do not overwrite non-empty dir") {
|
||||
srcFile.copyTo(dstFile, overwrite = true)
|
||||
}
|
||||
child.delete()
|
||||
|
||||
srcFile.copyTo(dstFile, overwrite = true)
|
||||
assertEquals(srcFile.readText(), dstFile.readText(), "copy with overwrite over empty dir")
|
||||
|
||||
assertTrue(srcFile.delete())
|
||||
assertTrue(dstFile.delete())
|
||||
|
||||
assertFailsWith(NoSuchFileException::class) {
|
||||
srcFile.copyTo(dstFile)
|
||||
}
|
||||
|
||||
srcFile.mkdir()
|
||||
srcFile.resolve("somefile").writeText("some content")
|
||||
dstFile.writeText("")
|
||||
assertFailsWith(FileAlreadyExistsException::class, "copy dir do not overwrite file") {
|
||||
srcFile.copyTo(dstFile)
|
||||
}
|
||||
srcFile.copyTo(dstFile, overwrite = true)
|
||||
assertTrue(dstFile.isDirectory)
|
||||
assertTrue(dstFile.listFiles()!!.isEmpty(), "only directory is copied, but not its content")
|
||||
|
||||
assertFailsWith(FileAlreadyExistsException::class, "copy dir do not overwrite dir") {
|
||||
srcFile.copyTo(dstFile)
|
||||
}
|
||||
|
||||
srcFile.copyTo(dstFile, overwrite = true)
|
||||
assertTrue(dstFile.isDirectory)
|
||||
assertTrue(dstFile.listFiles()!!.isEmpty(), "only directory is copied, but not its content")
|
||||
|
||||
dstFile.resolve("somefile2").writeText("some content2")
|
||||
assertFailsWith(FileAlreadyExistsException::class, "copy dir do not overwrite dir") {
|
||||
srcFile.copyTo(dstFile, overwrite = true)
|
||||
}
|
||||
}
|
||||
finally {
|
||||
srcFile.deleteRecursively()
|
||||
dstFile.deleteRecursively()
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun copyToNameWithoutParent() {
|
||||
val currentDir = File("").absoluteFile!!
|
||||
val srcFile = createTempFile()
|
||||
val dstFile = createTempFile(directory = currentDir)
|
||||
try {
|
||||
srcFile.writeText("Hello, World!", Charsets.UTF_8)
|
||||
dstFile.delete()
|
||||
|
||||
val dstRelative = File(dstFile.name)
|
||||
|
||||
srcFile.copyTo(dstRelative)
|
||||
|
||||
assertEquals(srcFile.readText(), dstFile.readText())
|
||||
}
|
||||
finally {
|
||||
dstFile.delete()
|
||||
srcFile.delete()
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun deleteRecursively() {
|
||||
val dir = createTempDir()
|
||||
dir.delete()
|
||||
dir.mkdir()
|
||||
val subDir = File(dir, "subdir");
|
||||
subDir.mkdir()
|
||||
File(dir, "test1.txt").createNewFile()
|
||||
File(subDir, "test2.txt").createNewFile()
|
||||
|
||||
assertTrue(dir.deleteRecursively())
|
||||
assertFalse(dir.exists())
|
||||
assertTrue(dir.deleteRecursively())
|
||||
}
|
||||
|
||||
@Test fun deleteRecursivelyWithFail() {
|
||||
val basedir = FileTreeWalkTest.createTestFiles()
|
||||
val restricted = File(basedir, "1")
|
||||
try {
|
||||
if (restricted.setReadable(false)) {
|
||||
if (File(basedir, "7.txt").setReadable(false)) {
|
||||
assertFalse(basedir.deleteRecursively(), "Expected incomplete recursive deletion.")
|
||||
restricted.setReadable(true)
|
||||
File(basedir, "7.txt").setReadable(true)
|
||||
var i = 0
|
||||
for (file in basedir.walkTopDown()) {
|
||||
i++
|
||||
}
|
||||
assertEquals(6, i)
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
restricted.setReadable(true)
|
||||
File(basedir, "7.txt").setReadable(true)
|
||||
basedir.deleteRecursively()
|
||||
}
|
||||
}
|
||||
|
||||
fun compareFiles(src: File, dst: File, message: String? = null) {
|
||||
assertTrue(dst.exists())
|
||||
assertEquals(src.isFile, dst.isFile, message)
|
||||
if (dst.isFile) {
|
||||
assertTrue(Arrays.equals(src.readBytes(), dst.readBytes()), message)
|
||||
}
|
||||
}
|
||||
|
||||
fun compareDirectories(src: File, dst: File) {
|
||||
for (srcFile in src.walkTopDown()) {
|
||||
val dstFile = dst.resolve(srcFile.relativeTo(src))
|
||||
compareFiles(srcFile, dstFile)
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun copyRecursively() {
|
||||
val src = createTempDir()
|
||||
val dst = createTempDir()
|
||||
dst.delete()
|
||||
fun check() = compareDirectories(src, dst)
|
||||
|
||||
try {
|
||||
val subDir1 = createTempDir(prefix = "d1_", directory = src)
|
||||
val subDir2 = createTempDir(prefix = "d2_", directory = src)
|
||||
createTempDir(prefix = "d1_", directory = subDir1)
|
||||
val file1 = createTempFile(prefix = "f1_", directory = src)
|
||||
val file2 = createTempFile(prefix = "f2_", directory = subDir1)
|
||||
file1.writeText("hello")
|
||||
file2.writeText("wazzup")
|
||||
createTempDir(prefix = "d1_", directory = subDir2)
|
||||
|
||||
assertTrue(src.copyRecursively(dst))
|
||||
check()
|
||||
|
||||
assertFailsWith(FileAlreadyExistsException::class) {
|
||||
src.copyRecursively(dst)
|
||||
}
|
||||
|
||||
var conflicts = 0
|
||||
src.copyRecursively(dst) {
|
||||
_: File, e: IOException ->
|
||||
if (e is FileAlreadyExistsException) {
|
||||
conflicts++
|
||||
OnErrorAction.SKIP
|
||||
} else {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
assertEquals(2, conflicts)
|
||||
|
||||
if (subDir1.setReadable(false)) {
|
||||
try {
|
||||
dst.deleteRecursively()
|
||||
var caught = false
|
||||
assertTrue(src.copyRecursively(dst) {
|
||||
_: File, e: IOException ->
|
||||
if (e is AccessDeniedException) {
|
||||
caught = true
|
||||
OnErrorAction.SKIP
|
||||
} else {
|
||||
throw e
|
||||
}
|
||||
})
|
||||
assertTrue(caught)
|
||||
check()
|
||||
} finally {
|
||||
subDir1.setReadable(true)
|
||||
}
|
||||
}
|
||||
|
||||
src.deleteRecursively()
|
||||
dst.deleteRecursively()
|
||||
assertFailsWith(NoSuchFileException::class) {
|
||||
src.copyRecursively(dst)
|
||||
}
|
||||
|
||||
assertFalse(src.copyRecursively(dst) { _, _ -> OnErrorAction.TERMINATE })
|
||||
} finally {
|
||||
src.deleteRecursively()
|
||||
dst.deleteRecursively()
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun copyRecursivelyWithOverwrite() {
|
||||
val src = createTempDir()
|
||||
val dst = createTempDir()
|
||||
fun check() = compareDirectories(src, dst)
|
||||
|
||||
try {
|
||||
val srcFile = src.resolve("test")
|
||||
val dstFile = dst.resolve("test")
|
||||
srcFile.writeText("text1")
|
||||
|
||||
src.copyRecursively(dst)
|
||||
|
||||
srcFile.writeText("text1 modified")
|
||||
src.copyRecursively(dst, overwrite = true)
|
||||
check()
|
||||
|
||||
dstFile.delete()
|
||||
dstFile.mkdir()
|
||||
dstFile.resolve("subFile").writeText("subfile")
|
||||
src.copyRecursively(dst, overwrite = true)
|
||||
check()
|
||||
|
||||
srcFile.delete()
|
||||
srcFile.mkdir()
|
||||
srcFile.resolve("subFile").writeText("text2")
|
||||
src.copyRecursively(dst, overwrite = true)
|
||||
check()
|
||||
}
|
||||
finally {
|
||||
src.deleteRecursively()
|
||||
dst.deleteRecursively()
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun helpers1() {
|
||||
val str = "123456789\n"
|
||||
System.setIn(str.byteInputStream())
|
||||
val reader = System.`in`.bufferedReader()
|
||||
assertEquals("123456789", reader.readLine())
|
||||
val stringReader = str.reader()
|
||||
assertEquals('1', stringReader.read().toChar())
|
||||
assertEquals('2', stringReader.read().toChar())
|
||||
assertEquals('3', stringReader.read().toChar())
|
||||
}
|
||||
|
||||
@Test fun helpers2() {
|
||||
val file = createTempFile()
|
||||
val writer = file.printWriter()
|
||||
val str1 = "Hello, world!"
|
||||
val str2 = "Everything is wonderful!"
|
||||
writer.println(str1)
|
||||
writer.println(str2)
|
||||
writer.close()
|
||||
val reader = file.bufferedReader()
|
||||
assertEquals(str1, reader.readLine())
|
||||
assertEquals(str2, reader.readLine())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
@file:kotlin.jvm.JvmVersion
|
||||
package test.io
|
||||
|
||||
import kotlin.test.*
|
||||
import java.io.Writer
|
||||
import java.io.BufferedReader
|
||||
|
||||
class IOStreamsTest {
|
||||
@Test fun testGetStreamOfFile() {
|
||||
val tmpFile = createTempFile()
|
||||
var writer: Writer? = null
|
||||
try {
|
||||
writer = tmpFile.outputStream().writer()
|
||||
writer.write("Hello, World!")
|
||||
} finally {
|
||||
writer?.close()
|
||||
}
|
||||
val act: String?
|
||||
var reader: BufferedReader? = null
|
||||
try {
|
||||
reader = tmpFile.inputStream().reader().buffered()
|
||||
act = reader.readLine()
|
||||
} finally {
|
||||
reader?.close()
|
||||
}
|
||||
assertEquals("Hello, World!", act)
|
||||
}
|
||||
|
||||
@Test fun testInputStreamIterator() {
|
||||
val x = ByteArray(10) { it.toByte() }
|
||||
|
||||
val result = mutableListOf<Byte>()
|
||||
|
||||
x.inputStream().buffered().use { stream ->
|
||||
for(b in stream) {
|
||||
result += b
|
||||
}
|
||||
}
|
||||
|
||||
assertEquals(x.asList(), result)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
@file:kotlin.jvm.JvmVersion
|
||||
package test.io
|
||||
|
||||
import kotlin.test.*
|
||||
import java.io.File
|
||||
import java.io.Reader
|
||||
import java.io.StringReader
|
||||
import java.net.URL
|
||||
import java.util.ArrayList
|
||||
|
||||
fun sample(): Reader = StringReader("Hello\nWorld");
|
||||
|
||||
class ReadWriteTest {
|
||||
@Test fun testAppendText() {
|
||||
val file = File.createTempFile("temp", System.nanoTime().toString())
|
||||
file.writeText("Hello\n")
|
||||
file.appendText("World\n")
|
||||
file.appendText("Again")
|
||||
|
||||
assertEquals("Hello\nWorld\nAgain", file.readText())
|
||||
assertEquals(listOf("Hello", "World", "Again"), file.readLines(Charsets.UTF_8))
|
||||
file.deleteOnExit()
|
||||
}
|
||||
|
||||
@Test fun reader() {
|
||||
val list = ArrayList<String>()
|
||||
|
||||
/* TODO would be nicer maybe to write this as
|
||||
reader.lines.forEach { ... }
|
||||
|
||||
as we could one day maybe write that as
|
||||
for (line in reader.lines)
|
||||
|
||||
if the for(elem in thing) {...} statement could act as syntax sugar for
|
||||
thing.forEach{ elem -> ... }
|
||||
|
||||
if thing is not an Iterable/array/Iterator but has a suitable forEach method
|
||||
*/
|
||||
sample().forEachLine {
|
||||
list.add(it)
|
||||
}
|
||||
assertEquals(listOf("Hello", "World"), list)
|
||||
|
||||
assertEquals(listOf("Hello", "World"), sample().readLines())
|
||||
|
||||
sample().useLines {
|
||||
assertEquals(listOf("Hello", "World"), it.toList())
|
||||
}
|
||||
|
||||
|
||||
var reader = StringReader("")
|
||||
var c = 0
|
||||
reader.forEachLine { c++ }
|
||||
assertEquals(0, c)
|
||||
|
||||
reader = StringReader(" ")
|
||||
reader.forEachLine { c++ }
|
||||
assertEquals(1, c)
|
||||
|
||||
reader = StringReader(" \n")
|
||||
c = 0
|
||||
reader.forEachLine { c++ }
|
||||
assertEquals(1, c)
|
||||
|
||||
reader = StringReader(" \n ")
|
||||
c = 0
|
||||
reader.forEachLine { c++ }
|
||||
assertEquals(2, c)
|
||||
}
|
||||
|
||||
@Test fun file() {
|
||||
val file = File.createTempFile("temp", System.nanoTime().toString())
|
||||
val writer = file.outputStream().writer().buffered()
|
||||
|
||||
writer.write("Hello")
|
||||
writer.newLine()
|
||||
writer.write("World")
|
||||
writer.close()
|
||||
|
||||
//file.replaceText("Hello\nWorld")
|
||||
file.forEachBlock { arr: ByteArray, size: Int ->
|
||||
assertTrue(size >= 11 && size <= 12, size.toString())
|
||||
assertTrue(arr.contains('W'.toByte()))
|
||||
}
|
||||
val list = ArrayList<String>()
|
||||
file.forEachLine(Charsets.UTF_8, {
|
||||
list.add(it)
|
||||
})
|
||||
assertEquals(arrayListOf("Hello", "World"), list)
|
||||
|
||||
assertEquals(arrayListOf("Hello", "World"), file.readLines())
|
||||
|
||||
file.useLines {
|
||||
assertEquals(arrayListOf("Hello", "World"), it.toList())
|
||||
}
|
||||
|
||||
val text = file.inputStream().reader().readText()
|
||||
assertTrue(text.contains("Hello"))
|
||||
assertTrue(text.contains("World"))
|
||||
|
||||
file.writeText("")
|
||||
var c = 0
|
||||
file.forEachLine { c++ }
|
||||
assertEquals(0, c)
|
||||
|
||||
file.writeText(" ")
|
||||
file.forEachLine { c++ }
|
||||
assertEquals(1, c)
|
||||
|
||||
file.writeText(" \n")
|
||||
c = 0
|
||||
file.forEachLine { c++ }
|
||||
assertEquals(1, c)
|
||||
|
||||
file.writeText(" \n ")
|
||||
c = 0
|
||||
file.forEachLine { c++ }
|
||||
assertEquals(2, c)
|
||||
|
||||
file.deleteOnExit()
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test fun testUse() {
|
||||
val list = ArrayList<String>()
|
||||
val reader = sample().buffered()
|
||||
|
||||
reader.use {
|
||||
while (true) {
|
||||
val line = it.readLine()
|
||||
if (line != null)
|
||||
list.add(line)
|
||||
else
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
assertEquals(arrayListOf("Hello", "World"), list)
|
||||
}
|
||||
|
||||
@Test fun testPlatformNullUse() {
|
||||
fun <T> platformNull() = @Suppress("UNCHECKED_CAST") java.util.Collections.singleton(null as T).first()
|
||||
val resource = platformNull<java.io.Closeable>()
|
||||
val result = resource.use {
|
||||
"ok"
|
||||
}
|
||||
assertEquals("ok", result)
|
||||
}
|
||||
|
||||
@Test fun testURL() {
|
||||
val url = URL("http://kotlinlang.org")
|
||||
val text = url.readText()
|
||||
assertFalse(text.isEmpty())
|
||||
val text2 = url.readText(charset("UTF8"))
|
||||
assertFalse(text2.isEmpty())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class LineIteratorTest {
|
||||
@Test fun useLines() {
|
||||
// TODO we should maybe zap the useLines approach as it encourages
|
||||
// use of iterators which don't close the underlying stream
|
||||
val list1 = sample().useLines { it.toList() }
|
||||
val list2 = sample().useLines<ArrayList<String>>{ it.toCollection(arrayListOf()) }
|
||||
|
||||
assertEquals(listOf("Hello", "World"), list1)
|
||||
assertEquals(listOf("Hello", "World"), list2)
|
||||
}
|
||||
|
||||
@Test fun manualClose() {
|
||||
val reader = sample().buffered()
|
||||
try {
|
||||
val list = reader.lineSequence().toList()
|
||||
assertEquals(arrayListOf("Hello", "World"), list)
|
||||
} finally {
|
||||
reader.close()
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun boundaryConditions() {
|
||||
var reader = StringReader("").buffered()
|
||||
assertEquals(emptyList(), reader.lineSequence().toList())
|
||||
reader.close()
|
||||
|
||||
reader = StringReader(" ").buffered()
|
||||
assertEquals(listOf(" "), reader.lineSequence().toList())
|
||||
reader.close()
|
||||
|
||||
reader = StringReader(" \n").buffered()
|
||||
assertEquals(listOf(" "), reader.lineSequence().toList())
|
||||
reader.close()
|
||||
|
||||
reader = StringReader(" \n ").buffered()
|
||||
assertEquals(listOf(" ", " "), reader.lineSequence().toList())
|
||||
reader.close()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
@file:kotlin.jvm.JvmVersion
|
||||
package test.io
|
||||
|
||||
import java.io.*
|
||||
import kotlin.test.*
|
||||
|
||||
private class Serial(val name: String) : Serializable {
|
||||
override fun toString() = name
|
||||
}
|
||||
|
||||
private data class DataType(val name: String, val value: Int, val percent: Double) : Serializable
|
||||
|
||||
private enum class EnumSingleton { INSTANCE }
|
||||
private object ObjectSingleton : Serializable {
|
||||
private fun readResolve(): Any = ObjectSingleton
|
||||
}
|
||||
|
||||
private class OldSchoolSingleton private constructor() : Serializable {
|
||||
private fun readResolve(): Any = INSTANCE
|
||||
|
||||
companion object {
|
||||
val INSTANCE = OldSchoolSingleton()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class SerializableTest {
|
||||
@Test fun testClosure() {
|
||||
val tuple = Triple("Ivan", 12, Serial("serial"))
|
||||
val fn = { tuple.toString() }
|
||||
val deserialized = serializeAndDeserialize(fn)
|
||||
|
||||
assertEquals(fn(), deserialized())
|
||||
}
|
||||
|
||||
@Test fun testComplexClosure() {
|
||||
val y = 12
|
||||
val fn1 = { x: Int -> (x + y).toString() }
|
||||
val fn2: Int.(Int) -> String = { fn1(this + it) }
|
||||
val deserialized = serializeAndDeserialize(fn2)
|
||||
|
||||
assertEquals(5.fn2(10), 5.deserialized(10))
|
||||
}
|
||||
|
||||
@Test fun testDataClass() {
|
||||
val data = DataType("name", 176, 1.4)
|
||||
val deserialized = serializeAndDeserialize(data)
|
||||
|
||||
assertEquals(data, deserialized)
|
||||
}
|
||||
|
||||
@Test fun testSingletons() {
|
||||
assertTrue(EnumSingleton.INSTANCE === serializeAndDeserialize(EnumSingleton.INSTANCE))
|
||||
assertTrue(OldSchoolSingleton.INSTANCE === serializeAndDeserialize(OldSchoolSingleton.INSTANCE))
|
||||
assertTrue(ObjectSingleton === serializeAndDeserialize(ObjectSingleton))
|
||||
}
|
||||
}
|
||||
|
||||
public fun <T> serializeToByteArray(value: T): ByteArray {
|
||||
val outputStream = ByteArrayOutputStream()
|
||||
val objectOutputStream = ObjectOutputStream(outputStream)
|
||||
|
||||
objectOutputStream.writeObject(value)
|
||||
objectOutputStream.close()
|
||||
outputStream.close()
|
||||
return outputStream.toByteArray()
|
||||
}
|
||||
|
||||
public fun <T> deserializeFromByteArray(bytes: ByteArray): T {
|
||||
val inputStream = ByteArrayInputStream(bytes)
|
||||
val inputObjectStream = ObjectInputStream(inputStream)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return inputObjectStream.readObject() as T
|
||||
}
|
||||
|
||||
public fun <T> serializeAndDeserialize(value: T): T {
|
||||
val bytes = serializeToByteArray(value)
|
||||
return deserializeFromByteArray(bytes)
|
||||
}
|
||||
|
||||
private fun hexToBytes(value: String): ByteArray = value.split(" ").map { Integer.parseInt(it, 16).toByte() }.toByteArray()
|
||||
|
||||
public fun <T> deserializeFromHex(value: String) = deserializeFromByteArray<T>(hexToBytes(value))
|
||||
|
||||
public fun <T> serializeToHex(value: T) =
|
||||
serializeToByteArray(value).joinToString(" ") { (it.toInt() and 0xFF).toString(16).padStart(2, '0') }
|
||||
|
||||
Reference in New Issue
Block a user