From 20b83aaf698d282cd98d26fe0b51d92305a75fd0 Mon Sep 17 00:00:00 2001 From: Jesse Wilson Date: Thu, 22 Feb 2024 07:37:35 -0500 Subject: [PATCH] Get openZip working on KotlinNative (#1439) * Get openZip working on KotlinNative * No assertk for wasmJs or wasmWasi * Make okioRoot lazy --- build.gradle.kts | 22 ++++++++++++ okio-testing-support/build.gradle.kts | 6 ++++ .../commonMain/kotlin/okio/TestingCommon.kt | 7 ++++ .../resources/okio/zipfilesystem/empty.zip | Bin 22 -> 63 bytes .../src/jsMain/kotlin/okio/TestingJs.kt | 3 ++ .../src/jvmMain/kotlin/okio/TestingJvm.kt | 4 +++ .../nativeMain/kotlin/okio/TestingNative.kt | 9 +++++ .../src/wasmMain/kotlin/okio/TestingWasm.kt | 2 ++ .../src/zlibMain/kotlin/okio/TestingZlib.kt | 18 ++++++++++ okio/build.gradle.kts | 3 ++ okio/src/jvmMain/kotlin/okio/JvmOkio.kt | 3 -- .../kotlin/okio/internal/-ZlibNative.kt | 2 +- .../kotlin/okio/ZipFileSystem.kt | 2 -- okio/src/zlibMain/kotlin/okio/ZlibOkio.kt | 26 ++++++++++++++ .../kotlin/okio/internal/FixedLengthSource.kt | 0 .../kotlin/okio/internal/ZipEntry.kt | 0 .../kotlin/okio/internal/ZipFiles.kt | 1 + .../kotlin/okio/ZipFileSystemTest.kt | 32 ++++++++++++------ 18 files changed, 123 insertions(+), 17 deletions(-) create mode 100644 okio-testing-support/src/zlibMain/kotlin/okio/TestingZlib.kt rename okio/src/{jvmMain => zlibMain}/kotlin/okio/ZipFileSystem.kt (98%) create mode 100644 okio/src/zlibMain/kotlin/okio/ZlibOkio.kt rename okio/src/{jvmMain => zlibMain}/kotlin/okio/internal/FixedLengthSource.kt (100%) rename okio/src/{jvmMain => zlibMain}/kotlin/okio/internal/ZipEntry.kt (100%) rename okio/src/{jvmMain => zlibMain}/kotlin/okio/internal/ZipFiles.kt (99%) rename okio/src/{jvmTest => zlibTest}/kotlin/okio/ZipFileSystemTest.kt (94%) diff --git a/build.gradle.kts b/build.gradle.kts index f564d88a9e..c9490faae0 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,6 +15,9 @@ import org.jetbrains.dokka.gradle.DokkaTask import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmInstallTask +import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest +import org.jetbrains.kotlin.gradle.targets.jvm.tasks.KotlinJvmTest +import org.jetbrains.kotlin.gradle.targets.native.tasks.KotlinNativeTest import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { @@ -246,3 +249,22 @@ plugins.withType { args += "--ignore-engines" } } + +/** + * Set the `OKIO_ROOT` environment variable for tests to access it. + * https://publicobject.com/2023/04/16/read-a-project-file-in-a-kotlin-multiplatform-test/ + */ +allprojects { + tasks.withType().configureEach { + environment("OKIO_ROOT", rootDir) + } + + tasks.withType().configureEach { + environment("SIMCTL_CHILD_OKIO_ROOT", rootDir) + environment("OKIO_ROOT", rootDir) + } + + tasks.withType().configureEach { + environment("OKIO_ROOT", rootDir.toString()) + } +} diff --git a/okio-testing-support/build.gradle.kts b/okio-testing-support/build.gradle.kts index bdf3506f11..874bdf825d 100644 --- a/okio-testing-support/build.gradle.kts +++ b/okio-testing-support/build.gradle.kts @@ -28,6 +28,10 @@ kotlin { } } + val zlibMain by creating { + dependsOn(commonMain) + } + if (kmpJsEnabled) { val jsMain by getting { dependsOn(nonWasmMain) @@ -36,6 +40,7 @@ kotlin { val jvmMain by getting { dependsOn(nonWasmMain) + dependsOn(zlibMain) dependencies { // On the JVM the kotlin-test library resolves to one of three implementations based on // which testing framework is in use. JUnit is used downstream, but Gradle can't know that @@ -48,6 +53,7 @@ kotlin { createSourceSet("nativeMain", children = nativeTargets) .also { nativeMain -> nativeMain.dependsOn(nonWasmMain) + nativeMain.dependsOn(zlibMain) } } diff --git a/okio-testing-support/src/commonMain/kotlin/okio/TestingCommon.kt b/okio-testing-support/src/commonMain/kotlin/okio/TestingCommon.kt index 7a47b06814..d3a08214f8 100644 --- a/okio-testing-support/src/commonMain/kotlin/okio/TestingCommon.kt +++ b/okio-testing-support/src/commonMain/kotlin/okio/TestingCommon.kt @@ -19,6 +19,7 @@ import kotlin.random.Random import kotlin.test.assertEquals import kotlin.time.Duration import okio.ByteString.Companion.toByteString +import okio.Path.Companion.toPath fun Char.repeat(count: Int): String { return toString().repeat(count) @@ -90,3 +91,9 @@ expect val FileSystem.allowSymlinks: Boolean expect val FileSystem.allowReadsWhileWriting: Boolean expect var FileSystem.workingDirectory: Path + +expect fun getEnv(name: String): String? + +val okioRoot: Path by lazy { + getEnv("OKIO_ROOT")!!.toPath() +} diff --git a/okio-testing-support/src/commonMain/resources/okio/zipfilesystem/empty.zip b/okio-testing-support/src/commonMain/resources/okio/zipfilesystem/empty.zip index 15cb0ecb3e219d1701294bfdf0fe3f5cb5d208e7..a2ab2628daa805b1a9b9ae98a5e648383578493c 100644 GIT binary patch literal 63 zcmeZB&B@7E@Kn!L$STdtR!B)KNmM8(N-apuOG!;pD9KkS$w*a*@(fT6@MdLWzyJVh Cj}Dmt literal 22 NcmWIWW@Tf*000g10H*)| diff --git a/okio-testing-support/src/jsMain/kotlin/okio/TestingJs.kt b/okio-testing-support/src/jsMain/kotlin/okio/TestingJs.kt index 21442a5c07..82d7067dbc 100644 --- a/okio-testing-support/src/jsMain/kotlin/okio/TestingJs.kt +++ b/okio-testing-support/src/jsMain/kotlin/okio/TestingJs.kt @@ -20,3 +20,6 @@ actual fun isBrowser(): Boolean { } actual fun isWasm() = false + +actual fun getEnv(name: String): String? = + js("globalThis.process.env[name]") as String? diff --git a/okio-testing-support/src/jvmMain/kotlin/okio/TestingJvm.kt b/okio-testing-support/src/jvmMain/kotlin/okio/TestingJvm.kt index d6e274db1b..1f52b0870d 100644 --- a/okio-testing-support/src/jvmMain/kotlin/okio/TestingJvm.kt +++ b/okio-testing-support/src/jvmMain/kotlin/okio/TestingJvm.kt @@ -15,6 +15,10 @@ */ package okio +actual val SYSTEM_FILE_SYSTEM = FileSystem.SYSTEM + actual fun isBrowser() = false actual fun isWasm() = false + +actual fun getEnv(name: String): String? = System.getenv(name) diff --git a/okio-testing-support/src/nativeMain/kotlin/okio/TestingNative.kt b/okio-testing-support/src/nativeMain/kotlin/okio/TestingNative.kt index d6e274db1b..a7d223ba0d 100644 --- a/okio-testing-support/src/nativeMain/kotlin/okio/TestingNative.kt +++ b/okio-testing-support/src/nativeMain/kotlin/okio/TestingNative.kt @@ -15,6 +15,15 @@ */ package okio +import kotlinx.cinterop.ExperimentalForeignApi +import kotlinx.cinterop.toKString +import platform.posix.getenv + +actual val SYSTEM_FILE_SYSTEM = FileSystem.SYSTEM + actual fun isBrowser() = false actual fun isWasm() = false + +@OptIn(ExperimentalForeignApi::class) +actual fun getEnv(name: String): String? = getenv(name)?.toKString() diff --git a/okio-testing-support/src/wasmMain/kotlin/okio/TestingWasm.kt b/okio-testing-support/src/wasmMain/kotlin/okio/TestingWasm.kt index cb84178308..865cf716a9 100644 --- a/okio-testing-support/src/wasmMain/kotlin/okio/TestingWasm.kt +++ b/okio-testing-support/src/wasmMain/kotlin/okio/TestingWasm.kt @@ -59,3 +59,5 @@ actual val FileSystem.allowReadsWhileWriting: Boolean actual var FileSystem.workingDirectory: Path get() = error("unexpected call") set(_) = error("unexpected call") + +actual fun getEnv(name: String): String? = error("unexpected call") diff --git a/okio-testing-support/src/zlibMain/kotlin/okio/TestingZlib.kt b/okio-testing-support/src/zlibMain/kotlin/okio/TestingZlib.kt new file mode 100644 index 0000000000..aa4c599de3 --- /dev/null +++ b/okio-testing-support/src/zlibMain/kotlin/okio/TestingZlib.kt @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2024 Square, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package okio + +expect val SYSTEM_FILE_SYSTEM: FileSystem diff --git a/okio/build.gradle.kts b/okio/build.gradle.kts index db8abfc2af..11a0acad0b 100644 --- a/okio/build.gradle.kts +++ b/okio/build.gradle.kts @@ -97,6 +97,9 @@ kotlin { val zlibTest by creating { dependsOn(commonTest) + dependencies { + implementation(libs.test.assertk) + } } val jvmMain by getting { diff --git a/okio/src/jvmMain/kotlin/okio/JvmOkio.kt b/okio/src/jvmMain/kotlin/okio/JvmOkio.kt index 614c48b920..44a046f261 100644 --- a/okio/src/jvmMain/kotlin/okio/JvmOkio.kt +++ b/okio/src/jvmMain/kotlin/okio/JvmOkio.kt @@ -224,9 +224,6 @@ fun Sink.hashingSink(digest: MessageDigest): HashingSink = HashingSink(this, dig */ fun Source.hashingSource(digest: MessageDigest): HashingSource = HashingSource(this, digest) -@Throws(IOException::class) -fun FileSystem.openZip(zipPath: Path): FileSystem = okio.internal.openZip(zipPath, this) - fun ClassLoader.asResourceFileSystem(): FileSystem = ResourceFileSystem(this, indexEagerly = true) /** diff --git a/okio/src/nativeMain/kotlin/okio/internal/-ZlibNative.kt b/okio/src/nativeMain/kotlin/okio/internal/-ZlibNative.kt index a7ee44e065..ac8533998d 100644 --- a/okio/src/nativeMain/kotlin/okio/internal/-ZlibNative.kt +++ b/okio/src/nativeMain/kotlin/okio/internal/-ZlibNative.kt @@ -20,7 +20,7 @@ internal actual val DEFAULT_COMPRESSION: Int = platform.zlib.Z_DEFAULT_COMPRESSI /** * Roll our own date math because Kotlin doesn't include a built-in date math API, and the - * kotlinx.datetime library doesn't offer a stable at this time. + * kotlinx.datetime library doesn't offer a stable release at this time. * * Also, we don't necessarily want to take on that dependency for Okio. * diff --git a/okio/src/jvmMain/kotlin/okio/ZipFileSystem.kt b/okio/src/zlibMain/kotlin/okio/ZipFileSystem.kt similarity index 98% rename from okio/src/jvmMain/kotlin/okio/ZipFileSystem.kt rename to okio/src/zlibMain/kotlin/okio/ZipFileSystem.kt index 2c8d9ea5f5..2660ae44d7 100644 --- a/okio/src/jvmMain/kotlin/okio/ZipFileSystem.kt +++ b/okio/src/zlibMain/kotlin/okio/ZipFileSystem.kt @@ -16,8 +16,6 @@ */ package okio -import java.io.FileNotFoundException -import java.util.zip.Inflater import okio.Path.Companion.toPath import okio.internal.COMPRESSION_METHOD_STORED import okio.internal.FixedLengthSource diff --git a/okio/src/zlibMain/kotlin/okio/ZlibOkio.kt b/okio/src/zlibMain/kotlin/okio/ZlibOkio.kt new file mode 100644 index 0000000000..cf4c0315ae --- /dev/null +++ b/okio/src/zlibMain/kotlin/okio/ZlibOkio.kt @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2014 Square, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:JvmMultifileClass +@file:JvmName("Okio") + +package okio + +import kotlin.jvm.JvmMultifileClass +import kotlin.jvm.JvmName + +@Throws(IOException::class) +fun FileSystem.openZip(zipPath: Path): FileSystem = okio.internal.openZip(zipPath, this) diff --git a/okio/src/jvmMain/kotlin/okio/internal/FixedLengthSource.kt b/okio/src/zlibMain/kotlin/okio/internal/FixedLengthSource.kt similarity index 100% rename from okio/src/jvmMain/kotlin/okio/internal/FixedLengthSource.kt rename to okio/src/zlibMain/kotlin/okio/internal/FixedLengthSource.kt diff --git a/okio/src/jvmMain/kotlin/okio/internal/ZipEntry.kt b/okio/src/zlibMain/kotlin/okio/internal/ZipEntry.kt similarity index 100% rename from okio/src/jvmMain/kotlin/okio/internal/ZipEntry.kt rename to okio/src/zlibMain/kotlin/okio/internal/ZipEntry.kt diff --git a/okio/src/jvmMain/kotlin/okio/internal/ZipFiles.kt b/okio/src/zlibMain/kotlin/okio/internal/ZipFiles.kt similarity index 99% rename from okio/src/jvmMain/kotlin/okio/internal/ZipFiles.kt rename to okio/src/zlibMain/kotlin/okio/internal/ZipFiles.kt index f65e82b32e..201a7e6e16 100644 --- a/okio/src/jvmMain/kotlin/okio/internal/ZipFiles.kt +++ b/okio/src/zlibMain/kotlin/okio/internal/ZipFiles.kt @@ -24,6 +24,7 @@ import okio.Path import okio.Path.Companion.toPath import okio.ZipFileSystem import okio.buffer +import okio.use private const val LOCAL_FILE_HEADER_SIGNATURE = 0x4034b50 private const val CENTRAL_FILE_HEADER_SIGNATURE = 0x2014b50 diff --git a/okio/src/jvmTest/kotlin/okio/ZipFileSystemTest.kt b/okio/src/zlibTest/kotlin/okio/ZipFileSystemTest.kt similarity index 94% rename from okio/src/jvmTest/kotlin/okio/ZipFileSystemTest.kt rename to okio/src/zlibTest/kotlin/okio/ZipFileSystemTest.kt index 6b11e5ed8a..069955b930 100644 --- a/okio/src/jvmTest/kotlin/okio/ZipFileSystemTest.kt +++ b/okio/src/zlibTest/kotlin/okio/ZipFileSystemTest.kt @@ -15,20 +15,30 @@ */ package okio +import assertk.assertThat +import assertk.assertions.containsExactly +import assertk.assertions.containsExactlyInAnyOrder +import assertk.assertions.isEmpty +import assertk.assertions.isEqualTo +import assertk.assertions.isFalse +import assertk.assertions.isGreaterThan +import assertk.assertions.isLessThan +import assertk.assertions.isNotNull +import assertk.assertions.isNull +import assertk.assertions.isTrue +import kotlin.test.BeforeTest +import kotlin.test.Test import kotlin.test.assertFailsWith import kotlinx.datetime.Instant import okio.ByteString.Companion.decodeHex import okio.ByteString.Companion.encodeUtf8 import okio.Path.Companion.toPath -import org.assertj.core.api.Assertions.assertThat -import org.junit.Before -import org.junit.Test class ZipFileSystemTest { - private val fileSystem = FileSystem.SYSTEM - private var base = "../okio-testing-support/src/commonMain/resources/okio/zipfilesystem".toPath() + private val fileSystem = SYSTEM_FILE_SYSTEM + private var base = okioRoot / "okio-testing-support/src/commonMain/resources/okio/zipfilesystem" - @Before + @BeforeTest fun setUp() { fileSystem.createDirectory(base) } @@ -83,7 +93,7 @@ class ZipFileSystemTest { .isEqualTo("Another file!") assertThat(zipFileSystem.list("/".toPath())) - .hasSameElementsAs(listOf("/hello.txt".toPath(), "/directory".toPath())) + .containsExactlyInAnyOrder("/hello.txt".toPath(), "/directory".toPath()) assertThat(zipFileSystem.list("/directory".toPath())) .containsExactly("/directory/subdirectory".toPath()) assertThat(zipFileSystem.list("/directory/subdirectory".toPath())) @@ -112,7 +122,7 @@ class ZipFileSystemTest { fun zipWithDeflate() { val content = "Android\n".repeat(1000) val zipPath = base / "zipWithDeflate.zip" - assertThat(fileSystem.metadata(zipPath).size).isLessThan(content.length.toLong()) + assertThat(fileSystem.metadata(zipPath).size).isNotNull().isLessThan(content.length.toLong()) val zipFileSystem = fileSystem.openZip(zipPath) assertThat(zipFileSystem.read("a.txt".toPath()) { readUtf8() }) @@ -138,7 +148,7 @@ class ZipFileSystemTest { fun zipWithStore() { val content = "Android\n".repeat(1000) val zipPath = base / "zipWithStore.zip" - assertThat(fileSystem.metadata(zipPath).size).isGreaterThan(content.length.toLong()) + assertThat(fileSystem.metadata(zipPath).size).isNotNull().isGreaterThan(content.length.toLong()) val zipFileSystem = fileSystem.openZip(zipPath) assertThat(zipFileSystem.read("a.txt".toPath()) { readUtf8() }) @@ -524,8 +534,8 @@ class ZipFileSystemTest { * `META-INF/kotlin-gradle-statistics.kotlin_module`. * * We used to crash on duplicates, but they are common in practice so now we prefer the last - * entry. This behavior is consistent with both [java.util.zip.ZipFile] and - * [java.nio.file.FileSystem]. + * entry. This behavior is consistent with both `java.util.zip.ZipFile` and + * `java.nio.file.FileSystem`. * * ``` * echo "This is the first hello.txt" > hello.txt