-
-
Save dellisd/a1df42787d42b41cd3ce16f573984674 to your computer and use it in GitHub Desktop.
| // Part of a multi-module project, hence the rootProject everywhere | |
| task copyTestResourcesForJs(type: Copy) { | |
| from "$projectDir/src/commonTest/resources" | |
| into "${rootProject.buildDir}/js/packages/${rootProject.name}-${project.name}-test/src/commonTest/resources" | |
| } | |
| jsNodeTest.dependsOn copyTestResourcesForJs |
| // Common | |
| const val RESOURCE_PATH = "./src/commonTest/resources" | |
| expect class Resource(name: String) { | |
| val name: String | |
| fun exists(): Boolean | |
| fun readText(): String | |
| } | |
| // JVM | |
| import java.io.File | |
| actual class Resource actual constructor(actual val name: String) { | |
| private val file = File("$RESOURCE_PATH/$name") | |
| actual fun exists(): Boolean = file.exists() | |
| actual fun readText(): String = file.readText() | |
| } | |
| // Native | |
| import kotlinx.cinterop.* | |
| import platform.posix.* | |
| actual class Resource actual constructor(actual val name: String) { | |
| private val file: CPointer<FILE>? = fopen("$RESOURCE_PATH/$name", "r") | |
| actual fun exists(): Boolean = file != null | |
| actual fun readText(): String { | |
| fseek(file, 0, SEEK_END) | |
| val size = ftell(file) | |
| rewind(file) | |
| return memScoped { | |
| val tmp = allocArray<ByteVar>(size) | |
| fread(tmp, sizeOf<ByteVar>().convert(), size.convert(), file) | |
| tmp.toKString() | |
| } | |
| } | |
| } | |
| // JS (Node) | |
| private external fun require(module: String): dynamic | |
| private val fs = require("fs") | |
| actual class Resource actual constructor(actual val name: String) { | |
| private val path = "$RESOURCE_PATH/$name" | |
| actual fun exists(): Boolean = fs.existsSync(path) as Boolean | |
| actual fun readText(): String = fs.readFileSync(path, "utf8") as String | |
| } |
| @Test | |
| fun testLength2() { | |
| // Located at /src/commonTest/resources/test.json | |
| val resource = Resource("test.json") | |
| val geometry = resource.readText().toGeometry<LineString>() | |
| assertEquals(42.560767589197006, length(geometry, Units.Kilometers)) | |
| } |
Yesterday I played with this script a bit and it didn't really work for iosX64 target. I guess it's more complicated than that, after all it's not run inside an ios filesystem (although on an m1 mac there should be a way).
That's true. This was built for use in JVM, Native (non-iOS/watchOS/tvOS), and Node environments.
Android Instrumentation tests, those other Apple environments, and Browser environments would require some more work, but I suspect they're not impossible.
It didn't work for me while trying to run tests on iOS. This modification did the job:
// Native
import kotlinx.cinterop.*
import platform.posix.*
actual class Resource actual constructor(actual val name: String) {
private val path = NSBundle.mainBundle.pathForResource("resources/FILE_NAME", "FILE_EXTENSION") ?: ""
private val file: CPointer<FILE>? = fopen(path, "r")Then, in the build.gradle.kts file:
tasks.register<Copy>("copyiOSTestResources") {
from("src/commonTest/resources")
into("build/bin/iosX64/debugTest/resources")
}
tasks.findByName("iosX64Test")!!.dependsOn("copyiOSTestResources")This article helped me out a lot: https://developer.squareup.com/blog/kotlin-multiplatform-shared-test-resources/
Cannot you simply specify
private val path = "kotlin/$name"in the JS implementation of the Resource class's constructor (i.e. without the need for the copyTestResourcesForJs Gradle task)?
I haven't had a need to stream the input yet so I haven't really thought much about it, but you could probably use something like Okio and return an implementation of a
Source(or whatever implementation of an InputStream you want to use). You'd just have to adjust thefreadcall to read the number of bytes that are requested.