[tests] getting rid of obsolete API use in (de)compressor tests

GitOrigin-RevId: 9946ce70db26f9cb9912732157d59ab37d01b5f8
This commit is contained in:
Roman Shevchenko
2024-03-07 20:51:37 +00:00
committed by intellij-monorepo-bot
parent 242652b9b4
commit dbe0bbd184
2 changed files with 268 additions and 258 deletions
@@ -1,22 +1,18 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.util.io
import com.intellij.openapi.util.io.IoTestUtil.assumeSymLinkCreationIsSupported
import com.intellij.openapi.util.io.NioFiles
import com.intellij.testFramework.rules.TempDirectory
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream
import org.assertj.core.api.Assertions.assertThat
import org.junit.Assume.assumeTrue
import org.junit.Rule
import org.junit.Test
import org.junit.jupiter.api.Assumptions.assumeTrue
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.io.TempDir
import java.io.ByteArrayInputStream
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.nio.charset.StandardCharsets
import java.nio.file.FileSystems
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.attribute.PosixFilePermission
import java.nio.file.attribute.PosixFilePermissions
import java.util.jar.Attributes
@@ -24,14 +20,19 @@ import java.util.jar.JarFile
import java.util.jar.Manifest
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
import kotlin.io.path.createDirectories
import kotlin.io.path.createFile
import kotlin.io.path.createParentDirectories
import kotlin.io.path.createSymbolicLinkPointingTo
import kotlin.io.path.getPosixFilePermissions
import kotlin.io.path.inputStream
import kotlin.io.path.name
import kotlin.io.path.writeText
class CompressorTest {
@Rule @JvmField var tempDir: TempDirectory = TempDirectory()
@Test fun simpleZip() {
val zip = tempDir.newFile("test.zip")
val data = tempDir.newFile("file.txt", "789".toByteArray())
@Test fun simpleZip(@TempDir tempDir: Path) {
val zip = tempDir.resolve("test.zip")
val data = tempDir.resolve("file.txt").apply { writeText("789") }
Compressor.Zip(zip).use {
it.addFile("empty.txt", byteArrayOf())
it.addFile("file1.txt", "123".toByteArray())
@@ -41,9 +42,9 @@ class CompressorTest {
assertZip(zip, "empty.txt" to "", "file1.txt" to "123", "file2.txt" to "456", "file3.txt" to "789")
}
@Test fun simpleTar() {
val tar = tempDir.newFile("test.tar")
val data = tempDir.newFile("file.txt", "789".toByteArray())
@Test fun simpleTar(@TempDir tempDir: Path) {
val tar = tempDir.resolve("test.tar")
val data = tempDir.resolve("file.txt").apply { writeText("789") }
Compressor.Tar(tar, Compressor.Tar.Compression.GZIP).use {
it.addFile("empty.txt", byteArrayOf())
it.addFile("file1.txt", "123".toByteArray())
@@ -53,8 +54,8 @@ class CompressorTest {
assertTar(tar, "empty.txt" to "", "file1.txt" to "123", "file2.txt" to "456", "file3.txt" to "789")
}
@Test fun simpleZipWithFilters() {
val zip = tempDir.newFile("test.zip")
@Test fun simpleZipWithFilters(@TempDir tempDir: Path) {
val zip = tempDir.resolve("test.zip")
val set = mutableSetOf<String>()
Compressor.Zip(zip).filter { entryName, _ -> set.add(entryName) && !entryName.startsWith("d1/") }.use {
it.addFile("file1.txt", "123".toByteArray())
@@ -66,9 +67,9 @@ class CompressorTest {
assertZip(zip, "file1.txt" to "123", "file2.txt" to "456")
}
@Test fun streamZip() {
val zip = tempDir.newFile("test.zip")
FileOutputStream(zip).use { os ->
@Test fun streamZip(@TempDir tempDir: Path) {
val zip = tempDir.resolve("test.zip")
zip.outputStream().use { os ->
Compressor.Zip(os).withLevel(ZipEntry.STORED).use {
it.addFile("file.txt", "123".toByteArray())
}
@@ -76,18 +77,18 @@ class CompressorTest {
assertZip(zip, "file.txt" to "123")
}
@Test fun recursiveZip() {
val dir = tempDir.newDirectory("dir")
tempDir.newFile("dir/f1").writeText("1")
tempDir.newFile("dir/f2").writeText("2")
tempDir.newFile("dir/d1/f11").writeText("11")
tempDir.newFile("dir/d1/f12").writeText("12")
tempDir.newFile("dir/d1/d11/f111").writeText("111")
tempDir.newFile("dir/d1/d11/f112").writeText("112")
tempDir.newFile("dir/d2/f21").writeText("21")
tempDir.newFile("dir/d2/f22").writeText("22")
@Test fun recursiveZip(@TempDir tempDir: Path) {
val dir = tempDir.resolve("dir")
tempDir.resolve("dir/f1").createParentDirectories().writeText("1")
tempDir.resolve("dir/f2").createParentDirectories().writeText("2")
tempDir.resolve("dir/d1/f11").createParentDirectories().writeText("11")
tempDir.resolve("dir/d1/f12").createParentDirectories().writeText("12")
tempDir.resolve("dir/d1/d11/f111").createParentDirectories().writeText("111")
tempDir.resolve("dir/d1/d11/f112").createParentDirectories().writeText("112")
tempDir.resolve("dir/d2/f21").createParentDirectories().writeText("21")
tempDir.resolve("dir/d2/f22").createParentDirectories().writeText("22")
val zip = tempDir.newFile("test.zip")
val zip = tempDir.resolve("test.zip")
Compressor.Zip(zip).filter { entryName, _ -> entryName != "d1/d11" }.use { it.addDirectory(dir) }
assertZip(
zip,
@@ -97,18 +98,18 @@ class CompressorTest {
"d2/f21" to "21", "d2/f22" to "22")
}
@Test fun recursiveTarWithPrefix() {
val dir = tempDir.newDirectory("dir")
tempDir.newFile("dir/f1").writeText("1")
tempDir.newFile("dir/f2").writeText("2")
tempDir.newFile("dir/d1/f11").writeText("11")
tempDir.newFile("dir/d1/f12").writeText("12")
tempDir.newFile("dir/d1/d11/f111").writeText("111")
tempDir.newFile("dir/d1/d11/f112").writeText("112")
tempDir.newFile("dir/d2/f21").writeText("21")
tempDir.newFile("dir/d2/f22").writeText("22")
@Test fun recursiveTarWithPrefix(@TempDir tempDir: Path) {
val dir = tempDir.resolve("dir")
tempDir.resolve("dir/f1").createParentDirectories().writeText("1")
tempDir.resolve("dir/f2").createParentDirectories().writeText("2")
tempDir.resolve("dir/d1/f11").createParentDirectories().writeText("11")
tempDir.resolve("dir/d1/f12").createParentDirectories().writeText("12")
tempDir.resolve("dir/d1/d11/f111").createParentDirectories().writeText("111")
tempDir.resolve("dir/d1/d11/f112").createParentDirectories().writeText("112")
tempDir.resolve("dir/d2/f21").createParentDirectories().writeText("21")
tempDir.resolve("dir/d2/f22").createParentDirectories().writeText("22")
val tar = tempDir.newFile("test.tgz")
val tar = tempDir.resolve("test.tgz")
Compressor.Tar(tar, Compressor.Tar.Compression.GZIP).use { it.addDirectory("tar/", dir) }
assertTar(
tar,
@@ -119,69 +120,71 @@ class CompressorTest {
"tar/d2/f21" to "21", "tar/d2/f22" to "22")
}
@Test fun tarWithEmptyPrefix() {
val file = tempDir.newFile("dir/file").toPath()
val tar = tempDir.newFile("test.tgz")
@Test fun tarWithEmptyPrefix(@TempDir tempDir: Path) {
val file = tempDir.resolve("dir/file").createParentDirectories().createFile()
val tar = tempDir.resolve("test.tgz")
Compressor.Tar(tar, Compressor.Tar.Compression.GZIP).use { it.addDirectory("", file.parent) }
assertTar(tar, file.name to "")
}
@Test fun tarWithExecutableFiles() {
@Test fun tarWithExecutableFiles(@TempDir tempDir: Path) {
assumeTrue(FileSystems.getDefault().supportedFileAttributeViews().contains("posix"))
val dir = tempDir.newDirectory("dir").toPath()
val regular = Files.createFile(dir.resolve("regular"))
val executable = Files.createFile(dir.resolve("executable"), PosixFilePermissions.asFileAttribute(PosixFilePermission.values().toSet()))
val dir = tempDir.resolve("dir").createDirectories()
val regular = dir.resolve("regular").createFile()
val executable = dir.resolve("executable").createFile(PosixFilePermissions.asFileAttribute(PosixFilePermission.entries.toSet()))
val tar = tempDir.newFile("test.tgz")
val tar = tempDir.resolve("test.tgz")
Compressor.Tar(tar, Compressor.Tar.Compression.GZIP).use { it.addDirectory(dir) }
val out = tempDir.newDirectory("out").toPath()
val out = tempDir.resolve("out")
Decompressor.Tar(tar).extract(out)
assertThat(Files.getPosixFilePermissions(out.resolve(regular.name))).doesNotContain(PosixFilePermission.OWNER_EXECUTE)
assertThat(Files.getPosixFilePermissions(out.resolve(executable.name))).contains(PosixFilePermission.OWNER_EXECUTE)
assertThat(out.resolve(regular.name).getPosixFilePermissions()).doesNotContain(PosixFilePermission.OWNER_EXECUTE)
assertThat(out.resolve(executable.name).getPosixFilePermissions()).contains(PosixFilePermission.OWNER_EXECUTE)
}
@Test fun tarWithSymbolicLinks() {
@Test fun tarWithSymbolicLinks(@TempDir tempDir: Path) {
assumeSymLinkCreationIsSupported()
val dir = tempDir.newDirectory("dir").toPath()
val origin = Files.createFile(dir.resolve("origin"))
val link = Files.createSymbolicLink(dir.resolve("link"), origin.fileName)
val dir = tempDir.resolve("dir").createDirectories()
val origin = dir.resolve("origin").createFile()
val link = dir.resolve("link").createSymbolicLinkPointingTo(origin.fileName)
val tar = tempDir.newFile("test.tgz")
val tar = tempDir.resolve("test.tgz")
Compressor.Tar(tar, Compressor.Tar.Compression.GZIP).use { it.addDirectory(dir) }
NioFiles.deleteRecursively(dir)
val out = tempDir.newDirectory("out").toPath()
val out = tempDir.resolve("out")
Decompressor.Tar(tar).extract(out)
assertThat(out.resolve(link.name)).isSymbolicLink.hasSameBinaryContentAs(out.resolve(origin.name))
}
@Test fun entryNameTrimming() {
val zip = tempDir.newFile("test.zip")
@Test fun entryNameTrimming(@TempDir tempDir: Path) {
val zip = tempDir.resolve("test.zip")
Compressor.Zip(zip).use { it.addFile("//file.txt//", "123".toByteArray()) }
assertZip(zip, "file.txt" to "123")
}
@Test fun jarWithManifest() {
val jar = tempDir.newFile("test.jar")
@Test fun jarWithManifest(@TempDir tempDir: Path) {
val jar = tempDir.resolve("test.jar")
val mf = Manifest()
mf.mainAttributes[Attributes.Name.MANIFEST_VERSION] = "9.75"
Compressor.Jar(jar).use { it.addManifest(mf) }
assertZip(jar, JarFile.MANIFEST_NAME to "Manifest-Version: 9.75")
}
private fun assertZip(zip: File, vararg expected: Pair<String, String>) {
val actual = ZipInputStream(FileInputStream(zip)).use {
//<editor-fold desc="Helpers.">
private fun assertZip(zip: Path, vararg expected: Pair<String, String>) {
val actual = ZipInputStream(zip.inputStream()).use {
generateSequence(it::getNextEntry).map { entry -> entry.name to it.readBytes().toString(StandardCharsets.UTF_8).trim() }.toList()
}
assertThat(actual).containsExactlyInAnyOrder(*expected)
}
private fun assertTar(tar: File, vararg expected: Pair<String, String>) {
val actual = TarArchiveInputStream(GzipCompressorInputStream(FileInputStream(tar))).use {
generateSequence(it::getNextTarEntry).map { entry -> entry.name to it.readBytes().toString(StandardCharsets.UTF_8).trim() }.toList()
private fun assertTar(tar: Path, vararg expected: Pair<String, String>) {
val actual = TarArchiveInputStream(GzipCompressorInputStream(tar.inputStream())).use {
generateSequence(it::getNextEntry).map { entry -> entry.name to it.readBytes().toString(StandardCharsets.UTF_8).trim() }.toList()
}
assertThat(actual).containsExactlyInAnyOrder(*expected)
}
//</editor-fold>
}
@@ -4,7 +4,6 @@ package com.intellij.util.io
import com.github.marschall.memoryfilesystem.MemoryFileSystemBuilder
import com.intellij.openapi.util.SystemInfo
import com.intellij.openapi.util.io.IoTestUtil.assumeSymLinkCreationIsSupported
import com.intellij.testFramework.rules.TempDirectory
import com.intellij.util.SystemProperties
import org.apache.commons.compress.archivers.tar.TarArchiveEntry
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream
@@ -15,11 +14,9 @@ import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatThrownBy
import org.assertj.core.api.Condition
import org.junit.Rule
import org.junit.Test
import java.io.FileOutputStream
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.io.TempDir
import java.io.IOException
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.attribute.FileTime
import java.time.Instant
@@ -28,102 +25,111 @@ import java.util.function.Predicate
import java.util.zip.ZipEntry
import java.util.zip.ZipException
import java.util.zip.ZipOutputStream
import kotlin.io.path.createDirectories
import kotlin.io.path.createFile
import kotlin.io.path.createParentDirectories
import kotlin.io.path.createSymbolicLinkPointingTo
import kotlin.io.path.isExecutable
import kotlin.io.path.isHidden
import kotlin.io.path.isWritable
import kotlin.io.path.outputStream
import kotlin.io.path.readSymbolicLink
import kotlin.io.path.writeBytes
import kotlin.io.path.writeText
class DecompressorTest {
@Rule @JvmField var tempDir: TempDirectory = TempDirectory()
@Test fun noInternalTraversalInZip() {
val zip = tempDir.newFile("test.zip")
ZipOutputStream(FileOutputStream(zip)).use { writeEntry(it, "a/../bad.txt") }
val dir = tempDir.newDirectory("unpacked").toPath()
@Test fun noInternalTraversalInZip(@TempDir tempDir: Path) {
val zip = tempDir.resolve("test.zip")
ZipOutputStream(zip.outputStream()).use { writeEntry(it, "a/../bad.txt") }
val dir = tempDir.resolve("unpacked")
testNoTraversal(Decompressor.Zip(zip), dir, dir.resolve("bad.txt"))
testNoTraversal(Decompressor.Zip(zip).withZipExtensions(), dir, dir.resolve("bad.txt"))
}
@Test fun noExternalTraversalInZip() {
val zip = tempDir.newFile("test.zip")
ZipOutputStream(FileOutputStream(zip)).use { writeEntry(it, "../evil.txt") }
val dir = tempDir.newDirectory("unpacked").toPath()
@Test fun noExternalTraversalInZip(@TempDir tempDir: Path) {
val zip = tempDir.resolve("test.zip")
ZipOutputStream(zip.outputStream()).use { writeEntry(it, "../evil.txt") }
val dir = tempDir.resolve("unpacked")
testNoTraversal(Decompressor.Zip(zip), dir, dir.parent.resolve("evil.txt"))
testNoTraversal(Decompressor.Zip(zip).withZipExtensions(), dir, dir.parent.resolve("evil.txt"))
}
@Test fun noAbsolutePathsInZip() {
val zip = tempDir.newFile("test.zip")
ZipOutputStream(FileOutputStream(zip)).use { writeEntry(it, "/root.txt") }
val dir1 = tempDir.newDirectory("unpacked1").toPath()
@Test fun noAbsolutePathsInZip(@TempDir tempDir: Path) {
val zip = tempDir.resolve("test.zip")
ZipOutputStream(zip.outputStream()).use { writeEntry(it, "/root.txt") }
val dir1 = tempDir.resolve("unpacked1")
Decompressor.Zip(zip).extract(dir1)
assertThat(dir1.resolve("root.txt")).exists()
val dir2 = tempDir.newDirectory("unpacked2").toPath()
val dir2 = tempDir.resolve("unpacked2")
Decompressor.Zip(zip).withZipExtensions().extract(dir2)
assertThat(dir2.resolve("root.txt")).exists()
}
@Test fun tarDetectionPlain() {
val tar = tempDir.newFile("test.tar")
TarArchiveOutputStream(FileOutputStream(tar)).use { writeEntry(it, "dir/file.txt") }
val dir = tempDir.newDirectory("unpacked").toPath()
@Test fun tarDetectionPlain(@TempDir tempDir: Path) {
val tar = tempDir.resolve("test.tar")
TarArchiveOutputStream(tar.outputStream()).use { writeEntry(it, "dir/file.txt") }
val dir = tempDir.resolve("unpacked")
Decompressor.Tar(tar).extract(dir)
assertThat(dir.resolve("dir/file.txt")).exists()
}
@Test fun tarDetectionGZip() {
val tar = tempDir.newFile("test.tgz")
TarArchiveOutputStream(GzipCompressorOutputStream(FileOutputStream(tar))).use { writeEntry(it, "dir/file.txt") }
val dir = tempDir.newDirectory("unpacked").toPath()
@Test fun tarDetectionGZip(@TempDir tempDir: Path) {
val tar = tempDir.resolve("test.tgz")
TarArchiveOutputStream(GzipCompressorOutputStream(tar.outputStream())).use { writeEntry(it, "dir/file.txt") }
val dir = tempDir.resolve("unpacked")
Decompressor.Tar(tar).extract(dir)
assertThat(dir.resolve("dir/file.txt")).exists()
}
@Test fun noInternalTraversalInTar() {
val tar = tempDir.newFile("test.tar")
TarArchiveOutputStream(FileOutputStream(tar)).use { writeEntry(it, "a/../bad.txt") }
val dir = tempDir.newDirectory("unpacked").toPath()
@Test fun noInternalTraversalInTar(@TempDir tempDir: Path) {
val tar = tempDir.resolve("test.tar")
TarArchiveOutputStream(tar.outputStream()).use { writeEntry(it, "a/../bad.txt") }
val dir = tempDir.resolve("unpacked")
testNoTraversal(Decompressor.Tar(tar), dir, dir.resolve("bad.txt"))
}
@Test fun noExternalTraversalInTar() {
val tar = tempDir.newFile("test.tar")
TarArchiveOutputStream(FileOutputStream(tar)).use { writeEntry(it, "../evil.txt") }
val dir = tempDir.newDirectory("unpacked").toPath()
@Test fun noExternalTraversalInTar(@TempDir tempDir: Path) {
val tar = tempDir.resolve("test.tar")
TarArchiveOutputStream(tar.outputStream()).use { writeEntry(it, "../evil.txt") }
val dir = tempDir.resolve("unpacked")
testNoTraversal(Decompressor.Tar(tar), dir, dir.parent.resolve("evil.txt"))
}
@Test fun noAbsolutePathsInTar() {
val tar = tempDir.newFile("test.tar")
TarArchiveOutputStream(FileOutputStream(tar)).use { writeEntry(it, "/root.txt") }
val dir = tempDir.newDirectory("unpacked").toPath()
@Test fun noAbsolutePathsInTar(@TempDir tempDir: Path) {
val tar = tempDir.resolve("test.tar")
TarArchiveOutputStream(tar.outputStream()).use { writeEntry(it, "/root.txt") }
val dir = tempDir.resolve("unpacked")
Decompressor.Tar(tar).extract(dir)
assertThat(dir.resolve("root.txt")).exists()
}
@Test(expected = ZipException::class)
fun failsOnCorruptedZip() {
val zip = tempDir.newFile("test.zip")
zip.writeText("whatever")
val dir = tempDir.newDirectory("unpacked").toPath()
Decompressor.Zip(zip).extract(dir)
@Test
fun failsOnCorruptedZip(@TempDir tempDir: Path) {
val zip = tempDir.createDirectories().resolve("test.zip").apply { writeText("whatever") }
val dir = tempDir.resolve("unpacked")
assertThatThrownBy {
Decompressor.Zip(zip).extract(dir)
}.isInstanceOf(ZipException::class.java)
}
@Test
fun failsOnCorruptedExtZip() {
val zip = tempDir.newFile("test.zip")
zip.writeText("whatever")
val dir = tempDir.newDirectory("unpacked").toPath()
fun failsOnCorruptedExtZip(@TempDir tempDir: Path) {
val zip = tempDir.resolve("test.zip").apply { writeText("whatever") }
val dir = tempDir.resolve("unpacked")
assertThatThrownBy {
Decompressor.Zip(zip).withZipExtensions().extract(dir)
}.hasRootCauseInstanceOf(ZipException::class.java)
}
@Test fun tarFileModes() {
val tar = tempDir.newFile("test.tar")
TarArchiveOutputStream(FileOutputStream(tar)).use {
@Test fun tarFileModes(@TempDir tempDir: Path) {
val tar = tempDir.resolve("test.tar")
TarArchiveOutputStream(tar.outputStream()).use {
writeEntry(it, "dir/r", mode = 0b100_000_000)
writeEntry(it, "dir/rw", mode = 0b110_000_000)
writeEntry(it, "dir/rx", mode = 0b101_000_000)
writeEntry(it, "dir/rwx", mode = 0b111_000_000)
}
val dir = tempDir.newDirectory("unpacked").toPath()
val dir = tempDir.resolve("unpacked")
Decompressor.Tar(tar).extract(dir)
if (SystemInfo.isWindows) {
arrayOf("r", "rw", "rx", "rwx").forEach {
@@ -138,15 +144,15 @@ class DecompressorTest {
}
}
@Test fun zipUnixFileModes() {
val zip = tempDir.newFile("test.zip")
ZipArchiveOutputStream(FileOutputStream(zip)).use {
@Test fun zipUnixFileModes(@TempDir tempDir: Path) {
val zip = tempDir.resolve("test.zip")
ZipArchiveOutputStream(zip.outputStream()).use {
writeEntry(it, "dir/r", mode = 0b100_000_000)
writeEntry(it, "dir/rw", mode = 0b110_000_000)
writeEntry(it, "dir/rx", mode = 0b101_000_000)
writeEntry(it, "dir/rwx", mode = 0b111_000_000)
}
val dir = tempDir.newDirectory("unpacked").toPath()
val dir = tempDir.resolve("unpacked")
Decompressor.Zip(zip).withZipExtensions().extract(dir)
if (SystemInfo.isWindows) {
arrayOf("r", "rw", "rx", "rwx").forEach {
@@ -161,14 +167,14 @@ class DecompressorTest {
}
}
@Test fun zipDosFileModes() {
val zip = tempDir.newFile("test.zip")
ZipArchiveOutputStream(FileOutputStream(zip)).use {
@Test fun zipDosFileModes(@TempDir tempDir: Path) {
val zip = tempDir.resolve("test.zip")
ZipArchiveOutputStream(zip.outputStream()).use {
writeEntry(it, "dir/ro", readOnly = true)
writeEntry(it, "dir/rw")
writeEntry(it, "dir/h", hidden = true)
}
val dir = tempDir.newDirectory("unpacked").toPath()
val dir = tempDir.resolve("unpacked")
Decompressor.Zip(zip).withZipExtensions().extract(dir)
assertThat(dir.resolve("dir/ro")).exists().isNot(Writable)
assertThat(dir.resolve("dir/rw")).exists().`is`(Writable)
@@ -177,91 +183,91 @@ class DecompressorTest {
}
}
@Test fun filtering() {
val zip = tempDir.newFile("test.zip")
ZipOutputStream(FileOutputStream(zip)).use {
@Test fun filtering(@TempDir tempDir: Path) {
val zip = tempDir.resolve("test.zip")
ZipOutputStream(zip.outputStream()).use {
writeEntry(it, "d1/f1.txt")
writeEntry(it, "d2/f2.txt")
}
val dir = tempDir.newDirectory("unpacked").toPath()
val dir = tempDir.resolve("unpacked")
Decompressor.Zip(zip).filter(Predicate { !it.startsWith("d2/") }).extract(dir)
assertThat(dir.resolve("d1/f1.txt")).isRegularFile()
assertThat(dir.resolve("d2")).doesNotExist()
}
@Test fun tarSymlinks() {
@Test fun tarSymlinks(@TempDir tempDir: Path) {
assumeSymLinkCreationIsSupported()
val rogueTarget = tempDir.newFile("rogue_f", "123789".toByteArray(Charsets.UTF_8))
val tar = tempDir.newFile("test.tar")
TarArchiveOutputStream(FileOutputStream(tar)).use {
val rogueTarget = tempDir.resolve("rogue_f").apply { writeText("123789") }
val tar = tempDir.resolve("test.tar")
TarArchiveOutputStream(tar.outputStream()).use {
writeEntry(it, "f")
writeEntry(it, "links/ok", link = "../f")
writeEntry(it, "rogue", link = "../rogue_f")
}
val dir = tempDir.newDirectory("unpacked").toPath()
val dir = tempDir.resolve("unpacked")
Decompressor.Tar(tar).extract(dir)
assertThat(dir.resolve("links/ok")).isSymbolicLink().hasSameBinaryContentAs(dir.resolve("f"))
assertThat(dir.resolve("rogue")).isSymbolicLink().hasSameBinaryContentAs(rogueTarget.toPath())
assertThat(dir.resolve("rogue")).isSymbolicLink().hasSameBinaryContentAs(rogueTarget)
}
@Test fun tarHardlinks() {
val tar = tempDir.newFile("test.tar")
TarArchiveOutputStream(FileOutputStream(tar)).use {
@Test fun tarHardlinks(@TempDir tempDir: Path) {
val tar = tempDir.resolve("test.tar")
TarArchiveOutputStream(tar.outputStream()).use {
writeEntry(it, "hardlink", link = "hardlink", type = TarArchiveEntry.LF_LINK)
}
val dir = tempDir.newDirectory("unpacked").toPath()
val dir = tempDir.resolve("unpacked")
Decompressor.Tar(tar).extract(dir)
assertThat(dir.resolve("hardlink")).doesNotExist()
}
@Test fun zipSymlinks() {
@Test fun zipSymlinks(@TempDir tempDir: Path) {
assumeSymLinkCreationIsSupported()
val rogueTarget = tempDir.newFile("rogue_f", "123789".toByteArray(Charsets.UTF_8))
val zip = tempDir.newFile("test.zip")
ZipArchiveOutputStream(FileOutputStream(zip)).use {
val rogueTarget = tempDir.resolve("rogue_f").apply { writeText("123789") }
val zip = tempDir.resolve("test.zip")
ZipArchiveOutputStream(zip.outputStream()).use {
writeEntry(it, "f")
writeEntry(it, "links/ok", link = "../f")
writeEntry(it, "rogue", link = "../rogue_f")
}
val dir = tempDir.newDirectory("unpacked").toPath()
val dir = tempDir.resolve("unpacked")
Decompressor.Zip(zip).withZipExtensions().extract(dir)
assertThat(dir.resolve("links/ok")).isSymbolicLink().hasSameBinaryContentAs(dir.resolve("f"))
assertThat(dir.resolve("rogue")).isSymbolicLink().hasSameBinaryContentAs(rogueTarget.toPath())
assertThat(dir.resolve("rogue")).isSymbolicLink().hasSameBinaryContentAs(rogueTarget)
}
@Test fun zipRogueSymlinks() {
@Test fun zipRogueSymlinks(@TempDir tempDir: Path) {
assumeSymLinkCreationIsSupported()
val zip = tempDir.newFile("test.zip")
ZipArchiveOutputStream(FileOutputStream(zip)).use { writeEntry(it, "rogue", link = "../f") }
val zip = tempDir.resolve("test.zip")
ZipArchiveOutputStream(zip.outputStream()).use { writeEntry(it, "rogue", link = "../f") }
val decompressor = Decompressor.Zip(zip).withZipExtensions().escapingSymlinkPolicy(
Decompressor.EscapingSymlinkPolicy.DISALLOW)
val dir = tempDir.newDirectory("unpacked").toPath()
val dir = tempDir.resolve("unpacked")
testNoTraversal(decompressor, dir, dir.resolve("rogue"))
}
@Test fun tarRogueSymlinks() {
@Test fun tarRogueSymlinks(@TempDir tempDir: Path) {
assumeSymLinkCreationIsSupported()
val tar = tempDir.newFile("test.tar")
TarArchiveOutputStream(FileOutputStream(tar)).use { writeEntry(it, "rogue", link = "../f") }
val tar = tempDir.resolve("test.tar")
TarArchiveOutputStream(tar.outputStream()).use { writeEntry(it, "rogue", link = "../f") }
val decompressor = Decompressor.Tar(tar).escapingSymlinkPolicy(
Decompressor.EscapingSymlinkPolicy.DISALLOW)
val dir = tempDir.newDirectory("unpacked").toPath()
val dir = tempDir.resolve("unpacked")
testNoTraversal(decompressor, dir, dir.resolve("rogue"))
}
@Test fun prefixPathsFilesInZip() {
val zip = tempDir.newFile("test.zip")
ZipOutputStream(FileOutputStream(zip)).use {
@Test fun prefixPathsFilesInZip(@TempDir tempDir: Path) {
val zip = tempDir.resolve("test.zip")
ZipOutputStream(zip.outputStream()).use {
writeEntry(it, "a/b/c.txt")
}
val dir = tempDir.newDirectory("unpacked").toPath()
val dir = tempDir.resolve("unpacked")
Decompressor.Zip(zip).removePrefixPath("a/b").extract(dir)
assertThat(dir.resolve("c.txt")).isRegularFile()
@@ -270,12 +276,12 @@ class DecompressorTest {
assertThat(dir.resolve("b")).doesNotExist()
}
@Test fun prefixPathsFilesInCommonsZip() {
val zip = tempDir.newFile("test.zip")
ZipOutputStream(FileOutputStream(zip)).use {
@Test fun prefixPathsFilesInCommonsZip(@TempDir tempDir: Path) {
val zip = tempDir.resolve("test.zip")
ZipOutputStream(zip.outputStream()).use {
writeEntry(it, "a/b/c.txt")
}
val dir = tempDir.newDirectory("unpacked").toPath()
val dir = tempDir.resolve("unpacked")
Decompressor.Zip(zip).removePrefixPath("a/b").extract(dir)
assertThat(dir.resolve("c.txt")).isRegularFile()
@@ -284,13 +290,13 @@ class DecompressorTest {
assertThat(dir.resolve("b")).doesNotExist()
}
@Test fun prefixPathFilesInZipWithFilter() {
val zip = tempDir.newFile("test.zip")
ZipOutputStream(FileOutputStream(zip)).use {
@Test fun prefixPathFilesInZipWithFilter(@TempDir tempDir: Path) {
val zip = tempDir.resolve("test.zip")
ZipOutputStream(zip.outputStream()).use {
writeEntry(it, "a/b/c.txt")
writeEntry(it, "skip.txt")
}
val dir = tempDir.newDirectory("unpacked").toPath()
val dir = tempDir.resolve("unpacked")
val filterLog = mutableListOf<String>()
Decompressor.Zip(zip).removePrefixPath("a/b").filter(Predicate{ filterLog.add(it) }).extract(dir)
@@ -302,40 +308,40 @@ class DecompressorTest {
assertThat(filterLog).containsExactlyInAnyOrder("a/b/c.txt", "skip.txt")
}
@Test fun prefixPathsFilesInTarWithSymlinks() {
@Test fun prefixPathsFilesInTarWithSymlinks(@TempDir tempDir: Path) {
assumeSymLinkCreationIsSupported()
val tar = tempDir.newFile("test.tar")
TarArchiveOutputStream(FileOutputStream(tar)).use {
val tar = tempDir.resolve("test.tar")
TarArchiveOutputStream(tar.outputStream()).use {
writeEntry(it, "a/f")
writeEntry(it, "a/links/ok", link = "../f")
}
val dir = tempDir.newDirectory("unpacked").toPath()
val dir = tempDir.resolve("unpacked")
Decompressor.Tar(tar).removePrefixPath("a").extract(dir)
assertThat(dir.resolve("f")).isRegularFile()
assertThat(dir.resolve("links/ok")).isSymbolicLink().hasSameBinaryContentAs(dir.resolve("f"))
}
@Test fun prefixPathFillMatch() {
val tar = tempDir.newFile("test.tar")
TarArchiveOutputStream(FileOutputStream(tar)).use {
@Test fun prefixPathFillMatch(@TempDir tempDir: Path) {
val tar = tempDir.resolve("test.tar")
TarArchiveOutputStream(tar.outputStream()).use {
writeEntry(it, "./a/f")
}
val dir = tempDir.newDirectory("unpacked").toPath()
val dir = tempDir.resolve("unpacked")
Decompressor.Tar(tar).removePrefixPath("/a/f").extract(dir)
assertThat(dir.resolve("f")).doesNotExist()
}
@Test fun prefixPathWithSlashTar() {
val tar = tempDir.newFile("test.tar")
TarArchiveOutputStream(FileOutputStream(tar)).use {
@Test fun prefixPathWithSlashTar(@TempDir tempDir: Path) {
val tar = tempDir.resolve("test.tar")
TarArchiveOutputStream(tar.outputStream()).use {
writeEntry(it, "./a/f")
writeEntry(it, "/a/g")
writeEntry(it, "././././././//a/h")
}
val dir = tempDir.newDirectory("unpacked").toPath()
val dir = tempDir.resolve("unpacked")
Decompressor.Tar(tar).removePrefixPath("/a/").extract(dir)
assertThat(dir.resolve("f")).isRegularFile()
@@ -343,14 +349,14 @@ class DecompressorTest {
assertThat(dir.resolve("h")).isRegularFile()
}
@Test fun prefixPathWithDotTar() {
val tar = tempDir.newFile("test.tar")
TarArchiveOutputStream(FileOutputStream(tar)).use {
@Test fun prefixPathWithDotTar(@TempDir tempDir: Path) {
val tar = tempDir.resolve("test.tar")
TarArchiveOutputStream(tar.outputStream()).use {
writeEntry(it, "./a/b/f")
writeEntry(it, "/a/b/g")
writeEntry(it, "././././././//a/b/h")
}
val dir = tempDir.newDirectory("unpacked").toPath()
val dir = tempDir.resolve("unpacked")
Decompressor.Tar(tar).removePrefixPath("./a/b").extract(dir)
assertThat(dir.resolve("f")).isRegularFile()
@@ -358,14 +364,14 @@ class DecompressorTest {
assertThat(dir.resolve("h")).isRegularFile()
}
@Test fun prefixPathWithCommonsZip() {
val zip = tempDir.newFile("test.zip")
ZipArchiveOutputStream(FileOutputStream(zip)).use {
@Test fun prefixPathWithCommonsZip(@TempDir tempDir: Path) {
val zip = tempDir.resolve("test.zip")
ZipArchiveOutputStream(zip.outputStream()).use {
writeEntry(it, "./a/b/f")
writeEntry(it, "/a/b/g")
writeEntry(it, "././././././//a/b/h")
}
val dir = tempDir.newDirectory("unpacked").toPath()
val dir = tempDir.resolve("unpacked")
Decompressor.Zip(zip).removePrefixPath("./a/b").extract(dir)
assertThat(dir.resolve("f")).isRegularFile()
@@ -373,93 +379,92 @@ class DecompressorTest {
assertThat(dir.resolve("h")).isRegularFile()
}
@Test fun prefixPathTarSymlink() {
@Test fun prefixPathTarSymlink(@TempDir tempDir: Path) {
assumeSymLinkCreationIsSupported()
val tar = tempDir.newFile("test.tar")
TarArchiveOutputStream(FileOutputStream(tar)).use {
val tar = tempDir.resolve("test.tar")
TarArchiveOutputStream(tar.outputStream()).use {
writeEntry(it, "./a/b/f")
writeEntry(it, "a/b/links/ok", link = "../f")
}
val dir = tempDir.newDirectory("unpacked").toPath()
val dir = tempDir.resolve("unpacked")
Decompressor.Tar(tar).removePrefixPath("a/b").extract(dir)
assertThat(dir.resolve("f")).isRegularFile()
assertThat(dir.resolve("links/ok")).isSymbolicLink().hasSameBinaryContentAs(dir.resolve("f"))
}
@Test fun prefixPathZipSymlink() {
@Test fun prefixPathZipSymlink(@TempDir tempDir: Path) {
assumeSymLinkCreationIsSupported()
val zip = tempDir.newFile("test.zip")
ZipArchiveOutputStream(FileOutputStream(zip)).use {
val zip = tempDir.resolve("test.zip")
ZipArchiveOutputStream(zip.outputStream()).use {
writeEntry(it, "./a/b/f")
writeEntry(it, "a/b/links/ok", link = "../f")
}
val dir = tempDir.newDirectory("unpacked").toPath()
val dir = tempDir.resolve("unpacked")
Decompressor.Zip(zip).withZipExtensions().removePrefixPath("a/b").extract(dir)
assertThat(dir.resolve("f")).isRegularFile()
assertThat(dir.resolve("links/ok")).isSymbolicLink().hasSameBinaryContentAs(dir.resolve("f"))
}
@Test fun prefixPathTarRogueSymlinks() {
@Test fun prefixPathTarRogueSymlinks(@TempDir tempDir: Path) {
assumeSymLinkCreationIsSupported()
val tar = tempDir.newFile("test.tar")
TarArchiveOutputStream(FileOutputStream(tar)).use { writeEntry(it, "a/b/c/rogue", link = "../f") }
val tar = tempDir.resolve("test.tar")
TarArchiveOutputStream(tar.outputStream()).use { writeEntry(it, "a/b/c/rogue", link = "../f") }
val decompressor = Decompressor.Tar(tar).escapingSymlinkPolicy(
Decompressor.EscapingSymlinkPolicy.DISALLOW).removePrefixPath("a/b/c")
val dir = tempDir.newDirectory("unpacked").toPath()
val dir = tempDir.resolve("unpacked")
testNoTraversal(decompressor, dir, dir.resolve("rogue"))
}
@Test fun prefixPathZipRogueSymlinks() {
@Test fun prefixPathZipRogueSymlinks(@TempDir tempDir: Path) {
assumeSymLinkCreationIsSupported()
val zip = tempDir.newFile("test.zip")
ZipArchiveOutputStream(FileOutputStream(zip)).use { writeEntry(it, "a/b/c/rogue", link = "../f") }
val zip = tempDir.resolve("test.zip")
ZipArchiveOutputStream(zip.outputStream()).use { writeEntry(it, "a/b/c/rogue", link = "../f") }
val decompressor = Decompressor.Zip(zip).withZipExtensions().escapingSymlinkPolicy(
Decompressor.EscapingSymlinkPolicy.DISALLOW).removePrefixPath("a/b/c")
val dir = tempDir.newDirectory("unpacked").toPath()
val dir = tempDir.resolve("unpacked")
testNoTraversal(decompressor, dir, dir.resolve("rogue"))
}
@Test fun prefixPathSkipsTooShortPaths() {
val tar = tempDir.newFile("test.tar")
TarArchiveOutputStream(FileOutputStream(tar)).use {
@Test fun prefixPathSkipsTooShortPaths(@TempDir tempDir: Path) {
val tar = tempDir.resolve("test.tar")
TarArchiveOutputStream(tar.outputStream()).use {
writeEntry(it, "missed")
writeEntry(it, "a/b/c/file.txt")
}
val dir = tempDir.newDirectory("unpacked").toPath()
val dir = tempDir.resolve("unpacked")
Decompressor.Tar(tar).removePrefixPath("a/b").extract(dir)
assertThat(dir.resolve("c/file.txt")).isRegularFile()
assertThat(dir.resolve("missed")).doesNotExist()
}
@Test fun fileOverwrite() {
val zip = tempDir.newFile("test.zip")
ZipOutputStream(FileOutputStream(zip)).use { writeEntry(it, "a/file.txt") }
val dir = tempDir.newDirectory("unpacked")
val file = tempDir.newFile("unpacked/a/file.txt", byteArrayOf(0))
@Test fun fileOverwrite(@TempDir tempDir: Path) {
val zip = tempDir.resolve("test.zip")
ZipOutputStream(zip.outputStream()).use { writeEntry(it, "a/file.txt") }
val dir = tempDir.resolve("unpacked")
val file = tempDir.resolve("unpacked/a/file.txt").createParentDirectories().apply { writeBytes(byteArrayOf(0)) }
Decompressor.Zip(zip).extract(dir)
assertThat(file).hasBinaryContent(TestContent)
}
@Test fun symlinkOverwrite() {
@Test fun symlinkOverwrite(@TempDir tempDir: Path) {
assumeSymLinkCreationIsSupported()
val tar = tempDir.newFile("test.tar")
TarArchiveOutputStream(FileOutputStream(tar)).use {
val tar = tempDir.resolve("test.tar")
TarArchiveOutputStream(tar.outputStream()).use {
writeEntry(it, "a/file")
writeEntry(it, "a/link", link = "file")
}
val dir = tempDir.newDirectory("unpacked")
val link = tempDir.rootPath.resolve("unpacked/a/link")
val target = tempDir.newFile("unpacked/a/target", byteArrayOf(0)).toPath()
Files.createSymbolicLink(link, target)
val dir = tempDir.resolve("unpacked")
val target = tempDir.resolve("unpacked/a/target").createParentDirectories().apply { writeBytes(byteArrayOf(0)) }
val link = tempDir.resolve("unpacked/a/link").createSymbolicLinkPointingTo(target)
Decompressor.Tar(tar).extract(dir)
assertThat(link).isSymbolicLink().hasBinaryContent(TestContent)
}
@@ -467,11 +472,11 @@ class DecompressorTest {
@Test fun extZipPureNIO() {
MemoryFileSystemBuilder.newLinux().build("${DecompressorTest::class.simpleName}.extZipPureNIO").use { fs ->
val testDir = fs.getPath("/home/${SystemProperties.getUserName()}")
val zip = Files.createFile(testDir.resolve("test.zip"))
ZipArchiveOutputStream(Files.newOutputStream(zip)).use {
val zip = testDir.resolve("test.zip").createFile()
ZipArchiveOutputStream(zip.outputStream()).use {
writeEntry(it, "dir/r", mode = 0b100_000_000)
}
val dir = Files.createDirectory(testDir.resolve("unpacked"))
val dir = testDir.resolve("unpacked").createDirectories()
Decompressor.Zip(zip).withZipExtensions().extract(dir)
assertThat(dir.resolve("dir/r")).exists()
}
@@ -480,40 +485,40 @@ class DecompressorTest {
@Test fun tarPureNIO() {
MemoryFileSystemBuilder.newLinux().build("${DecompressorTest::class.simpleName}.tarPureNIO").use { fs ->
val testDir = fs.getPath("/home/${SystemProperties.getUserName()}")
val tar = Files.createFile(testDir.resolve("test.tar"))
TarArchiveOutputStream(Files.newOutputStream(tar)).use {
val tar = testDir.resolve("test.tar").createFile()
TarArchiveOutputStream(tar.outputStream()).use {
writeEntry(it, "dir/r", mode = 0b100_000_000)
}
val dir = Files.createDirectory(testDir.resolve("unpacked"))
val dir = testDir.resolve("unpacked").createDirectories()
Decompressor.Tar(tar).extract(dir)
assertThat(dir.resolve("dir/r")).exists()
}
}
@Test fun absoluteSymlinkToRelativeWithOptionSet() {
val tar = tempDir.newFile("test.tar")
TarArchiveOutputStream(FileOutputStream(tar)).use {
@Test fun absoluteSymlinkToRelativeWithOptionSet(@TempDir tempDir: Path) {
val tar = tempDir.resolve("test.tar")
TarArchiveOutputStream(tar.outputStream()).use {
writeEntry(it, "symlink", link = "/root")
}
val dir = tempDir.newDirectory("unpacked").toPath()
val dir = tempDir.resolve("unpacked")
Decompressor.Tar(tar).escapingSymlinkPolicy(
Decompressor.EscapingSymlinkPolicy.RELATIVIZE_ABSOLUTE).extract(dir)
val symlink = dir.resolve("symlink")
assertThat(symlink).isSymbolicLink()
assertThat(Files.readSymbolicLink(symlink)).isEqualTo(dir.resolve("root"))
assertThat(symlink.readSymbolicLink()).isEqualTo(dir.resolve("root"))
}
@Test fun retryStrategyErrorHandler() {
val zip = tempDir.newFile("retryStrategyErrorHandler.zip")
ZipArchiveOutputStream(FileOutputStream(zip)).use {
@Test fun retryStrategyErrorHandler(@TempDir tempDir: Path) {
val zip = tempDir.resolve("retryStrategyErrorHandler.zip")
ZipArchiveOutputStream(zip.outputStream()).use {
writeEntry(it, "good-file.txt")
writeEntry(it, "bad-file.txt", link = "")
writeEntry(it, "good-file-too.md")
}
var retries = 3 // to make sure if we really make retrying
val dir = tempDir.newDirectory("unpacked").toPath()
val dir = tempDir.resolve("unpacked")
Decompressor.Zip(zip).withZipExtensions().errorHandler { _, _ ->
if (retries == 0) {
@@ -529,46 +534,46 @@ class DecompressorTest {
assertThat(dir.resolve("good-file-too.md")).exists()
}
@Test fun abortStrategyErrorHandlerDeletingFiles() {
val zip = tempDir.newFile("abortStrategyErrorHandlerDeletingFiles.zip")
ZipArchiveOutputStream(FileOutputStream(zip)).use {
@Test fun abortStrategyErrorHandlerDeletingFiles(@TempDir tempDir: Path) {
val zip = tempDir.resolve("abortStrategyErrorHandlerDeletingFiles.zip")
ZipArchiveOutputStream(zip.outputStream()).use {
writeEntry(it, "good-file.txt")
writeEntry(it, "very-good-file.java")
writeEntry(it, "bad-file.txt", link = "")
}
val dir = tempDir.newDirectory("unpacked").toPath()
val dir = tempDir.resolve("unpacked")
Decompressor.Zip(zip).withZipExtensions().errorHandler { _, _ -> Decompressor.ErrorHandlerChoice.ABORT }.extract(dir)
assertThat(dir.resolve("good-file.txt")).doesNotExist()
assertThat(dir.resolve("very-good-file.java")).doesNotExist()
}
@Test fun skipStrategyErrorHandlerNotDeletingFiles() {
val zip = tempDir.newFile("skipStrategyErrorHandlerNotDeletingFiles.zip")
ZipArchiveOutputStream(FileOutputStream(zip)).use {
@Test fun skipStrategyErrorHandlerNotDeletingFiles(@TempDir tempDir: Path) {
val zip = tempDir.resolve("skipStrategyErrorHandlerNotDeletingFiles.zip")
ZipArchiveOutputStream(zip.outputStream()).use {
writeEntry(it, "good-file.txt")
writeEntry(it, "bad-file.txt", link = "")
writeEntry(it, "very-good-file.java")
}
val dir = tempDir.newDirectory("unpacked").toPath()
val dir = tempDir.resolve("unpacked")
Decompressor.Zip(zip).withZipExtensions().errorHandler { _, _ -> Decompressor.ErrorHandlerChoice.SKIP }.extract(dir)
assertThat(dir.resolve("good-file.txt")).exists()
assertThat(dir.resolve("very-good-file.java")).exists()
}
@Test fun doNothingStrategyErrorHandlerNotDeletingFilesBeforeSkipAfter() {
val zip = tempDir.newFile("doNothingStrategyErrorHandlerNotDeletingFilesBeforeSkipAfter.zip")
ZipArchiveOutputStream(FileOutputStream(zip)).use {
@Test fun doNothingStrategyErrorHandlerNotDeletingFilesBeforeSkipAfter(@TempDir tempDir: Path) {
val zip = tempDir.resolve("doNothingStrategyErrorHandlerNotDeletingFilesBeforeSkipAfter.zip")
ZipArchiveOutputStream(zip.outputStream()).use {
writeEntry(it, "good-file.txt")
writeEntry(it, "very-good-file.java")
writeEntry(it, "bad-file.txt", link = "")
writeEntry(it, "good-but-unlucky-file.kt")
}
val dir = tempDir.newDirectory("unpacked").toPath()
val dir = tempDir.resolve("unpacked")
assertThatThrownBy {
Decompressor.Zip(zip).withZipExtensions().errorHandler { _, _ -> Decompressor.ErrorHandlerChoice.BAIL_OUT }.extract(dir)
}.isInstanceOf(IOException::class.java)
@@ -578,15 +583,15 @@ class DecompressorTest {
assertThat(dir.resolve("good-but-unlucky-file.kt")).doesNotExist()
}
@Test fun skipAllStrategyCalledOnlyOnce() {
val zip = tempDir.newFile("skipAllStrategyCalledOnlyOnce.zip")
ZipArchiveOutputStream(FileOutputStream(zip)).use {
@Test fun skipAllStrategyCalledOnlyOnce(@TempDir tempDir: Path) {
val zip = tempDir.resolve("skipAllStrategyCalledOnlyOnce.zip")
ZipArchiveOutputStream(zip.outputStream()).use {
writeEntry(it, "bad-file.txt", link = "")
writeEntry(it, "another-bad-file.txt", link = "")
writeEntry(it, "another-bad-file.cpp", link = "")
}
var isCalled = false
val dir = tempDir.newDirectory("unpacked").toPath()
val dir = tempDir.resolve("unpacked")
Decompressor.Zip(zip).withZipExtensions().errorHandler { _, _ ->
if (!isCalled) {
@@ -596,6 +601,8 @@ class DecompressorTest {
throw AssertionError("SKIP_ALL strategy can't be called twice")
}
}.extract(dir)
assertThat(isCalled).isTrue
}
//<editor-fold desc="Helpers.">
@@ -658,9 +665,9 @@ class DecompressorTest {
companion object {
private val TestContent = "...".toByteArray()
private val Writable = Condition<Path>(Predicate { Files.isWritable(it) }, "writable")
private val Executable = Condition<Path>(Predicate { Files.isExecutable(it) }, "executable")
private val Hidden = Condition<Path>(Predicate { Files.isHidden(it) }, "hidden")
private val Writable = Condition<Path>(Predicate { it.isWritable() }, "writable")
private val Executable = Condition<Path>(Predicate { it.isExecutable() }, "executable")
private val Hidden = Condition<Path>(Predicate { it.isHidden() }, "hidden")
}
//</editor-fold>
}