blob: a5db29691b2e0b2f5f9b5c0b40a892f06569cae0 [file] [log] [blame]
/*
* Copyright 2010-2018 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 test.io
import test.assertArrayContentEquals
import java.io.*
import kotlin.io.walkTopDown
import kotlin.random.Random
import kotlin.test.*
class FilesTest {
private val isCaseInsensitiveFileSystem = File("C:/") == File("c:/")
private val isBackslashSeparator = File.separatorChar == '\\'
@Suppress("DEPRECATION")
@Test fun testPath() {
val fileSuf = System.currentTimeMillis().toString()
val file1 = createTempFile("temp", fileSuf)
assertTrue(file1.path.endsWith(fileSuf), file1.path)
}
@Suppress("DEPRECATION")
@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.startsWith("temp") && dir2.name.endsWith(".tmp"))
val dir3 = createTempDir()
assertTrue(dir3.exists() && dir3.isDirectory && dir3.name.startsWith("tmp") && dir3.name.endsWith(".tmp"))
dir1.delete()
dir2.delete()
dir3.delete()
}
@Suppress("DEPRECATION")
@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.startsWith("temp") && file2.name.endsWith(".tmp"))
val file3 = createTempFile()
assertTrue(file3.exists() && file3.name.startsWith("tmp") && file3.name.endsWith(".tmp"))
file1.delete()
file2.delete()
file3.delete()
}
@Suppress("DEPRECATION")
@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)
}
private class FixedLengthFile(path: String, private val length: Long) : File(path) {
override fun length(): Long = length
}
@Test fun writeReadText() {
val file = @Suppress("DEPRECATION") createTempFile()
try {
val expected = String(CharArray(DEFAULT_BUFFER_SIZE * 2) { Random.nextInt(0, 1024).toChar() })
file.writeText(expected)
run {
val actual1 = file.readText()
assertEquals(expected.length, actual1.length)
assertTrue(expected.equals(actual1), "Expected to read the same content back")
}
val fileLength = file.length()
val testLengths = listOf(0L, *Array(3) { Random.nextLong(fileLength) })
for (length in testLengths) {
val shorterFile = FixedLengthFile(file.path, length)
val actual2 = shorterFile.readText()
assertEquals(expected.length, actual2.length)
assertTrue(expected.equals(actual2), "Expected to read the same content back")
}
} finally {
file.delete()
}
}
@Test fun writeReadBytes() {
val file = @Suppress("DEPRECATION") createTempFile()
try {
val expected = Random.nextBytes(DEFAULT_BUFFER_SIZE * 4)
file.writeBytes(expected)
run {
val actual1 = file.readBytes()
assertArrayContentEquals(expected, actual1, "Expected to read the same content back")
}
val fileLength = file.length()
val testLengths = listOf(0L, *Array(3) { Random.nextLong(fileLength) })
for (length in testLengths) {
val shorterFile = FixedLengthFile(file.path, length)
val actual2 = shorterFile.readBytes()
assertEquals(actual2.size, expected.size)
assertArrayContentEquals(expected, actual2, "Expected to read the same content back")
}
} finally {
file.delete()
}
}
@Test fun readVirtualFile() {
val virtualFile = File("/proc/self/cmdline")
if (virtualFile.exists() && virtualFile.length() == 0L) {
val allBytes = virtualFile.readBytes()
assertNotEquals(0, allBytes.size)
val allText = virtualFile.readText()
assertNotEquals(0, allText.length)
println(allText)
}
}
@Test fun testCopyTo() {
val srcFile = @Suppress("DEPRECATION") createTempFile()
val dstFile = @Suppress("DEPRECATION") 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 = @Suppress("DEPRECATION") createTempFile()
val dstFile = @Suppress("DEPRECATION") 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 = @Suppress("DEPRECATION") 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) {
assertArrayContentEquals(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)
}
}
@Suppress("DEPRECATION")
@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()
}
}
@Suppress("DEPRECATION")
@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 = @Suppress("DEPRECATION") 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())
}
}