diff --git a/.gitignore b/.gitignore index 347e252e..3f18343a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # Gradle files .gradle/ +.kotlin/ build/ # Local configuration file (sdk path, etc) diff --git a/.kotlin-js-store/yarn.lock b/.kotlin-js-store/yarn.lock index a8f39437..5890f9df 100644 --- a/.kotlin-js-store/yarn.lock +++ b/.kotlin-js-store/yarn.lock @@ -288,10 +288,40 @@ js-yaml@4.1.0: dependencies: argparse "^2.0.1" -kmp-tor-resource-tor@408.10.0-SNAPSHOT.0: - version "408.10.0-SNAPSHOT.0" - resolved "https://registry.yarnpkg.com/kmp-tor-resource-tor/-/kmp-tor-resource-tor-408.10.0-SNAPSHOT.0.tgz#83caaf1f03d08ddd5b764fa5aa4c1347aad9f3d6" - integrity sha512-1dRccrHL5Bt7wEiy7j8zt2DPTKPi0yQHaE81IcbppKMpW+++cHo6K5U8WLoezBhERZVP/eXswglTMlSJ53WJDg== +kmp-tor.resource-exec-tor.all@408.12.0: + version "408.12.0" + resolved "https://registry.yarnpkg.com/kmp-tor.resource-exec-tor.all/-/kmp-tor.resource-exec-tor.all-408.12.0.tgz#10c365fb3452ba8f5dd8f5be5a9a68ae8d813d81" + integrity sha512-mproBhkmswFep755NswyxBwQjBu+Trn8eML2oTXq+6z3fdu1n+fPhhnoak1gWJOTIizLpxnvO5hHHmH0ag3cOg== + dependencies: + kmp-tor.resource-exec-tor.linux-android "408.12.0" + kmp-tor.resource-exec-tor.linux-libc "408.12.0" + kmp-tor.resource-exec-tor.macos "408.12.0" + kmp-tor.resource-exec-tor.mingw "408.12.0" + +kmp-tor.resource-exec-tor.linux-android@408.12.0: + version "408.12.0" + resolved "https://registry.yarnpkg.com/kmp-tor.resource-exec-tor.linux-android/-/kmp-tor.resource-exec-tor.linux-android-408.12.0.tgz#55cb915f8976ae53c965b91e1e81338c769814b4" + integrity sha512-T6uSnvpr7woLt86V1rYElLS1t6cVX4Uzvq2K3twlScI9WvrKNk+8579eLB63uYIRmT8XG+65mqp2uZqy4rIiNg== + +kmp-tor.resource-exec-tor.linux-libc@408.12.0: + version "408.12.0" + resolved "https://registry.yarnpkg.com/kmp-tor.resource-exec-tor.linux-libc/-/kmp-tor.resource-exec-tor.linux-libc-408.12.0.tgz#174247250eec49b94ff53d23328c0be823cd1fc2" + integrity sha512-bhRQAK/+z9xtyeKWdVNdcLbothr4qRyhAcTsuJEVhS1rMUo0nfQ+ScbJUoE4LDDXQCg0kiZE3qPK6qZxk1DuCw== + +kmp-tor.resource-exec-tor.macos@408.12.0: + version "408.12.0" + resolved "https://registry.yarnpkg.com/kmp-tor.resource-exec-tor.macos/-/kmp-tor.resource-exec-tor.macos-408.12.0.tgz#bdddb7add33af2763da87940a4f234cc42d828a1" + integrity sha512-q45vZwiii9Yu6ql80YezM6E82HSD8Og9vUvGNP+oIr97wnHe6WoAxOk9oaSMMOExi0ZkQG6YXntqfcJS5hj4KQ== + +kmp-tor.resource-exec-tor.mingw@408.12.0: + version "408.12.0" + resolved "https://registry.yarnpkg.com/kmp-tor.resource-exec-tor.mingw/-/kmp-tor.resource-exec-tor.mingw-408.12.0.tgz#5ad4fb58eddcb71207e1ab4b052f9b7b1f8bdc45" + integrity sha512-ycvSEwG7snWCOtfC2jU6mP3n1mTpqFTOyiNjs1FlwYhZRiSDWE+bR0DgZdyRDkwKPlyLioQGbl/x5zjBnS0acw== + +kmp-tor.resource-geoip@408.12.0: + version "408.12.0" + resolved "https://registry.yarnpkg.com/kmp-tor.resource-geoip/-/kmp-tor.resource-geoip-408.12.0.tgz#02c15bb53a174658add7b38dea5d45731535cfbd" + integrity sha512-Sg/mmEo58a6oNo9+W1ygDyIS8KH+1JXTv78Wiyed7D8gIQx4Bn2QXC7jpSH6pN69/OG/CBC7YMRDXTpdACczEA== locate-path@^6.0.0: version "6.0.0" diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts index 0234fcf7..d9f4ef45 100644 --- a/build-logic/build.gradle.kts +++ b/build-logic/build.gradle.kts @@ -23,6 +23,9 @@ dependencies { implementation(libs.gradle.kotlin) implementation(libs.gradle.publish.maven) + // iOS simulator targets need to utilize the macOS executables, so... + implementation(libs.kmp.tor.resource.exec.tor) + // https://github.com/gradle/gradle/issues/15383#issuecomment-779893192 implementation(files(libs.javaClass.superclass.protectionDomain.codeSource.location)) } diff --git a/build.gradle.kts b/build.gradle.kts index da3ae26c..1b8f4a19 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -30,7 +30,13 @@ allprojects { repositories { mavenCentral() - maven("https://s01.oss.sonatype.org/content/repositories/snapshots") + + if (version.toString().endsWith("-SNAPSHOT")) { + // Only allow snapshot dependencies for non-release versions. + // This would cause a build failure if attempting to make a release + // while depending on a -SNAPSHOT version (such as core). + maven("https://s01.oss.sonatype.org/content/repositories/snapshots/") + } } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5a035057..ff76cf21 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,7 +14,7 @@ kotlinx-coroutines = "1.8.1" # tests androidx-test-core = "1.5.0" androidx-test-runner = "1.5.2" -kmp-tor-resource = "408.10.0-SNAPSHOT" +kmp-tor-resource = "408.12.0" [libraries] gradle-android = { module = "com.android.tools.build:gradle", version.ref = "gradle-android" } @@ -31,7 +31,8 @@ kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-c # tests androidx-test-core = { module = "androidx.test:core", version.ref = "androidx-test-core" } androidx-test-runner = { module = "androidx.test:runner", version.ref = "androidx-test-runner" } -kmp-tor-resource-tor = { module = "io.matthewnelson.kmp-tor:resource-tor", version.ref = "kmp-tor-resource" } +kmp-tor-resource-android-unit-test-tor = { module = "io.matthewnelson.kmp-tor:resource-android-unit-test-tor", version.ref = "kmp-tor-resource" } +kmp-tor-resource-exec-tor = { module = "io.matthewnelson.kmp-tor:resource-exec-tor", version.ref = "kmp-tor-resource" } kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinx-coroutines" } [plugins] diff --git a/library/process-testing/build.gradle.kts b/library/process-testing/build.gradle.kts index fd7070d1..f9962761 100644 --- a/library/process-testing/build.gradle.kts +++ b/library/process-testing/build.gradle.kts @@ -1,3 +1,8 @@ +import io.matthewnelson.kmp.tor.common.api.GeoipFiles +import io.matthewnelson.kmp.tor.common.api.ResourceLoader +import io.matthewnelson.kmp.tor.resource.exec.tor.ResourceLoaderTorExec +import org.jetbrains.kotlin.konan.target.HostManager + /* * Copyright (c) 2024 Matthew Nelson * @@ -47,6 +52,19 @@ kmpConfiguration { implementation(libs.androidx.test.runner) } } + sourceSetTest { + dependencies { + implementation(libs.kmp.tor.resource.android.unit.test.tor) + } + } + } + + js { + sourceSetTest { + dependencies { + implementation(npm("kmp-tor.resource-exec-tor.all", libs.versions.kmp.tor.resource.get())) + } + } } common { @@ -58,10 +76,59 @@ kmpConfiguration { sourceSetTest { dependencies { - implementation(libs.kmp.tor.resource.tor) + implementation(libs.kmp.tor.resource.exec.tor) implementation(libs.kotlinx.coroutines.test) } } } + + kotlin { + val iosTest = sourceSets.findByName("iosTest") ?: return@kotlin + + val buildDir = project + .layout + .buildDirectory + .asFile + .get() + + var files: Pair? = null + + // Only extract resources when on macOS machine (ios simulator targets are enabled) + if (HostManager.hostIsMac) { + val resourceDir = buildDir + .resolve("kmp-tor-resource") + .resolve("macos") + + val loader = ResourceLoaderTorExec.getOrCreate(resourceDir) as ResourceLoader.Tor.Exec + files = loader.extract() to loader.process(BINDER) { tor, _ -> tor } + } + + val kotlinSrc = buildDir + .resolve("generated") + .resolve("sources") + .resolve("testConfig") + .resolve("iosTest") + .resolve("kotlin") + + val pkgDir = kotlinSrc.resolve("io") + .resolve("matthewnelson") + .resolve("kmp") + .resolve(project.name.replace('-', File.separatorChar)) + + pkgDir.mkdirs() + + pkgDir.resolve("TestIosConfig.kt").writeText(""" + package io.matthewnelson.kmp.${project.name.replace('-', '.')} + + internal const val IOS_TOR_EXECUTABLE: String = "${files?.second?.path ?: ""}" + internal const val IOS_TOR_GEOIP: String = "${files?.first?.geoip?.path ?: ""}" + internal const val IOS_TOR_GEOIP6: String = "${files?.first?.geoip6?.path ?: ""}" + + """.trimIndent()) + + iosTest.kotlin.srcDir(kotlinSrc) + } } } + +private object BINDER: ResourceLoader.RuntimeBinder diff --git a/library/process-testing/src/androidMain/AndroidManifest.xml b/library/process-testing/src/androidMain/AndroidManifest.xml index 71bba7d9..6ada8a8b 100644 --- a/library/process-testing/src/androidMain/AndroidManifest.xml +++ b/library/process-testing/src/androidMain/AndroidManifest.xml @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. *--> - + - + + + diff --git a/library/process-testing/src/androidUnitTest/kotlin/io/matthewnelson/kmp/process/testing/ProcessAndroidUnitTest.kt b/library/process-testing/src/androidUnitTest/kotlin/io/matthewnelson/kmp/process/testing/ProcessAndroidUnitTest.kt new file mode 100644 index 00000000..697b0806 --- /dev/null +++ b/library/process-testing/src/androidUnitTest/kotlin/io/matthewnelson/kmp/process/testing/ProcessAndroidUnitTest.kt @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2024 Matthew Nelson + * + * 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 + * + * https://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 io.matthewnelson.kmp.process.testing + +class ProcessAndroidUnitTest: ProcessBaseTest() diff --git a/library/process-testing/src/commonTest/kotlin/io/matthewnelson/kmp/process/testing/CommonTestPlatform.kt b/library/process-testing/src/commonTest/kotlin/io/matthewnelson/kmp/process/testing/CommonTestPlatform.kt index 5114ddfa..3fb54c7f 100644 --- a/library/process-testing/src/commonTest/kotlin/io/matthewnelson/kmp/process/testing/CommonTestPlatform.kt +++ b/library/process-testing/src/commonTest/kotlin/io/matthewnelson/kmp/process/testing/CommonTestPlatform.kt @@ -15,11 +15,28 @@ **/ package io.matthewnelson.kmp.process.testing +import io.matthewnelson.kmp.file.File +import io.matthewnelson.kmp.file.SysTempDir import io.matthewnelson.kmp.file.path +import io.matthewnelson.kmp.file.resolve import io.matthewnelson.kmp.process.Stdio +import io.matthewnelson.kmp.tor.common.api.ResourceLoader internal val IsWindows = Stdio.Null.file.path == "NUL" internal expect val IsDarwinMobile: Boolean internal expect val IsNodeJs: Boolean + +internal expect val LOADER: ResourceLoader.Tor.Exec + +internal object TorResourceBinder: ResourceLoader.RuntimeBinder { + + internal val RESOURCE_DIR: File by lazy { + + // This is OK for Android Runtime, as only geoip files will be installed + // to the Context.cacheDir/kmp_process. libtor.so is extracted to the + // Context.applicationInfo.nativeLibraryDir automatically, so. + SysTempDir.resolve("kmp_process") + } +} diff --git a/library/process-testing/src/commonTest/kotlin/io/matthewnelson/kmp/process/testing/ProcessBaseTest.kt b/library/process-testing/src/commonTest/kotlin/io/matthewnelson/kmp/process/testing/ProcessBaseTest.kt index 1fc5ac97..66a72c39 100644 --- a/library/process-testing/src/commonTest/kotlin/io/matthewnelson/kmp/process/testing/ProcessBaseTest.kt +++ b/library/process-testing/src/commonTest/kotlin/io/matthewnelson/kmp/process/testing/ProcessBaseTest.kt @@ -22,8 +22,7 @@ import io.matthewnelson.kmp.process.Process import io.matthewnelson.kmp.process.ProcessException.Companion.CTX_FEED_STDOUT import io.matthewnelson.kmp.process.Signal import io.matthewnelson.kmp.process.Stdio -import io.matthewnelson.kmp.tor.core.api.ResourceInstaller -import io.matthewnelson.kmp.tor.resource.tor.TorResources +import io.matthewnelson.kmp.tor.common.api.ResourceLoader import kotlinx.coroutines.* import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest @@ -35,17 +34,8 @@ import kotlin.time.Duration.Companion.seconds abstract class ProcessBaseTest { - private companion object { - // This is OK for Android Runtime, as only geoip files will be installed - // to the Context.cacheDir/kmp_process. libtor.so is extracted to the - // Context.applicationInfo.nativeLibraryDir automatically, so. - private val installer by lazy { - TorResources(installationDir = SysTempDir.resolve("kmp_process")) - } - } - protected open val IsAndroidInstrumentTest: Boolean = false - protected open val homeDir get() = installer.installationDir + protected open val homeDir get() = LOADER.resourceDir protected open val cacheDir get() = homeDir.resolve("cache") protected open val dataDir get() = homeDir.resolve("data") @@ -255,6 +245,8 @@ abstract class ProcessBaseTest { throw IllegalStateException(line) }.waitForAsync(500.milliseconds) + delayTest(100.milliseconds) + assertTrue(invocationError > 0) if (!shouldThrow) { @@ -372,7 +364,7 @@ abstract class ProcessBaseTest { assertFalse(stdoutFile.exists()) assertFalse(stderrFile.exists()) - installer.install().toProcessBuilder() + LOADER.toProcessBuilder() .stdout(Stdio.File.of(stdoutFile, append = true)) .stderr(Stdio.File.of(stderrFile)) .spawn { p -> @@ -398,7 +390,7 @@ abstract class ProcessBaseTest { @Test open fun givenExecutable_whenOutput_thenIsAsExpected() = runTest(timeout = 25.seconds) { - val out = installer.install().toProcessBuilder() + val out = LOADER.toProcessBuilder() .output { timeoutMillis = 2_000 } println(out) @@ -413,7 +405,7 @@ abstract class ProcessBaseTest { @Test open fun givenExecutable_whenPipeOutputFeeds_thenIsAsExpected() = runTest(timeout = 25.seconds) { - installer.install().toProcessBuilder().spawn { p -> + LOADER.toProcessBuilder().spawn { p -> val stdoutBuilder = StringBuilder() val stderrBuilder = StringBuilder() @@ -478,31 +470,36 @@ abstract class ProcessBaseTest { private fun Process.Builder.envHome(): Process.Builder = environment("HOME", homeDir.path) - private fun ResourceInstaller.Paths.Tor.toProcessBuilder(): Process.Builder { - val b = Process.Builder(executable = tor) - .args("--DataDirectory") - .args(dataDir.also { it.mkdirs() }.path) - .args("--CacheDirectory") - .args(cacheDir.also { it.mkdirs() }.path) - .args("--GeoIPFile") - .args(geoip.path) - .args("--GeoIPv6File") - .args(geoip6.path) - .args("--DormantCanceledByStartup") - .args("1") - .args("--SocksPort") - .args("auto") - .args("--DisableNetwork") - .args("1") - .args("--RunAsDaemon") - .args("0") - .args("--__OwningControllerProcess") - .args(Process.Current.pid().toString()) - .destroySignal(Signal.SIGTERM) - .envHome() - .stdin(Stdio.Null) - .stdout(Stdio.Pipe) - .stderr(Stdio.Pipe) + private fun ResourceLoader.Tor.Exec.toProcessBuilder(): Process.Builder { + val geoipFiles = extract() + + val b = process(TorResourceBinder) { tor, configureEnv -> + Process.Builder(executable = tor) + .args("--DataDirectory") + .args(dataDir.also { it.mkdirs() }.path) + .args("--CacheDirectory") + .args(cacheDir.also { it.mkdirs() }.path) + .args("--GeoIPFile") + .args(geoipFiles.geoip.path) + .args("--GeoIPv6File") + .args(geoipFiles.geoip6.path) + .args("--DormantCanceledByStartup") + .args("1") + .args("--SocksPort") + .args("auto") + .args("--DisableNetwork") + .args("1") + .args("--RunAsDaemon") + .args("0") + .args("--__OwningControllerProcess") + .args(Process.Current.pid().toString()) + .destroySignal(Signal.SIGTERM) + .envHome() + .environment(configureEnv) + .stdin(Stdio.Null) + .stdout(Stdio.Pipe) + .stderr(Stdio.Pipe) + } if (!IsDarwinMobile) { b.chdir(homeDir) diff --git a/library/process-testing/src/iosTest/kotlin/io/matthewnelson/kmp/process/testing/IosTestPlatform.kt b/library/process-testing/src/iosTest/kotlin/io/matthewnelson/kmp/process/testing/IosTestPlatform.kt new file mode 100644 index 00000000..497b5f20 --- /dev/null +++ b/library/process-testing/src/iosTest/kotlin/io/matthewnelson/kmp/process/testing/IosTestPlatform.kt @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2024 Matthew Nelson + * + * 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 + * + * https://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 io.matthewnelson.kmp.process.testing + +import io.matthewnelson.kmp.file.toFile +import io.matthewnelson.kmp.tor.common.api.GeoipFiles +import io.matthewnelson.kmp.tor.common.api.ResourceLoader + +internal actual val LOADER: ResourceLoader.Tor.Exec by lazy { + IosTestLoader.getOrCreate() as ResourceLoader.Tor.Exec +} + +// Need to mock executable files for ios simulator tests to use macOS +// compilations of tor. +private class IosTestLoader private constructor(): ResourceLoader.Tor.Exec() { + companion object { + fun getOrCreate(): Tor = getOrCreate( + resourceDir = TorResourceBinder.RESOURCE_DIR, + extract = { + check(IOS_TOR_GEOIP.isNotBlank()) { "geoip file does not exist" } + check(IOS_TOR_GEOIP6.isNotBlank()) { "geoip6 file does not exist" } + + val files = GeoipFiles(IOS_TOR_GEOIP.toFile(), IOS_TOR_GEOIP6.toFile()) + check(files.geoip.exists()) { "geoip file does not exist" } + check(files.geoip6.exists()) { "geoip6 file does not exist" } + + files + }, + extractTor = { + check(IOS_TOR_EXECUTABLE.isNotBlank()) { "tor executable file does not exist" } + + val file = IOS_TOR_EXECUTABLE.toFile() + check(file.exists()) { "tor executable file does not exist" } + + file + }, + configureEnv = { /* no-op */ }, + toString = { "IosTestLoader" }, + ) + } +} diff --git a/library/process-testing/src/jsTest/kotlin/io/matthewnelson/kmp/process/testing/JsTestPlatform.kt b/library/process-testing/src/jsTest/kotlin/io/matthewnelson/kmp/process/testing/JsTestPlatform.kt index 132cece6..055e7c8a 100644 --- a/library/process-testing/src/jsTest/kotlin/io/matthewnelson/kmp/process/testing/JsTestPlatform.kt +++ b/library/process-testing/src/jsTest/kotlin/io/matthewnelson/kmp/process/testing/JsTestPlatform.kt @@ -15,6 +15,13 @@ **/ package io.matthewnelson.kmp.process.testing +import io.matthewnelson.kmp.tor.common.api.ResourceLoader +import io.matthewnelson.kmp.tor.resource.exec.tor.ResourceLoaderTorExec + internal actual val IsDarwinMobile: Boolean = false internal actual val IsNodeJs: Boolean = true + +internal actual val LOADER: ResourceLoader.Tor.Exec by lazy { + ResourceLoaderTorExec.getOrCreate(TorResourceBinder.RESOURCE_DIR) as ResourceLoader.Tor.Exec +} diff --git a/library/process-testing/src/jvmAndroidTest/kotlin/io/matthewnelson/kmp/process/testing/JvmAndroidTestPlatform.kt b/library/process-testing/src/jvmAndroidTest/kotlin/io/matthewnelson/kmp/process/testing/JvmAndroidTestPlatform.kt index c1baca5f..7e6d5704 100644 --- a/library/process-testing/src/jvmAndroidTest/kotlin/io/matthewnelson/kmp/process/testing/JvmAndroidTestPlatform.kt +++ b/library/process-testing/src/jvmAndroidTest/kotlin/io/matthewnelson/kmp/process/testing/JvmAndroidTestPlatform.kt @@ -15,6 +15,13 @@ **/ package io.matthewnelson.kmp.process.testing +import io.matthewnelson.kmp.tor.common.api.ResourceLoader +import io.matthewnelson.kmp.tor.resource.exec.tor.ResourceLoaderTorExec + internal actual val IsDarwinMobile: Boolean = false internal actual val IsNodeJs: Boolean = false + +internal actual val LOADER: ResourceLoader.Tor.Exec by lazy { + ResourceLoaderTorExec.getOrCreate(TorResourceBinder.RESOURCE_DIR) as ResourceLoader.Tor.Exec +} diff --git a/library/process-testing/src/linuxTest/kotlin/io/matthewnelson/kmp/process/testing/LinuxTestPlatform.kt b/library/process-testing/src/linuxTest/kotlin/io/matthewnelson/kmp/process/testing/LinuxTestPlatform.kt new file mode 100644 index 00000000..88542095 --- /dev/null +++ b/library/process-testing/src/linuxTest/kotlin/io/matthewnelson/kmp/process/testing/LinuxTestPlatform.kt @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2024 Matthew Nelson + * + * 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 + * + * https://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 io.matthewnelson.kmp.process.testing + +import io.matthewnelson.kmp.tor.common.api.ResourceLoader +import io.matthewnelson.kmp.tor.resource.exec.tor.ResourceLoaderTorExec + +internal actual val LOADER: ResourceLoader.Tor.Exec by lazy { + ResourceLoaderTorExec.getOrCreate(TorResourceBinder.RESOURCE_DIR) as ResourceLoader.Tor.Exec +} diff --git a/library/process-testing/src/macosTest/kotlin/io/matthewnelson/kmp/process/testing/MacosTestPlatform.kt b/library/process-testing/src/macosTest/kotlin/io/matthewnelson/kmp/process/testing/MacosTestPlatform.kt new file mode 100644 index 00000000..88542095 --- /dev/null +++ b/library/process-testing/src/macosTest/kotlin/io/matthewnelson/kmp/process/testing/MacosTestPlatform.kt @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2024 Matthew Nelson + * + * 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 + * + * https://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 io.matthewnelson.kmp.process.testing + +import io.matthewnelson.kmp.tor.common.api.ResourceLoader +import io.matthewnelson.kmp.tor.resource.exec.tor.ResourceLoaderTorExec + +internal actual val LOADER: ResourceLoader.Tor.Exec by lazy { + ResourceLoaderTorExec.getOrCreate(TorResourceBinder.RESOURCE_DIR) as ResourceLoader.Tor.Exec +}